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.

refactor(oauth-browser-client): use oauth-types package

Mary 29b911e9 af4ac7fe

+39 -186
+5
.changeset/rare-banks-design.md
··· 1 + --- 2 + '@atcute/oauth-browser-client': patch 3 + --- 4 + 5 + make use of @atcute/oauth-types
+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 5 5 6 import { createES256Key } from '../dpop.js'; 6 7 import { CLIENT_ID, database, REDIRECT_URI } from '../environment.js'; 7 8 import { AuthorizationError, LoginError } from '../errors.js'; 8 9 import type { ResolvedIdentity } from '../types/identity.js'; 9 - import type { AuthorizationServerMetadata } from '../types/server.js'; 10 10 import type { Session } from '../types/token.js'; 11 11 import { generatePKCE } from '../utils/runtime.js'; 12 12 ··· 35 35 export const createAuthorizationUrl = async (options: AuthorizeOptions): Promise<URL> => { 36 36 const { target, scope, state = null, ...reqs } = options; 37 37 38 - let resolved: { identity?: ResolvedIdentity; metadata: AuthorizationServerMetadata }; 38 + let resolved: { identity?: ResolvedIdentity; metadata: OAuthAuthorizationServerMetadata }; 39 39 switch (target.type) { 40 40 case 'account': { 41 41 resolved = await resolveFromIdentifier(target.identifier);
+7 -5
packages/oauth/browser-client/lib/agents/server-agent.ts
··· 1 1 import type { Did } from '@atcute/lexicons'; 2 + import type { AtprotoOAuthTokenResponse, OAuthParResponse } from '@atcute/oauth-types'; 2 3 3 4 import { createDPoPFetch, createDPoPSignage } from '../dpop.js'; 4 5 import { CLIENT_ID, fetchClientAssertion, REDIRECT_URI } from '../environment.js'; 5 6 import { FetchResponseError, OAuthResponseError, TokenRefreshError } from '../errors.js'; 6 7 import { resolveFromIdentifier } from '../resolvers.js'; 7 8 import type { DPoPKey } from '../types/dpop.js'; 8 - import type { OAuthParResponse } from '../types/par.js'; 9 9 import type { PersistedAuthorizationServerMetadata } from '../types/server.js'; 10 - import type { ExchangeInfo, OAuthTokenResponse, TokenInfo } from '../types/token.js'; 10 + import type { ExchangeInfo, TokenInfo } from '../types/token.js'; 11 11 import { pick } from '../utils/misc.js'; 12 12 import { extractContentType } from '../utils/response.js'; 13 13 ··· 26 26 endpoint: 'pushed_authorization_request', 27 27 payload: Record<string, unknown>, 28 28 ): Promise<OAuthParResponse>; 29 - async request(endpoint: 'token', payload: Record<string, unknown>): Promise<OAuthTokenResponse>; 29 + async request(endpoint: 'token', payload: Record<string, unknown>): Promise<AtprotoOAuthTokenResponse>; 30 30 async request(endpoint: 'revocation', payload: Record<string, unknown>): Promise<any>; 31 31 async request(endpoint: 'introspection', payload: Record<string, unknown>): Promise<any>; 32 32 async request(endpoint: string, payload: Record<string, unknown>): Promise<any> { ··· 120 120 } 121 121 } 122 122 123 - #processTokenResponse(res: OAuthTokenResponse): TokenInfo { 123 + #processTokenResponse(res: AtprotoOAuthTokenResponse): TokenInfo { 124 124 if (!res.sub) { 125 125 throw new TypeError(`missing sub field in token response`); 126 126 } ··· 140 140 }; 141 141 } 142 142 143 - async #processExchangeResponse(res: OAuthTokenResponse): Promise<{ info: ExchangeInfo; token: TokenInfo }> { 143 + async #processExchangeResponse( 144 + res: AtprotoOAuthTokenResponse, 145 + ): Promise<{ info: ExchangeInfo; token: TokenInfo }> { 144 146 const sub = res.sub; 145 147 if (!sub) { 146 148 throw new TypeError(`missing sub field in token response`);
+8 -2
packages/oauth/browser-client/lib/index.ts
··· 7 7 export * from './agents/sessions.js'; 8 8 export * from './agents/user-agent.js'; 9 9 10 + export type { 11 + AtprotoOAuthTokenResponse as OAuthTokenResponse, 12 + OAuthAuthorizationServerMetadata as AuthorizationServerMetadata, 13 + OAuthClientMetadata as ClientMetadata, 14 + OAuthParResponse, 15 + OAuthProtectedResourceMetadata as ProtectedResourceMetadata, 16 + } from '@atcute/oauth-types'; 17 + 10 18 export * from './types/client-assertion.js'; 11 - export * from './types/client.js'; 12 19 export * from './types/dpop.js'; 13 20 export * from './types/identity.js'; 14 - export * from './types/par.js'; 15 21 export * from './types/server.js'; 16 22 export * from './types/store.js'; 17 23 export * from './types/token.js';
+12 -10
packages/oauth/browser-client/lib/resolvers.ts
··· 1 1 import type { ActorIdentifier } from '@atcute/lexicons'; 2 + import type { OAuthAuthorizationServerMetadata, OAuthProtectedResourceMetadata } from '@atcute/oauth-types'; 2 3 3 4 import { identityResolver } from './environment.js'; 4 5 import { ResolverError } from './errors.js'; 5 6 import type { ResolvedIdentity } from './types/identity.js'; 6 - import type { AuthorizationServerMetadata, ProtectedResourceMetadata } from './types/server.js'; 7 7 import { extractContentType } from './utils/response.js'; 8 8 import { isValidUrl } from './utils/strings.js'; 9 9 10 10 export const resolveFromIdentifier = async ( 11 11 ident: ActorIdentifier, 12 - ): Promise<{ identity: ResolvedIdentity; metadata: AuthorizationServerMetadata }> => { 12 + ): Promise<{ identity: ResolvedIdentity; metadata: OAuthAuthorizationServerMetadata }> => { 13 13 const identity = await identityResolver.resolve(ident); 14 14 15 15 return { ··· 20 20 21 21 export const resolveFromService = async ( 22 22 host: string, 23 - ): Promise<{ metadata: AuthorizationServerMetadata }> => { 23 + ): Promise<{ metadata: OAuthAuthorizationServerMetadata }> => { 24 24 try { 25 25 const metadata = await getMetadataFromResourceServer(host); 26 26 return { metadata }; 27 27 } catch (err) { 28 28 if (err instanceof ResolverError) { 29 29 try { 30 - const metadata = await getAuthorizationServerMetadata(host); 30 + const metadata = await getOAuthAuthorizationServerMetadata(host); 31 31 return { metadata }; 32 32 } catch {} 33 33 } ··· 36 36 } 37 37 }; 38 38 39 - const getProtectedResourceMetadata = async (host: string): Promise<ProtectedResourceMetadata> => { 39 + const getOAuthProtectedResourceMetadata = async (host: string): Promise<OAuthProtectedResourceMetadata> => { 40 40 const url = new URL(`/.well-known/oauth-protected-resource`, host); 41 41 const response = await fetch(url.href, { 42 42 redirect: 'manual', ··· 49 49 throw new ResolverError(`unexpected response`); 50 50 } 51 51 52 - const metadata = (await response.json()) as ProtectedResourceMetadata; 52 + const metadata = (await response.json()) as OAuthProtectedResourceMetadata; 53 53 if (metadata.resource !== url.origin) { 54 54 throw new ResolverError(`unexpected issuer`); 55 55 } ··· 57 57 return metadata; 58 58 }; 59 59 60 - const getAuthorizationServerMetadata = async (host: string): Promise<AuthorizationServerMetadata> => { 60 + const getOAuthAuthorizationServerMetadata = async ( 61 + host: string, 62 + ): Promise<OAuthAuthorizationServerMetadata> => { 61 63 const url = new URL(`/.well-known/oauth-authorization-server`, host); 62 64 const response = await fetch(url.href, { 63 65 redirect: 'manual', ··· 70 72 throw new ResolverError(`unexpected response`); 71 73 } 72 74 73 - const metadata = (await response.json()) as AuthorizationServerMetadata; 75 + const metadata = (await response.json()) as OAuthAuthorizationServerMetadata; 74 76 if (metadata.issuer !== url.origin) { 75 77 throw new ResolverError(`unexpected issuer`); 76 78 } ··· 93 95 }; 94 96 95 97 const getMetadataFromResourceServer = async (input: string) => { 96 - const rs_metadata = await getProtectedResourceMetadata(input); 98 + const rs_metadata = await getOAuthProtectedResourceMetadata(input); 97 99 98 100 if (rs_metadata.authorization_servers?.length !== 1) { 99 101 throw new ResolverError(`expected exactly one authorization server in the listing`); ··· 101 103 102 104 const issuer = rs_metadata.authorization_servers[0]; 103 105 104 - const as_metadata = await getAuthorizationServerMetadata(issuer); 106 + const as_metadata = await getOAuthAuthorizationServerMetadata(issuer); 105 107 106 108 if (as_metadata.protected_resources) { 107 109 if (!as_metadata.protected_resources.includes(rs_metadata.resource)) {
+2 -2
packages/oauth/browser-client/lib/store/db.ts
··· 1 1 import type { Did } from '@atcute/lexicons'; 2 + import type { OAuthAuthorizationServerMetadata } from '@atcute/oauth-types'; 2 3 3 4 import type { DPoPKey } from '../types/dpop.js'; 4 - import type { AuthorizationServerMetadata } from '../types/server.js'; 5 5 import type { SimpleStore } from '../types/store.js'; 6 6 import type { Session } from '../types/token.js'; 7 7 import { locks } from '../utils/runtime.js'; ··· 28 28 key: string; 29 29 value: { 30 30 dpopKey: DPoPKey; 31 - metadata: AuthorizationServerMetadata; 31 + metadata: OAuthAuthorizationServerMetadata; 32 32 verifier?: string; 33 33 state?: unknown; 34 34 };
-82
packages/oauth/browser-client/lib/types/client.ts
··· 1 - export interface ClientMetadata { 2 - redirect_uris: string[]; 3 - response_types: ( 4 - | 'code' 5 - | 'token' 6 - | 'none' 7 - | 'code id_token token' 8 - | 'code id_token' 9 - | 'code token' 10 - | 'id_token token' 11 - | 'id_token' 12 - )[]; 13 - grant_types: ( 14 - | 'authorization_code' 15 - | 'implicit' 16 - | 'refresh_token' 17 - | 'password' 18 - | 'client_credentials' 19 - | 'urn:ietf:params:oauth:grant-type:jwt-bearer' 20 - | 'urn:ietf:params:oauth:grant-type:saml2-bearer' 21 - )[]; 22 - scope?: string; 23 - token_endpoint_auth_method?: 24 - | 'none' 25 - | 'client_secret_basic' 26 - | 'client_secret_jwt' 27 - | 'client_secret_post' 28 - | 'private_key_jwt' 29 - | 'self_signed_tls_client_auth' 30 - | 'tls_client_auth'; 31 - token_endpoint_auth_signing_alg?: string; 32 - introspection_endpoint_auth_method?: 33 - | 'none' 34 - | 'client_secret_basic' 35 - | 'client_secret_jwt' 36 - | 'client_secret_post' 37 - | 'private_key_jwt' 38 - | 'self_signed_tls_client_auth' 39 - | 'tls_client_auth'; 40 - introspection_endpoint_auth_signing_alg?: string; 41 - revocation_endpoint_auth_method?: 42 - | 'none' 43 - | 'client_secret_basic' 44 - | 'client_secret_jwt' 45 - | 'client_secret_post' 46 - | 'private_key_jwt' 47 - | 'self_signed_tls_client_auth' 48 - | 'tls_client_auth'; 49 - revocation_endpoint_auth_signing_alg?: string; 50 - pushed_authorization_request_endpoint_auth_method?: 51 - | 'none' 52 - | 'client_secret_basic' 53 - | 'client_secret_jwt' 54 - | 'client_secret_post' 55 - | 'private_key_jwt' 56 - | 'self_signed_tls_client_auth' 57 - | 'tls_client_auth'; 58 - pushed_authorization_request_endpoint_auth_signing_alg?: string; 59 - userinfo_signed_response_alg?: string; 60 - userinfo_encrypted_response_alg?: string; 61 - jwks_uri?: string; 62 - jwks?: unknown; 63 - application_type?: 'web' | 'native'; 64 - subject_type?: 'public' | 'pairwise'; 65 - request_object_signing_alg?: string; 66 - id_token_signed_response_alg?: string; 67 - authorization_signed_response_alg?: string; 68 - authorization_encrypted_response_enc?: 'A128CBC-HS256'; 69 - authorization_encrypted_response_alg?: string; 70 - client_id?: string; 71 - client_name?: string; 72 - client_uri?: string; 73 - policy_uri?: string; 74 - tos_uri?: string; 75 - logo_uri?: string; 76 - default_max_age?: number; 77 - require_auth_time?: boolean; 78 - contacts?: string[]; 79 - tls_client_certificate_bound_access_tokens?: boolean; 80 - dpop_bound_access_tokens?: boolean; 81 - authorization_details_types?: string[]; 82 - }
-4
packages/oauth/browser-client/lib/types/par.ts
··· 1 - export interface OAuthParResponse { 2 - request_uri: string; 3 - expires_in: number; 4 - }
+2 -57
packages/oauth/browser-client/lib/types/server.ts
··· 1 - export interface ProtectedResourceMetadata { 2 - resource: string; 3 - jwks_uri?: string; 4 - authorization_servers?: string[]; 5 - scopes_supported?: string[]; 6 - bearer_methods_supported?: ('header' | 'body' | 'query')[]; 7 - resource_signing_alg_values_supported?: string[]; 8 - resource_documentation?: string; 9 - resource_policy_uri?: string; 10 - resource_tos_uri?: string; 11 - } 12 - 13 - export interface AuthorizationServerMetadata { 14 - issuer: string; 15 - authorization_endpoint: string; 16 - token_endpoint: string; 17 - jwks_uri?: string; 18 - scopes_supported?: string[]; 19 - claims_supported?: string[]; 20 - claims_locales_supported?: string[]; 21 - claims_parameter_supported?: boolean; 22 - request_parameter_supported?: boolean; 23 - request_uri_parameter_supported?: boolean; 24 - require_request_uri_registration?: boolean; 25 - subject_types_supported?: string[]; 26 - response_types_supported?: string[]; 27 - response_modes_supported?: string[]; 28 - grant_types_supported?: string[]; 29 - code_challenge_methods_supported?: string[]; 30 - ui_locales_supported?: string[]; 31 - id_token_signing_alg_values_supported?: string[]; 32 - display_values_supported?: string[]; 33 - request_object_signing_alg_values_supported?: string[]; 34 - authorization_response_iss_parameter_supported?: boolean; 35 - authorization_details_types_supported?: string[]; 36 - request_object_encryption_alg_values_supported?: string[]; 37 - request_object_encryption_enc_values_supported?: string[]; 38 - token_endpoint_auth_methods_supported?: string[]; 39 - token_endpoint_auth_signing_alg_values_supported?: string[]; 40 - revocation_endpoint?: string; 41 - revocation_endpoint_auth_methods_supported?: string[]; 42 - revocation_endpoint_auth_signing_alg_values_supported?: string[]; 43 - introspection_endpoint?: string; 44 - introspection_endpoint_auth_methods_supported?: string[]; 45 - introspection_endpoint_auth_signing_alg_values_supported?: string[]; 46 - pushed_authorization_request_endpoint?: string; 47 - pushed_authorization_request_endpoint_auth_methods_supported?: string[]; 48 - pushed_authorization_request_endpoint_auth_signing_alg_values_supported?: string[]; 49 - require_pushed_authorization_requests?: boolean; 50 - userinfo_endpoint?: string; 51 - end_session_endpoint?: string; 52 - registration_endpoint?: string; 53 - dpop_signing_alg_values_supported?: string[]; 54 - protected_resources?: string[]; 55 - client_id_metadata_document_supported?: boolean; 56 - } 1 + import type { OAuthAuthorizationServerMetadata } from '@atcute/oauth-types'; 57 2 58 3 export interface PersistedAuthorizationServerMetadata extends Pick< 59 - AuthorizationServerMetadata, 4 + OAuthAuthorizationServerMetadata, 60 5 | 'issuer' 61 6 | 'authorization_endpoint' 62 7 | 'introspection_endpoint'
-22
packages/oauth/browser-client/lib/types/token.ts
··· 3 3 import type { DPoPKey } from './dpop.js'; 4 4 import type { PersistedAuthorizationServerMetadata } from './server.js'; 5 5 6 - export interface OAuthTokenResponse { 7 - access_token: string; 8 - // Can be DPoP or Bearer, normalize casing. 9 - token_type: string; 10 - issuer?: string; 11 - sub?: string; 12 - scope?: string; 13 - id_token?: `${string}.${string}.${string}`; 14 - refresh_token?: string; 15 - expires_in?: number; 16 - authorization_details?: 17 - | { 18 - type: string; 19 - locations?: string[]; 20 - actions?: string[]; 21 - datatypes?: string[]; 22 - identifier?: string; 23 - privileges?: string[]; 24 - }[] 25 - | undefined; 26 - } 27 - 28 6 export interface TokenInfo { 29 7 scope: string; 30 8 type: string;
+1
packages/oauth/browser-client/package.json
··· 30 30 "@atcute/identity-resolver": "workspace:^", 31 31 "@atcute/lexicons": "workspace:^", 32 32 "@atcute/multibase": "workspace:^", 33 + "@atcute/oauth-types": "workspace:^", 33 34 "@atcute/uint8array": "workspace:^", 34 35 "nanoid": "^5.1.6" 35 36 }