a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky
atproto bluesky typescript npm
101
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(oauth-types): support prompt_values_supported

though worth mentioning that only node-client checks for prompt_values_supported, browser-client does not

fixes https://github.com/mary-ext/atcute/issues/53

Mary 390b0883 debc9dfe

+39 -4
+2 -2
packages/oauth/browser-client/lib/agents/exchange.ts
··· 1 1 import { nanoid } from 'nanoid'; 2 2 3 3 import type { ActorIdentifier } from '@atcute/lexicons'; 4 - import type { OAuthAuthorizationServerMetadata } from '@atcute/oauth-types'; 4 + import type { OAuthAuthorizationServerMetadata, OAuthPrompt } from '@atcute/oauth-types'; 5 5 6 6 import { createES256Key } from '../dpop.js'; 7 7 import { CLIENT_ID, database, REDIRECT_URI } from '../environment.js'; ··· 22 22 target: AuthorizeTargetOptions; 23 23 scope: string; 24 24 state?: unknown; 25 - prompt?: 'none' | 'login' | 'consent' | 'select_account'; 25 + prompt?: OAuthPrompt | (string & {}); 26 26 display?: 'page' | 'popup' | 'touch' | 'wap'; 27 27 locale?: string; 28 28 }
+12 -1
packages/oauth/node-client/lib/oauth-client.ts
··· 8 8 FALLBACK_ALG, 9 9 type ConfidentialClientMetadata, 10 10 type OAuthClientMetadata, 11 + type OAuthPrompt, 11 12 type OAuthResponseMode, 12 13 } from '@atcute/oauth-types'; 13 14 import { Keyset, type PrivateKey } from '@atcute/oauth-keyset'; ··· 80 81 /** user-provided state to preserve through flow */ 81 82 state?: unknown; 82 83 /** OIDC prompt parameter */ 83 - prompt?: 'none' | 'login' | 'consent' | 'select_account'; 84 + prompt?: OAuthPrompt | (string & {}); 84 85 /** abort signal */ 85 86 signal?: AbortSignal; 86 87 } ··· 247 248 const { identity, metadata } = resolved; 248 249 249 250 signal?.throwIfAborted(); 251 + 252 + // validate prompt if server advertises supported values 253 + if (prompt) { 254 + const supported = metadata.prompt_values_supported; 255 + if (supported && !supported.includes(prompt)) { 256 + throw new TypeError( 257 + `prompt "${prompt}" not supported by server (supported: ${supported.join(', ')})`, 258 + ); 259 + } 260 + } 250 261 251 262 // generate PKCE and DPoP key 252 263 const pkce = await generatePkce();
+1
packages/oauth/types/lib/index.ts
··· 77 77 type OAuthCodeChallengeMethod, 78 78 } from './schemas/oauth-code-challenge-method.js'; 79 79 export { oauthResponseModeSchema, type OAuthResponseMode } from './schemas/oauth-response-mode.js'; 80 + export { oauthPromptSchema, type OAuthPrompt } from './schemas/oauth-prompt.js'; 80 81 81 82 // authorization details 82 83 export {
+2
packages/oauth/types/lib/schemas/oauth-authorization-server-metadata.ts
··· 2 2 3 3 import { oauthCodeChallengeMethodSchema } from './oauth-code-challenge-method.js'; 4 4 import { oauthIssuerIdentifierSchema } from './oauth-issuer-identifier.js'; 5 + import { oauthPromptSchema } from './oauth-prompt.js'; 5 6 import { webUriSchema } from './uri.js'; 6 7 7 8 /** ··· 25 26 ui_locales_supported: v.array(v.string()).optional(), 26 27 id_token_signing_alg_values_supported: v.array(v.string()).optional(), 27 28 display_values_supported: v.array(v.string()).optional(), 29 + prompt_values_supported: v.array(oauthPromptSchema).optional(), 28 30 request_object_signing_alg_values_supported: v.array(v.string()).optional(), 29 31 authorization_response_iss_parameter_supported: v.boolean().optional(), 30 32 authorization_details_types_supported: v.array(v.string()).optional(),
+20
packages/oauth/types/lib/schemas/oauth-prompt.ts
··· 1 + import * as v from '@badrap/valita'; 2 + 3 + /** 4 + * OAuth prompt mode values. 5 + * 6 + * - `none`: only succeed if user already authorized this client on this device 7 + * - `login`: force re-authentication 8 + * - `consent`: force re-consent 9 + * - `select_account`: force account selection 10 + * - `create`: force user registration screen 11 + */ 12 + export const oauthPromptSchema = v.union( 13 + v.literal('none'), 14 + v.literal('login'), 15 + v.literal('consent'), 16 + v.literal('select_account'), 17 + v.literal('create'), 18 + ); 19 + 20 + export type OAuthPrompt = v.Infer<typeof oauthPromptSchema>;
+2 -1
packages/oauth/types/package.json
··· 22 22 }, 23 23 "sideEffects": false, 24 24 "scripts": { 25 - "build": "tsgo --project tsconfig.build.json", 25 + "build": "tsc --project tsconfig.build.json", 26 26 "test": "vitest", 27 27 "prepublish": "rm -rf dist; pnpm run build" 28 28 }, 29 29 "dependencies": { 30 30 "@atcute/identity": "workspace:^", 31 + "@atcute/lexicons": "workspace:^", 31 32 "@atcute/oauth-keyset": "workspace:^", 32 33 "@badrap/valita": "^0.4.6" 33 34 },