refactor: streamline OAuth2 consent screens#3089
Conversation
Group permissions into a single bordered list with hairline dividers instead of separate tinted icon tiles, surface the signed-in account as a chip under the heading, render authorization details as compact tags, and collapse the footer into one line. Drop hardcoded color fallbacks in favor of design tokens.
Console (appwrite/console)Project ID: Tip Our Discord community has grown to 24K developers, and counting |
Greptile SummaryThis PR redesigns the OAuth2 consent screen with a cleaner grouped-scope layout, removes ~30 hardcoded hex color fallbacks in favour of design tokens, and adds a dedicated Account → Applications tab that surfaces console OAuth2 grants (e.g. the Appwrite CLI device flow) separately from browser sessions and sign-in identities.
Confidence Score: 4/5Safe to merge after fixing the oauth2 prefix string in the Sessions filter — everything else is well-implemented. The sessions filter uses 'oauth2' (no colon) while every other callsite — identities.svelte, applications/+page.ts, and the defined OAUTH2_PREFIX constant — uses 'oauth2:'. In practice Appwrite social providers don't use the oauth2 prefix, so no sessions are wrongly hidden today, but the divergence from the established constant means any future provider whose name begins with oauth2 would be silently excluded from the Sessions tab without an obvious reason. src/routes/(console)/account/sessions/+page.svelte — the provider prefix string in the visibleSessions filter should use 'oauth2:' to match the constant and the other two filter sites. Important Files Changed
Reviews (4): Last reviewed commit: "refactor: move authorized OAuth apps to ..." | Re-trigger Greptile |
Fall back to the 'Verify your identity' row when openid is the only requested scope, and guard the permission list so it never renders an empty bordered container. Document that the list mirrors the server's scope-based access enforcement.
List apps the user authorized through the console OAuth2 server (e.g. the Appwrite CLI via the device flow) in a 'Connected applications' section. These are stored as oauth2:<appId> identities rather than sessions, so they're fetched via listIdentities and revocable with deleteIdentity.
Replace the sessions-page 'Connected applications' section with a proper Account > Applications tab. It resolves each oauth2:<appId> identity grant to its app metadata via apps.get() and renders the name, logo, tagline, and a device-flow badge, with a Revoke action. Also: filter oauth2 grants out of the Sessions tab and the Overview Identities list so each surface owns one concept.

What
Redesigns the OAuth2 consent screen (shared by both the authorization and device flows) to be cleaner and more in line with familiar consent UIs, without dropping any information the user needs to make a decision.
Also includes a small correctness fix: the Full access to your account item now appears only when the app actually requests the
account.adminscope, instead of always being shown.Why
The previous screen felt busy: every scope sat in its own tinted icon tile (a noisy grid), each row repeated a description, rich authorization details were a second boxed list, and the footer stacked two-to-three separate lines. It was also full of hardcoded color fallbacks that didn't track the theme.
Changes
account.adminrow leads and is emphasized.profile/emailone-liners.Authorization flow
Device flow
Adapts to requested scopes
When an app doesn't request
account.admin, the full-access row is omitted entirely:Testing
bun run format·bun run check(0 errors) ·bun run lint(0 errors)Screenshots are hosted on the throwaway
pr-assets/oauth2-consent-redesignbranch; safe to delete after merge.Account → Applications tab
The Appwrite CLI (and any app authorized through the console OAuth2 server) signs in via the device flow, stored as an
oauth2:<appId>identity grant — not a session, and with no session↔app link. Rather than mixing it into Sessions, this adds a dedicated Account → Applications tab that resolves each grant to its app metadata viaapps.get()(name, logo, tagline, device-flow badge) with a Revoke action.To keep each surface single-purpose,
oauth2grants are also filtered out of the Sessions tab and the Overview Identities list.