@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.
- package/README.md +100 -244
- package/dist/agents/exchange.d.ts +2 -1
- package/dist/agents/exchange.d.ts.map +1 -1
- package/dist/agents/exchange.js +3 -4
- package/dist/agents/exchange.js.map +1 -1
- package/dist/agents/server-agent.d.ts +5 -5
- package/dist/agents/server-agent.d.ts.map +1 -1
- package/dist/agents/server-agent.js +5 -9
- package/dist/agents/server-agent.js.map +1 -1
- package/dist/agents/sessions.d.ts.map +1 -1
- package/dist/agents/sessions.js +16 -1
- package/dist/agents/sessions.js.map +1 -1
- package/dist/agents/user-agent.js +2 -2
- package/dist/agents/user-agent.js.map +1 -1
- package/dist/dpop.d.ts +2 -4
- package/dist/dpop.d.ts.map +1 -1
- package/dist/dpop.js +6 -79
- package/dist/dpop.js.map +1 -1
- package/dist/environment.d.ts +3 -3
- package/dist/environment.d.ts.map +1 -1
- package/dist/environment.js.map +1 -1
- package/dist/index.d.ts +3 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -11
- package/dist/index.js.map +1 -1
- package/dist/resolvers.d.ts +92 -4
- package/dist/resolvers.d.ts.map +1 -1
- package/dist/resolvers.js +7 -7
- package/dist/resolvers.js.map +1 -1
- package/dist/store/db.d.ts +49 -6
- package/dist/store/db.d.ts.map +1 -1
- package/dist/types/client-assertion.d.ts +2 -3
- package/dist/types/client-assertion.d.ts.map +1 -1
- package/dist/types/server.d.ts +2 -56
- package/dist/types/server.d.ts.map +1 -1
- package/dist/types/token.d.ts +8 -20
- package/dist/types/token.d.ts.map +1 -1
- package/dist/utils/dpop-key.d.ts +10 -0
- package/dist/utils/dpop-key.d.ts.map +1 -0
- package/dist/utils/dpop-key.js +13 -0
- package/dist/utils/dpop-key.js.map +1 -0
- package/dist/utils/runtime.d.ts +0 -6
- package/dist/utils/runtime.d.ts.map +1 -1
- package/dist/utils/runtime.js +0 -16
- package/dist/utils/runtime.js.map +1 -1
- package/lib/agents/exchange.ts +10 -11
- package/lib/agents/server-agent.ts +14 -17
- package/lib/agents/sessions.ts +23 -2
- package/lib/agents/user-agent.ts +2 -2
- package/lib/dpop.ts +7 -108
- package/lib/environment.ts +3 -3
- package/lib/index.ts +12 -12
- package/lib/resolvers.ts +15 -13
- package/lib/store/db.ts +6 -6
- package/lib/types/client-assertion.ts +2 -4
- package/lib/types/server.ts +2 -57
- package/lib/types/token.ts +10 -24
- package/lib/utils/dpop-key.ts +24 -0
- package/lib/utils/runtime.ts +0 -22
- package/package.json +12 -8
- package/dist/types/client.d.ts +0 -38
- package/dist/types/client.d.ts.map +0 -1
- package/dist/types/client.js +0 -2
- package/dist/types/client.js.map +0 -1
- package/dist/types/dpop.d.ts +0 -10
- package/dist/types/dpop.d.ts.map +0 -1
- package/dist/types/dpop.js +0 -2
- package/dist/types/dpop.js.map +0 -1
- package/dist/types/identity.d.ts +0 -6
- package/dist/types/identity.d.ts.map +0 -1
- package/dist/types/identity.js +0 -2
- package/dist/types/identity.js.map +0 -1
- package/dist/types/par.d.ts +0 -5
- package/dist/types/par.d.ts.map +0 -1
- package/dist/types/par.js +0 -2
- package/dist/types/par.js.map +0 -1
- package/dist/utils/identity-resolver.d.ts +0 -7
- package/dist/utils/identity-resolver.d.ts.map +0 -1
- package/dist/utils/identity-resolver.js +0 -8
- package/dist/utils/identity-resolver.js.map +0 -1
- package/lib/types/client.ts +0 -82
- package/lib/types/dpop.ts +0 -9
- package/lib/types/identity.ts +0 -12
- package/lib/types/par.ts +0 -4
- package/lib/utils/identity-resolver.ts +0 -12
package/dist/store/db.d.ts
CHANGED
|
@@ -1,17 +1,60 @@
|
|
|
1
|
-
import type {
|
|
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 {
|
|
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}`,
|
|
10
|
+
sessions: SimpleStore<`did:${string}:${string}`, RawSession>;
|
|
12
11
|
states: SimpleStore<string, {
|
|
13
|
-
dpopKey:
|
|
14
|
-
metadata:
|
|
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
|
}>;
|
package/dist/store/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../lib/store/db.ts"],"names":[],"mappings":"
|
|
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
|
|
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"}
|
package/dist/types/server.d.ts
CHANGED
|
@@ -1,58 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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":"AAAA,
|
|
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"}
|
package/dist/types/token.d.ts
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
import type { Did } from '@atcute/lexicons';
|
|
2
|
-
import type {
|
|
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:
|
|
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;
|
|
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"}
|
package/dist/utils/runtime.d.ts
CHANGED
|
@@ -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":"
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../lib/utils/runtime.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,EAAE,WAAW,GAAG,SAA0E,CAAC"}
|
package/dist/utils/runtime.js
CHANGED
|
@@ -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,
|
|
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"}
|
package/lib/agents/exchange.ts
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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?:
|
|
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?:
|
|
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
|
|
59
|
-
const dpopKey = await
|
|
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
|
|
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,
|
|
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:
|
|
17
|
+
#dpopKey: DpopPrivateJwk;
|
|
18
18
|
|
|
19
|
-
constructor(metadata: PersistedAuthorizationServerMetadata, 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<
|
|
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
|
|
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
|
-
|
|
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:
|
|
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(
|
|
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`);
|
package/lib/agents/sessions.ts
CHANGED
|
@@ -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
|
+
};
|
package/lib/agents/user-agent.ts
CHANGED
|
@@ -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
|
|