@atcute/oauth-browser-client 2.0.2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +100 -244
  2. package/dist/agents/exchange.d.ts +2 -1
  3. package/dist/agents/exchange.d.ts.map +1 -1
  4. package/dist/agents/exchange.js +3 -4
  5. package/dist/agents/exchange.js.map +1 -1
  6. package/dist/agents/server-agent.d.ts +5 -5
  7. package/dist/agents/server-agent.d.ts.map +1 -1
  8. package/dist/agents/server-agent.js +5 -9
  9. package/dist/agents/server-agent.js.map +1 -1
  10. package/dist/agents/sessions.d.ts.map +1 -1
  11. package/dist/agents/sessions.js +16 -1
  12. package/dist/agents/sessions.js.map +1 -1
  13. package/dist/agents/user-agent.js +2 -2
  14. package/dist/agents/user-agent.js.map +1 -1
  15. package/dist/dpop.d.ts +2 -4
  16. package/dist/dpop.d.ts.map +1 -1
  17. package/dist/dpop.js +6 -79
  18. package/dist/dpop.js.map +1 -1
  19. package/dist/environment.d.ts +3 -3
  20. package/dist/environment.d.ts.map +1 -1
  21. package/dist/environment.js.map +1 -1
  22. package/dist/index.d.ts +3 -11
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -11
  25. package/dist/index.js.map +1 -1
  26. package/dist/resolvers.d.ts +92 -4
  27. package/dist/resolvers.d.ts.map +1 -1
  28. package/dist/resolvers.js +7 -7
  29. package/dist/resolvers.js.map +1 -1
  30. package/dist/store/db.d.ts +49 -6
  31. package/dist/store/db.d.ts.map +1 -1
  32. package/dist/types/client-assertion.d.ts +2 -3
  33. package/dist/types/client-assertion.d.ts.map +1 -1
  34. package/dist/types/server.d.ts +2 -56
  35. package/dist/types/server.d.ts.map +1 -1
  36. package/dist/types/token.d.ts +8 -20
  37. package/dist/types/token.d.ts.map +1 -1
  38. package/dist/utils/dpop-key.d.ts +10 -0
  39. package/dist/utils/dpop-key.d.ts.map +1 -0
  40. package/dist/utils/dpop-key.js +13 -0
  41. package/dist/utils/dpop-key.js.map +1 -0
  42. package/dist/utils/runtime.d.ts +0 -6
  43. package/dist/utils/runtime.d.ts.map +1 -1
  44. package/dist/utils/runtime.js +0 -16
  45. package/dist/utils/runtime.js.map +1 -1
  46. package/lib/agents/exchange.ts +10 -11
  47. package/lib/agents/server-agent.ts +14 -17
  48. package/lib/agents/sessions.ts +23 -2
  49. package/lib/agents/user-agent.ts +2 -2
  50. package/lib/dpop.ts +7 -108
  51. package/lib/environment.ts +3 -3
  52. package/lib/index.ts +12 -12
  53. package/lib/resolvers.ts +15 -13
  54. package/lib/store/db.ts +6 -6
  55. package/lib/types/client-assertion.ts +2 -4
  56. package/lib/types/server.ts +2 -57
  57. package/lib/types/token.ts +10 -24
  58. package/lib/utils/dpop-key.ts +24 -0
  59. package/lib/utils/runtime.ts +0 -22
  60. package/package.json +12 -8
  61. package/dist/types/client.d.ts +0 -38
  62. package/dist/types/client.d.ts.map +0 -1
  63. package/dist/types/client.js +0 -2
  64. package/dist/types/client.js.map +0 -1
  65. package/dist/types/dpop.d.ts +0 -10
  66. package/dist/types/dpop.d.ts.map +0 -1
  67. package/dist/types/dpop.js +0 -2
  68. package/dist/types/dpop.js.map +0 -1
  69. package/dist/types/identity.d.ts +0 -6
  70. package/dist/types/identity.d.ts.map +0 -1
  71. package/dist/types/identity.js +0 -2
  72. package/dist/types/identity.js.map +0 -1
  73. package/dist/types/par.d.ts +0 -5
  74. package/dist/types/par.d.ts.map +0 -1
  75. package/dist/types/par.js +0 -2
  76. package/dist/types/par.js.map +0 -1
  77. package/dist/utils/identity-resolver.d.ts +0 -7
  78. package/dist/utils/identity-resolver.d.ts.map +0 -1
  79. package/dist/utils/identity-resolver.js +0 -8
  80. package/dist/utils/identity-resolver.js.map +0 -1
  81. package/lib/types/client.ts +0 -82
  82. package/lib/types/dpop.ts +0 -9
  83. package/lib/types/identity.ts +0 -12
  84. package/lib/types/par.ts +0 -4
  85. package/lib/utils/identity-resolver.ts +0 -12
@@ -1,17 +1,60 @@
1
- import type { DPoPKey } from '../types/dpop.js';
2
- import type { AuthorizationServerMetadata } from '../types/server.js';
1
+ import type { DpopPrivateJwk } from '@atcute/oauth-crypto';
3
2
  import type { SimpleStore } from '../types/store.js';
4
- import type { Session } from '../types/token.js';
3
+ import type { RawSession } from '../types/token.js';
5
4
  export interface OAuthDatabaseOptions {
6
5
  name: string;
7
6
  }
8
7
  export type OAuthDatabase = ReturnType<typeof createOAuthDatabase>;
9
8
  export declare const createOAuthDatabase: ({ name }: OAuthDatabaseOptions) => {
10
9
  dispose: () => void;
11
- sessions: SimpleStore<`did:${string}:${string}`, Session>;
10
+ sessions: SimpleStore<`did:${string}:${string}`, RawSession>;
12
11
  states: SimpleStore<string, {
13
- dpopKey: DPoPKey;
14
- metadata: AuthorizationServerMetadata;
12
+ dpopKey: DpopPrivateJwk;
13
+ metadata: {
14
+ issuer: string;
15
+ claims_supported?: string[] | undefined;
16
+ claims_locales_supported?: string[] | undefined;
17
+ claims_parameter_supported?: boolean | undefined;
18
+ request_parameter_supported?: boolean | undefined;
19
+ request_uri_parameter_supported?: boolean | undefined;
20
+ require_request_uri_registration?: boolean | undefined;
21
+ scopes_supported?: string[] | undefined;
22
+ subject_types_supported?: string[] | undefined;
23
+ response_types_supported?: string[] | undefined;
24
+ response_modes_supported?: string[] | undefined;
25
+ grant_types_supported?: string[] | undefined;
26
+ code_challenge_methods_supported?: ("S256" | "plain")[] | undefined;
27
+ ui_locales_supported?: string[] | undefined;
28
+ id_token_signing_alg_values_supported?: string[] | undefined;
29
+ display_values_supported?: string[] | undefined;
30
+ prompt_values_supported?: ("consent" | "create" | "login" | "none" | "select_account")[] | undefined;
31
+ request_object_signing_alg_values_supported?: string[] | undefined;
32
+ authorization_response_iss_parameter_supported?: boolean | undefined;
33
+ authorization_details_types_supported?: string[] | undefined;
34
+ request_object_encryption_alg_values_supported?: string[] | undefined;
35
+ request_object_encryption_enc_values_supported?: string[] | undefined;
36
+ jwks_uri?: string | undefined;
37
+ authorization_endpoint: string;
38
+ token_endpoint: string;
39
+ token_endpoint_auth_methods_supported?: string[] | undefined;
40
+ token_endpoint_auth_signing_alg_values_supported?: string[] | undefined;
41
+ revocation_endpoint?: string | undefined;
42
+ revocation_endpoint_auth_methods_supported?: string[] | undefined;
43
+ revocation_endpoint_auth_signing_alg_values_supported?: string[] | undefined;
44
+ introspection_endpoint?: string | undefined;
45
+ introspection_endpoint_auth_methods_supported?: string[] | undefined;
46
+ introspection_endpoint_auth_signing_alg_values_supported?: string[] | undefined;
47
+ pushed_authorization_request_endpoint?: string | undefined;
48
+ pushed_authorization_request_endpoint_auth_methods_supported?: string[] | undefined;
49
+ pushed_authorization_request_endpoint_auth_signing_alg_values_supported?: string[] | undefined;
50
+ require_pushed_authorization_requests?: boolean | undefined;
51
+ userinfo_endpoint?: string | undefined;
52
+ end_session_endpoint?: string | undefined;
53
+ registration_endpoint?: string | undefined;
54
+ dpop_signing_alg_values_supported?: string[] | undefined;
55
+ protected_resources?: string[] | undefined;
56
+ client_id_metadata_document_supported?: boolean | undefined;
57
+ };
15
58
  verifier?: string | undefined;
16
59
  state?: unknown;
17
60
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../lib/store/db.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;CACb;AA2CD,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEnE,eAAO,MAAM,mBAAmB;;;;;;;;;;;CAyJ/B,CAAC"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../lib/store/db.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;CACb;AA2CD,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEnE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyJ/B,CAAC"}
@@ -4,17 +4,16 @@ export interface ClientAssertionCredentials {
4
4
  client_assertion_type: typeof CLIENT_ASSERTION_TYPE_JWT_BEARER;
5
5
  }
6
6
  export interface FetchClientAssertionParams {
7
- /** JWK thumbprint of the DPoP key to bind the assertion to */
8
- jkt: string;
9
7
  /** authorization server issuer (audience for the assertion) */
10
8
  aud: string;
11
9
  /**
12
10
  * create a DPoP proof to prove you possess the key for the claimed jkt.
13
11
  *
14
12
  * @param htu origin and pathname to your backend
13
+ * @param nonce optional DPoP nonce from the server
15
14
  * @returns DPoP proof that can be included in the assertion
16
15
  */
17
- createDpopProof: (htu: string) => Promise<string>;
16
+ createDpopProof: (htu: string, nonce?: string) => Promise<string>;
18
17
  }
19
18
  export type ClientAssertionFetcher = (params: FetchClientAssertionParams) => Promise<ClientAssertionCredentials>;
20
19
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"client-assertion.d.ts","sourceRoot":"","sources":["../../lib/types/client-assertion.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,gCAAgC,2DAA2D,CAAC;AAElG,MAAM,WAAW,0BAA0B;IAC1C,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,OAAO,gCAAgC,CAAC;CAC/D;AAED,MAAM,WAAW,0BAA0B;IAC1C,8DAA8D;IAC9D,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IAEZ;;;;;OAKG;IACH,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClD;AAED,MAAM,MAAM,sBAAsB,GAAG,CACpC,MAAM,EAAE,0BAA0B,KAC9B,OAAO,CAAC,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"client-assertion.d.ts","sourceRoot":"","sources":["../../lib/types/client-assertion.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,gCAAgC,2DAA2D,CAAC;AAElG,MAAM,WAAW,0BAA0B;IAC1C,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,OAAO,gCAAgC,CAAC;CAC/D;AAED,MAAM,WAAW,0BAA0B;IAC1C,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClE;AAED,MAAM,MAAM,sBAAsB,GAAG,CACpC,MAAM,EAAE,0BAA0B,KAC9B,OAAO,CAAC,0BAA0B,CAAC,CAAC"}
@@ -1,58 +1,4 @@
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
- export interface AuthorizationServerMetadata {
13
- issuer: string;
14
- authorization_endpoint: string;
15
- token_endpoint: string;
16
- jwks_uri?: string;
17
- scopes_supported?: string[];
18
- claims_supported?: string[];
19
- claims_locales_supported?: string[];
20
- claims_parameter_supported?: boolean;
21
- request_parameter_supported?: boolean;
22
- request_uri_parameter_supported?: boolean;
23
- require_request_uri_registration?: boolean;
24
- subject_types_supported?: string[];
25
- response_types_supported?: string[];
26
- response_modes_supported?: string[];
27
- grant_types_supported?: string[];
28
- code_challenge_methods_supported?: string[];
29
- ui_locales_supported?: string[];
30
- id_token_signing_alg_values_supported?: string[];
31
- display_values_supported?: string[];
32
- request_object_signing_alg_values_supported?: string[];
33
- authorization_response_iss_parameter_supported?: boolean;
34
- authorization_details_types_supported?: string[];
35
- request_object_encryption_alg_values_supported?: string[];
36
- request_object_encryption_enc_values_supported?: string[];
37
- token_endpoint_auth_methods_supported?: string[];
38
- token_endpoint_auth_signing_alg_values_supported?: string[];
39
- revocation_endpoint?: string;
40
- revocation_endpoint_auth_methods_supported?: string[];
41
- revocation_endpoint_auth_signing_alg_values_supported?: string[];
42
- introspection_endpoint?: string;
43
- introspection_endpoint_auth_methods_supported?: string[];
44
- introspection_endpoint_auth_signing_alg_values_supported?: string[];
45
- pushed_authorization_request_endpoint?: string;
46
- pushed_authorization_request_endpoint_auth_methods_supported?: string[];
47
- pushed_authorization_request_endpoint_auth_signing_alg_values_supported?: string[];
48
- require_pushed_authorization_requests?: boolean;
49
- userinfo_endpoint?: string;
50
- end_session_endpoint?: string;
51
- registration_endpoint?: string;
52
- dpop_signing_alg_values_supported?: string[];
53
- protected_resources?: string[];
54
- client_id_metadata_document_supported?: boolean;
55
- }
56
- export interface PersistedAuthorizationServerMetadata extends Pick<AuthorizationServerMetadata, 'issuer' | 'authorization_endpoint' | 'introspection_endpoint' | 'pushed_authorization_request_endpoint' | 'revocation_endpoint' | 'token_endpoint'> {
1
+ import type { OAuthAuthorizationServerMetadata } from '@atcute/oauth-types';
2
+ export interface PersistedAuthorizationServerMetadata extends Pick<OAuthAuthorizationServerMetadata, 'issuer' | 'authorization_endpoint' | 'introspection_endpoint' | 'pushed_authorization_request_endpoint' | 'revocation_endpoint' | 'token_endpoint'> {
57
3
  }
58
4
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../lib/types/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../lib/types/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,qBAAqB,CAAC;AAE5E,MAAM,WAAW,oCAAqC,SAAQ,IAAI,CACjE,gCAAgC,EAC9B,QAAQ,GACR,wBAAwB,GACxB,wBAAwB,GACxB,uCAAuC,GACvC,qBAAqB,GACrB,gBAAgB,CAClB;CAAG"}
@@ -1,24 +1,7 @@
1
1
  import type { Did } from '@atcute/lexicons';
2
- import type { DPoPKey } from './dpop.js';
2
+ import type { DpopPrivateJwk } from '@atcute/oauth-crypto';
3
+ import type { LegacyDpopKey } from '../utils/dpop-key.js';
3
4
  import type { PersistedAuthorizationServerMetadata } from './server.js';
4
- export interface OAuthTokenResponse {
5
- access_token: string;
6
- token_type: string;
7
- issuer?: string;
8
- sub?: string;
9
- scope?: string;
10
- id_token?: `${string}.${string}.${string}`;
11
- refresh_token?: string;
12
- expires_in?: number;
13
- authorization_details?: {
14
- type: string;
15
- locations?: string[];
16
- actions?: string[];
17
- datatypes?: string[];
18
- identifier?: string;
19
- privileges?: string[];
20
- }[] | undefined;
21
- }
22
5
  export interface TokenInfo {
23
6
  scope: string;
24
7
  type: string;
@@ -31,8 +14,13 @@ export interface ExchangeInfo {
31
14
  aud: string;
32
15
  server: PersistedAuthorizationServerMetadata;
33
16
  }
17
+ export interface RawSession {
18
+ dpopKey: DpopPrivateJwk | LegacyDpopKey;
19
+ info: ExchangeInfo;
20
+ token: TokenInfo;
21
+ }
34
22
  export interface Session {
35
- dpopKey: DPoPKey;
23
+ dpopKey: DpopPrivateJwk;
36
24
  info: ExchangeInfo;
37
25
  token: TokenInfo;
38
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../lib/types/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,aAAa,CAAC;AAExE,MAAM,WAAW,kBAAkB;IAClC,YAAY,EAAE,MAAM,CAAC;IAErB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,GAAG,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,CAAC,EACnB;QACA,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,EAAE,GACH,SAAS,CAAC;CACb;AAED,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,oCAAoC,CAAC;CAC7C;AAED,MAAM,WAAW,OAAO;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;CACjB"}
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../lib/types/token.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,aAAa,CAAC;AAExE,MAAM,WAAW,SAAS;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC5B,GAAG,EAAE,GAAG,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,oCAAoC,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,cAAc,GAAG,aAAa,CAAC;IACxC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,OAAO;IACvB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;CACjB"}
@@ -0,0 +1,10 @@
1
+ import type { DpopPrivateJwk } from '@atcute/oauth-crypto';
2
+ export interface LegacyDpopKey {
3
+ typ: 'ES256';
4
+ key: string;
5
+ jwt: string;
6
+ jkt?: string;
7
+ }
8
+ export declare const isLegacyDpopKey: (key: LegacyDpopKey | DpopPrivateJwk) => key is LegacyDpopKey;
9
+ export declare const migrateLegacyDpopKey: (key: LegacyDpopKey) => Promise<DpopPrivateJwk>;
10
+ //# sourceMappingURL=dpop-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpop-key.d.ts","sourceRoot":"","sources":["../../lib/utils/dpop-key.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAID,eAAO,MAAM,eAAe,+DAE3B,CAAC;AAEF,eAAO,MAAM,oBAAoB,iDAOhC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { fromBase64Url } from '@atcute/multibase';
2
+ const ES256_ALG = { name: 'ECDSA', namedCurve: 'P-256' };
3
+ export const isLegacyDpopKey = (key) => {
4
+ return typeof key.key === 'string' && typeof key.jwt === 'string';
5
+ };
6
+ export const migrateLegacyDpopKey = async (key) => {
7
+ const pkcs8 = fromBase64Url(key.key);
8
+ const cryptoKey = await crypto.subtle.importKey('pkcs8', pkcs8, ES256_ALG, true, ['sign']);
9
+ const jwk = (await crypto.subtle.exportKey('jwk', cryptoKey));
10
+ jwk.alg = 'ES256';
11
+ return jwk;
12
+ };
13
+ //# sourceMappingURL=dpop-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dpop-key.js","sourceRoot":"","sources":["../../lib/utils/dpop-key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAUlD,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAW,CAAC;AAElE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAmC,EAAwB,EAAE,CAAC;IAC7F,OAAO,OAAQ,GAAqB,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAQ,GAAqB,CAAC,GAAG,KAAK,QAAQ,CAAC;AAAA,CACxG,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,EAAE,GAAkB,EAA2B,EAAE,CAAC;IAC1F,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3F,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAmB,CAAC;IAChF,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC;IAElB,OAAO,GAAG,CAAC;AAAA,CACX,CAAC"}
@@ -1,8 +1,2 @@
1
1
  export declare const locks: LockManager | undefined;
2
- export declare const stringToSha256: (input: string) => Promise<string>;
3
- export declare const generatePKCE: () => Promise<{
4
- verifier: string;
5
- challenge: string;
6
- method: string;
7
- }>;
8
2
  //# sourceMappingURL=runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../lib/utils/runtime.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,KAAK,EAAE,WAAW,GAAG,SAA0E,CAAC;AAE7G,eAAO,MAAM,cAAc,oCAK1B,CAAC;AAEF,eAAO,MAAM,YAAY;;;;EAQxB,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../lib/utils/runtime.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,EAAE,WAAW,GAAG,SAA0E,CAAC"}
@@ -1,18 +1,2 @@
1
- import { nanoid } from 'nanoid';
2
- import { toBase64Url } from '@atcute/multibase';
3
- import { encodeUtf8, toSha256 } from '@atcute/uint8array';
4
1
  export const locks = typeof navigator !== 'undefined' ? navigator.locks : undefined;
5
- export const stringToSha256 = async (input) => {
6
- const bytes = encodeUtf8(input);
7
- const digest = await toSha256(bytes);
8
- return toBase64Url(digest);
9
- };
10
- export const generatePKCE = async () => {
11
- const verifier = nanoid(64);
12
- return {
13
- verifier: verifier,
14
- challenge: await stringToSha256(verifier),
15
- method: 'S256',
16
- };
17
- };
18
2
  //# sourceMappingURL=runtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../lib/utils/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,CAAC,MAAM,KAAK,GAA4B,OAAO,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAE7G,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,KAAa,EAAmB,EAAE,CAAC;IACvE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;IAErC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;AAAA,CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,IAAsE,EAAE,CAAC;IACzG,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IAE5B,OAAO;QACN,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,MAAM,cAAc,CAAC,QAAQ,CAAC;QACzC,MAAM,EAAE,MAAM;KACd,CAAC;AAAA,CACF,CAAC"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../lib/utils/runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAA4B,OAAO,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC"}
@@ -1,16 +1,15 @@
1
- import { nanoid } from 'nanoid';
2
-
1
+ import type { ResolvedActor } from '@atcute/identity-resolver';
3
2
  import type { ActorIdentifier } from '@atcute/lexicons';
3
+ import { generateDpopKey, generatePkce } from '@atcute/oauth-crypto';
4
+ import type { OAuthAuthorizationServerMetadata, OAuthPrompt } from '@atcute/oauth-types';
5
+
6
+ import { nanoid } from 'nanoid';
4
7
 
5
- import { createES256Key } from '../dpop.js';
6
8
  import { CLIENT_ID, database, REDIRECT_URI } from '../environment.js';
7
9
  import { AuthorizationError, LoginError } from '../errors.js';
8
- import type { ResolvedIdentity } from '../types/identity.js';
9
- import type { AuthorizationServerMetadata } from '../types/server.js';
10
+ import { resolveFromIdentifier, resolveFromService } from '../resolvers.js';
10
11
  import type { Session } from '../types/token.js';
11
- import { generatePKCE } from '../utils/runtime.js';
12
12
 
13
- import { resolveFromIdentifier, resolveFromService } from '../resolvers.js';
14
13
  import { OAuthServerAgent } from './server-agent.js';
15
14
  import { storeSession } from './sessions.js';
16
15
 
@@ -22,7 +21,7 @@ export interface AuthorizeOptions {
22
21
  target: AuthorizeTargetOptions;
23
22
  scope: string;
24
23
  state?: unknown;
25
- prompt?: 'none' | 'login' | 'consent' | 'select_account';
24
+ prompt?: OAuthPrompt | (string & {});
26
25
  display?: 'page' | 'popup' | 'touch' | 'wap';
27
26
  locale?: string;
28
27
  }
@@ -35,7 +34,7 @@ export interface AuthorizeOptions {
35
34
  export const createAuthorizationUrl = async (options: AuthorizeOptions): Promise<URL> => {
36
35
  const { target, scope, state = null, ...reqs } = options;
37
36
 
38
- let resolved: { identity?: ResolvedIdentity; metadata: AuthorizationServerMetadata };
37
+ let resolved: { identity?: ResolvedActor; metadata: OAuthAuthorizationServerMetadata };
39
38
  switch (target.type) {
40
39
  case 'account': {
41
40
  resolved = await resolveFromIdentifier(target.identifier);
@@ -55,8 +54,8 @@ export const createAuthorizationUrl = async (options: AuthorizeOptions): Promise
55
54
 
56
55
  const sid = nanoid(24);
57
56
 
58
- const pkce = await generatePKCE();
59
- const dpopKey = await createES256Key();
57
+ const pkce = await generatePkce();
58
+ const dpopKey = await generateDpopKey(['ES256']);
60
59
 
61
60
  const params = {
62
61
  display: reqs.display,
@@ -1,22 +1,22 @@
1
1
  import type { Did } from '@atcute/lexicons';
2
+ import { createDpopProofSigner, type DpopPrivateJwk } from '@atcute/oauth-crypto';
3
+ import type { AtprotoOAuthTokenResponse, OAuthParResponse } from '@atcute/oauth-types';
2
4
 
3
- import { createDPoPFetch, createDPoPSignage } from '../dpop.js';
5
+ import { createDPoPFetch } from '../dpop.js';
4
6
  import { CLIENT_ID, fetchClientAssertion, REDIRECT_URI } from '../environment.js';
5
7
  import { FetchResponseError, OAuthResponseError, TokenRefreshError } from '../errors.js';
6
8
  import { resolveFromIdentifier } from '../resolvers.js';
7
- 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
 
14
14
  export class OAuthServerAgent {
15
15
  #fetch: typeof fetch;
16
16
  #metadata: PersistedAuthorizationServerMetadata;
17
- #dpopKey: DPoPKey;
17
+ #dpopKey: DpopPrivateJwk;
18
18
 
19
- constructor(metadata: PersistedAuthorizationServerMetadata, dpopKey: DPoPKey) {
19
+ constructor(metadata: PersistedAuthorizationServerMetadata, dpopKey: DpopPrivateJwk) {
20
20
  this.#metadata = metadata;
21
21
  this.#dpopKey = dpopKey;
22
22
  this.#fetch = createDPoPFetch(dpopKey, true);
@@ -26,7 +26,7 @@ export class OAuthServerAgent {
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> {
@@ -39,17 +39,12 @@ export class OAuthServerAgent {
39
39
  (endpoint === 'token' || endpoint === 'pushed_authorization_request') &&
40
40
  fetchClientAssertion !== undefined
41
41
  ) {
42
- const jkt = this.#dpopKey.jkt;
43
- if (jkt === undefined) {
44
- throw new Error(`DPoP key missing jkt field`);
45
- }
42
+ const sign = createDpopProofSigner(this.#dpopKey);
46
43
 
47
44
  const assertion = await fetchClientAssertion({
48
- jkt: jkt,
49
45
  aud: this.#metadata.issuer,
50
- createDpopProof: async (url) => {
51
- const sign = createDPoPSignage(this.#dpopKey);
52
- return await sign('POST', url, undefined, undefined);
46
+ createDpopProof: async (url, nonce) => {
47
+ return await sign('POST', url, nonce, undefined);
53
48
  },
54
49
  });
55
50
 
@@ -120,7 +115,7 @@ export class OAuthServerAgent {
120
115
  }
121
116
  }
122
117
 
123
- #processTokenResponse(res: OAuthTokenResponse): TokenInfo {
118
+ #processTokenResponse(res: AtprotoOAuthTokenResponse): TokenInfo {
124
119
  if (!res.sub) {
125
120
  throw new TypeError(`missing sub field in token response`);
126
121
  }
@@ -140,7 +135,9 @@ export class OAuthServerAgent {
140
135
  };
141
136
  }
142
137
 
143
- async #processExchangeResponse(res: OAuthTokenResponse): Promise<{ info: ExchangeInfo; token: TokenInfo }> {
138
+ async #processExchangeResponse(
139
+ res: AtprotoOAuthTokenResponse,
140
+ ): Promise<{ info: ExchangeInfo; token: TokenInfo }> {
144
141
  const sub = res.sub;
145
142
  if (!sub) {
146
143
  throw new TypeError(`missing sub field in token response`);
@@ -2,7 +2,8 @@ import type { Did } from '@atcute/lexicons';
2
2
 
3
3
  import { database } from '../environment.js';
4
4
  import { OAuthResponseError, TokenRefreshError } from '../errors.js';
5
- import type { Session } from '../types/token.js';
5
+ import type { RawSession, Session } from '../types/token.js';
6
+ import { isLegacyDpopKey, migrateLegacyDpopKey } from '../utils/dpop-key.js';
6
7
  import { locks } from '../utils/runtime.js';
7
8
 
8
9
  import { OAuthServerAgent } from './server-agent.js';
@@ -49,7 +50,7 @@ export const getSession = async (sub: Did, options?: SessionGetOptions): Promise
49
50
  }
50
51
 
51
52
  const run = async (): Promise<PendingItem<Session>> => {
52
- const storedSession = database.sessions.get(sub);
53
+ const storedSession = await migrateSessionIfNeeded(sub, database.sessions.get(sub));
53
54
 
54
55
  if (storedSession && allowStored(storedSession)) {
55
56
  // Use the stored value as return value for the current execution
@@ -140,3 +141,23 @@ const isTokenUsable = ({ token }: Session): boolean => {
140
141
  const expires = token.expires_at;
141
142
  return expires == null || Date.now() + 60_000 <= expires;
142
143
  };
144
+
145
+ const migrateSessionIfNeeded = async (
146
+ sub: Did,
147
+ session: RawSession | undefined,
148
+ ): Promise<Session | undefined> => {
149
+ if (!session || !isLegacyDpopKey(session.dpopKey)) {
150
+ return session as Session | undefined;
151
+ }
152
+
153
+ const dpopKey = await migrateLegacyDpopKey(session.dpopKey);
154
+ const migrated = { ...session, dpopKey };
155
+
156
+ try {
157
+ database.sessions.set(sub, migrated);
158
+ } catch {
159
+ // ignore persistence errors
160
+ }
161
+
162
+ return migrated;
163
+ };
@@ -56,7 +56,7 @@ export class OAuthUserAgent implements FetchHandlerObject {
56
56
 
57
57
  headers.set('authorization', `${session.token.type} ${session.token.access}`);
58
58
 
59
- let response = await this.#fetch(url, { ...init, headers });
59
+ let response = await this.#fetch(url.href, { ...init, headers });
60
60
  if (!isInvalidTokenResponse(response)) {
61
61
  return response;
62
62
  }
@@ -79,7 +79,7 @@ export class OAuthUserAgent implements FetchHandlerObject {
79
79
  url = new URL(pathname, session.info.aud);
80
80
  headers.set('authorization', `${session.token.type} ${session.token.access}`);
81
81
 
82
- return await this.#fetch(url, { ...init, headers });
82
+ return await this.#fetch(url.href, { ...init, headers });
83
83
  }
84
84
  }
85
85