@atcute/oauth-browser-client 2.0.3 → 3.0.1
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 +19 -12
- package/dist/agents/exchange.d.ts +3 -2
- 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 +6 -6
- 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 +6 -5
- 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.d.ts +2 -2
- package/dist/agents/user-agent.d.ts.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 +5 -5
- package/dist/environment.d.ts.map +1 -1
- package/dist/environment.js.map +1 -1
- package/dist/errors.d.ts +3 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -3
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +7 -15
- 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 +5 -4
- package/dist/resolvers.d.ts.map +1 -1
- package/dist/resolvers.js +5 -5
- package/dist/resolvers.js.map +1 -1
- package/dist/store/db.d.ts +8 -8
- package/dist/store/db.d.ts.map +1 -1
- package/dist/store/db.js.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 +9 -21
- 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/misc.d.ts.map +1 -1
- package/dist/utils/misc.js.map +1 -1
- package/dist/utils/response.d.ts.map +1 -1
- package/dist/utils/response.js.map +1 -1
- 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/dist/utils/strings.d.ts.map +1 -1
- package/dist/utils/strings.js.map +1 -1
- package/lib/agents/exchange.ts +15 -16
- package/lib/agents/server-agent.ts +21 -24
- package/lib/agents/sessions.ts +28 -7
- package/lib/agents/user-agent.ts +14 -8
- package/lib/dpop.ts +9 -110
- package/lib/environment.ts +5 -5
- package/lib/errors.ts +15 -14
- package/lib/index.ts +16 -16
- package/lib/resolvers.ts +17 -15
- package/lib/store/db.ts +8 -8
- 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 +20 -11
- 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/README.md
CHANGED
|
@@ -53,7 +53,9 @@ configureOAuth({
|
|
|
53
53
|
redirect_uri: 'https://example.com/oauth/callback',
|
|
54
54
|
},
|
|
55
55
|
identityResolver: new LocalActorResolver({
|
|
56
|
-
handleResolver: new XrpcHandleResolver({
|
|
56
|
+
handleResolver: new XrpcHandleResolver({
|
|
57
|
+
serviceUrl: 'https://public.api.bsky.app',
|
|
58
|
+
}),
|
|
57
59
|
didDocumentResolver: new CompositeDidDocumentResolver({
|
|
58
60
|
methods: {
|
|
59
61
|
plc: new PlcDidDocumentResolver(),
|
|
@@ -88,7 +90,7 @@ window.location.assign(authUrl);
|
|
|
88
90
|
on your redirect URL, extract the parameters and finalize:
|
|
89
91
|
|
|
90
92
|
```ts
|
|
91
|
-
import {
|
|
93
|
+
import { Client } from '@atcute/client';
|
|
92
94
|
import { OAuthUserAgent, finalizeAuthorization } from '@atcute/oauth-browser-client';
|
|
93
95
|
|
|
94
96
|
// server redirects with params in hash, not search string
|
|
@@ -99,7 +101,7 @@ history.replaceState(null, '', location.pathname + location.search);
|
|
|
99
101
|
|
|
100
102
|
const { session } = await finalizeAuthorization(params);
|
|
101
103
|
const agent = new OAuthUserAgent(session);
|
|
102
|
-
const rpc = new
|
|
104
|
+
const rpc = new Client({ handler: agent });
|
|
103
105
|
|
|
104
106
|
const { data } = await rpc.get('com.atproto.identity.resolveHandle', {
|
|
105
107
|
params: { handle: 'mary.my.id' },
|
|
@@ -114,7 +116,9 @@ your UI, as sessions without refresh tokens may expire.
|
|
|
114
116
|
```ts
|
|
115
117
|
import { OAuthUserAgent, getSession } from '@atcute/oauth-browser-client';
|
|
116
118
|
|
|
117
|
-
const session = await getSession('did:plc:ia76kvnndjutgedggx2ibrem', {
|
|
119
|
+
const session = await getSession('did:plc:ia76kvnndjutgedggx2ibrem', {
|
|
120
|
+
allowStale: true,
|
|
121
|
+
});
|
|
118
122
|
const agent = new OAuthUserAgent(session);
|
|
119
123
|
```
|
|
120
124
|
|
|
@@ -140,7 +144,8 @@ by default, this library operates as a **public client** with shorter session li
|
|
|
140
144
|
longer-lived sessions, set up a [client assertion backend][client-assertion-backend] to enable
|
|
141
145
|
**confidential client mode**.
|
|
142
146
|
|
|
143
|
-
[client-assertion-backend]:
|
|
147
|
+
[client-assertion-backend]:
|
|
148
|
+
https://github.com/bluesky-social/proposals/tree/main/0010-client-assertion-backend
|
|
144
149
|
|
|
145
150
|
add `fetchClientAssertion` to your config. the backend API is entirely up to you - this is just one
|
|
146
151
|
example:
|
|
@@ -149,13 +154,14 @@ example:
|
|
|
149
154
|
configureOAuth({
|
|
150
155
|
// ... existing config
|
|
151
156
|
|
|
152
|
-
async fetchClientAssertion({
|
|
153
|
-
const
|
|
157
|
+
async fetchClientAssertion({ aud, createDpopProof }) {
|
|
158
|
+
const htu = 'https://example.com/api/client-assertion';
|
|
159
|
+
const dpop = await createDpopProof(htu);
|
|
154
160
|
|
|
155
|
-
const response = await fetch(
|
|
161
|
+
const response = await fetch(htu, {
|
|
156
162
|
method: 'POST',
|
|
157
163
|
headers: { dpop, 'content-type': 'application/json' },
|
|
158
|
-
body: JSON.stringify({
|
|
164
|
+
body: JSON.stringify({ aud }),
|
|
159
165
|
});
|
|
160
166
|
|
|
161
167
|
const data = await response.json();
|
|
@@ -167,9 +173,9 @@ configureOAuth({
|
|
|
167
173
|
});
|
|
168
174
|
```
|
|
169
175
|
|
|
170
|
-
your backend validates the
|
|
171
|
-
your client
|
|
172
|
-
allowed key thumbprint).
|
|
176
|
+
your backend validates the dpop proof and signs a client assertion jwt containing `iss`, `sub` (both
|
|
177
|
+
your client id), `aud` (authorization server), `exp`, `jti` (unique nonce), and `cnf: { jkt }` (the
|
|
178
|
+
allowed key thumbprint derived from the proof).
|
|
173
179
|
|
|
174
180
|
update your client metadata for confidential mode - replace `token_endpoint_auth_method` with
|
|
175
181
|
`private_key_jwt`, add `token_endpoint_auth_signing_alg: "ES256"`, and add a `jwks_uri` pointing to
|
|
@@ -191,6 +197,7 @@ export default defineConfig({
|
|
|
191
197
|
server: { host: SERVER_HOST, port: SERVER_PORT },
|
|
192
198
|
plugins: [
|
|
193
199
|
{
|
|
200
|
+
name: 'oauth-envs',
|
|
194
201
|
config(_conf, { command }) {
|
|
195
202
|
if (command === 'build') {
|
|
196
203
|
process.env.VITE_OAUTH_CLIENT_ID = metadata.client_id;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ActorIdentifier } from '@atcute/lexicons';
|
|
2
|
-
import type {
|
|
2
|
+
import type { OAuthPrompt } from '@atcute/oauth-types';
|
|
3
|
+
import type { Session } from '../types/token.ts';
|
|
3
4
|
export type AuthorizeTargetOptions = {
|
|
4
5
|
type: 'account';
|
|
5
6
|
identifier: ActorIdentifier;
|
|
@@ -11,7 +12,7 @@ export interface AuthorizeOptions {
|
|
|
11
12
|
target: AuthorizeTargetOptions;
|
|
12
13
|
scope: string;
|
|
13
14
|
state?: unknown;
|
|
14
|
-
prompt?:
|
|
15
|
+
prompt?: OAuthPrompt | (string & {});
|
|
15
16
|
display?: 'page' | 'popup' | 'touch' | 'wap';
|
|
16
17
|
locale?: string;
|
|
17
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exchange.d.ts","sourceRoot":"","sources":["../../lib/agents/exchange.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exchange.d.ts","sourceRoot":"","sources":["../../lib/agents/exchange.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,KAAK,EAAoC,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAOzF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAKjD,MAAM,MAAM,sBAAsB,GAC/B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,eAAe,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC,MAAM,WAAW,gBAAgB;IAChC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,YAAmB,gBAAgB,KAAG,OAAO,CAAC,GAAG,CAwDnF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,WAAkB,eAAe;;;EA8ClE,CAAC"}
|
package/dist/agents/exchange.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { generateDpopKey, generatePkce } from '@atcute/oauth-crypto';
|
|
1
2
|
import { nanoid } from 'nanoid';
|
|
2
|
-
import { createES256Key } from '../dpop.js';
|
|
3
3
|
import { CLIENT_ID, database, REDIRECT_URI } from '../environment.js';
|
|
4
4
|
import { AuthorizationError, LoginError } from '../errors.js';
|
|
5
|
-
import { generatePKCE } from '../utils/runtime.js';
|
|
6
5
|
import { resolveFromIdentifier, resolveFromService } from '../resolvers.js';
|
|
7
6
|
import { OAuthServerAgent } from './server-agent.js';
|
|
8
7
|
import { storeSession } from './sessions.js';
|
|
@@ -30,8 +29,8 @@ export const createAuthorizationUrl = async (options) => {
|
|
|
30
29
|
: identity.did
|
|
31
30
|
: undefined;
|
|
32
31
|
const sid = nanoid(24);
|
|
33
|
-
const pkce = await
|
|
34
|
-
const dpopKey = await
|
|
32
|
+
const pkce = await generatePkce();
|
|
33
|
+
const dpopKey = await generateDpopKey(['ES256']);
|
|
35
34
|
const params = {
|
|
36
35
|
display: reqs.display,
|
|
37
36
|
ui_locales: reqs.locale,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../lib/agents/exchange.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../lib/agents/exchange.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Did } from '@atcute/lexicons';
|
|
2
|
-
import type
|
|
3
|
-
import type { OAuthParResponse } from '
|
|
4
|
-
import type { PersistedAuthorizationServerMetadata } from '../types/server.
|
|
5
|
-
import type { ExchangeInfo,
|
|
2
|
+
import { type DpopPrivateJwk } from '@atcute/oauth-crypto';
|
|
3
|
+
import type { AtprotoOAuthTokenResponse, OAuthParResponse } from '@atcute/oauth-types';
|
|
4
|
+
import type { PersistedAuthorizationServerMetadata } from '../types/server.ts';
|
|
5
|
+
import type { ExchangeInfo, TokenInfo } from '../types/token.ts';
|
|
6
6
|
export declare class OAuthServerAgent {
|
|
7
7
|
#private;
|
|
8
|
-
constructor(metadata: PersistedAuthorizationServerMetadata, dpopKey:
|
|
8
|
+
constructor(metadata: PersistedAuthorizationServerMetadata, dpopKey: DpopPrivateJwk);
|
|
9
9
|
request(endpoint: 'pushed_authorization_request', payload: Record<string, unknown>): Promise<OAuthParResponse>;
|
|
10
|
-
request(endpoint: 'token', payload: Record<string, unknown>): Promise<
|
|
10
|
+
request(endpoint: 'token', payload: Record<string, unknown>): Promise<AtprotoOAuthTokenResponse>;
|
|
11
11
|
request(endpoint: 'revocation', payload: Record<string, unknown>): Promise<any>;
|
|
12
12
|
request(endpoint: 'introspection', payload: Record<string, unknown>): Promise<any>;
|
|
13
13
|
revoke(token: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-agent.d.ts","sourceRoot":"","sources":["../../lib/agents/server-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"server-agent.d.ts","sourceRoot":"","sources":["../../lib/agents/server-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAMvF,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAIjE,qBAAa,gBAAgB;;IAK5B,YAAY,QAAQ,EAAE,oCAAoC,EAAE,OAAO,EAAE,cAAc,EAIlF;IAEK,OAAO,CACZ,QAAQ,EAAE,8BAA8B,EACxC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvB,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACjG,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAChF,OAAO,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IA0CnF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIzC;IAEK,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,CAAC,CAcrG;IAEK,OAAO,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAqBhF;CAqDD"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createDpopProofSigner } from '@atcute/oauth-crypto';
|
|
2
|
+
import { createDPoPFetch } from '../dpop.js';
|
|
2
3
|
import { CLIENT_ID, fetchClientAssertion, REDIRECT_URI } from '../environment.js';
|
|
3
4
|
import { FetchResponseError, OAuthResponseError, TokenRefreshError } from '../errors.js';
|
|
4
5
|
import { resolveFromIdentifier } from '../resolvers.js';
|
|
@@ -20,16 +21,11 @@ export class OAuthServerAgent {
|
|
|
20
21
|
}
|
|
21
22
|
if ((endpoint === 'token' || endpoint === 'pushed_authorization_request') &&
|
|
22
23
|
fetchClientAssertion !== undefined) {
|
|
23
|
-
const
|
|
24
|
-
if (jkt === undefined) {
|
|
25
|
-
throw new Error(`DPoP key missing jkt field`);
|
|
26
|
-
}
|
|
24
|
+
const sign = createDpopProofSigner(this.#dpopKey);
|
|
27
25
|
const assertion = await fetchClientAssertion({
|
|
28
|
-
jkt: jkt,
|
|
29
26
|
aud: this.#metadata.issuer,
|
|
30
|
-
createDpopProof: async (url) => {
|
|
31
|
-
|
|
32
|
-
return await sign('POST', url, undefined, undefined);
|
|
27
|
+
createDpopProof: async (url, nonce) => {
|
|
28
|
+
return await sign('POST', url, nonce, undefined);
|
|
33
29
|
},
|
|
34
30
|
});
|
|
35
31
|
payload = { ...payload, ...assertion };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-agent.js","sourceRoot":"","sources":["../../lib/agents/server-agent.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-agent.js","sourceRoot":"","sources":["../../lib/agents/server-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Did } from '@atcute/lexicons';
|
|
2
|
+
import type { Session } from '../types/token.ts';
|
|
2
3
|
export interface SessionGetOptions {
|
|
3
4
|
signal?: AbortSignal;
|
|
4
5
|
noCache?: boolean;
|
|
5
6
|
allowStale?: boolean;
|
|
6
7
|
}
|
|
7
|
-
export declare const getSession: (sub:
|
|
8
|
-
export declare const storeSession: (sub:
|
|
9
|
-
export declare const deleteStoredSession: (sub:
|
|
10
|
-
export declare const listStoredSessions: () =>
|
|
8
|
+
export declare const getSession: (sub: Did, options?: SessionGetOptions) => Promise<Session>;
|
|
9
|
+
export declare const storeSession: (sub: Did, newSession: Session) => Promise<void>;
|
|
10
|
+
export declare const deleteStoredSession: (sub: Did) => void;
|
|
11
|
+
export declare const listStoredSessions: () => Did[];
|
|
11
12
|
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../lib/agents/sessions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../lib/agents/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAI5C,OAAO,KAAK,EAAc,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAM7D,MAAM,WAAW,iBAAiB;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAKD,eAAO,MAAM,UAAU,QAAe,GAAG,YAAY,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAuEvF,CAAC;AAEF,eAAO,MAAM,YAAY,QAAe,GAAG,cAAc,OAAO,KAAG,OAAO,CAAC,IAAI,CAO9E,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAS,GAAG,KAAG,IAE9C,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,GAAG,EAExC,CAAC"}
|
package/dist/agents/sessions.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { database } from '../environment.js';
|
|
2
2
|
import { OAuthResponseError, TokenRefreshError } from '../errors.js';
|
|
3
|
+
import { isLegacyDpopKey, migrateLegacyDpopKey } from '../utils/dpop-key.js';
|
|
3
4
|
import { locks } from '../utils/runtime.js';
|
|
4
5
|
import { OAuthServerAgent } from './server-agent.js';
|
|
5
6
|
const pending = new Map();
|
|
@@ -33,7 +34,7 @@ export const getSession = async (sub, options) => {
|
|
|
33
34
|
options?.signal?.throwIfAborted();
|
|
34
35
|
}
|
|
35
36
|
const run = async () => {
|
|
36
|
-
const storedSession = database.sessions.get(sub);
|
|
37
|
+
const storedSession = await migrateSessionIfNeeded(sub, database.sessions.get(sub));
|
|
37
38
|
if (storedSession && allowStored(storedSession)) {
|
|
38
39
|
// Use the stored value as return value for the current execution
|
|
39
40
|
// flow. Notify other concurrent execution flows (that should be
|
|
@@ -107,4 +108,18 @@ const isTokenUsable = ({ token }) => {
|
|
|
107
108
|
const expires = token.expires_at;
|
|
108
109
|
return expires == null || Date.now() + 60_000 <= expires;
|
|
109
110
|
};
|
|
111
|
+
const migrateSessionIfNeeded = async (sub, session) => {
|
|
112
|
+
if (!session || !isLegacyDpopKey(session.dpopKey)) {
|
|
113
|
+
return session;
|
|
114
|
+
}
|
|
115
|
+
const dpopKey = await migrateLegacyDpopKey(session.dpopKey);
|
|
116
|
+
const migrated = { ...session, dpopKey };
|
|
117
|
+
try {
|
|
118
|
+
database.sessions.set(sub, migrated);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// ignore persistence errors
|
|
122
|
+
}
|
|
123
|
+
return migrated;
|
|
124
|
+
};
|
|
110
125
|
//# sourceMappingURL=sessions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../lib/agents/sessions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAErE,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AASrD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsC,CAAC;AAE9D,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,GAAQ,EAAE,OAA2B,EAAoB,EAAE
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../lib/agents/sessions.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FetchHandlerObject } from '@atcute/client';
|
|
2
2
|
import type { Did } from '@atcute/lexicons';
|
|
3
|
-
import type { Session } from '../types/token.
|
|
4
|
-
import { type SessionGetOptions } from './sessions.
|
|
3
|
+
import type { Session } from '../types/token.ts';
|
|
4
|
+
import { type SessionGetOptions } from './sessions.ts';
|
|
5
5
|
export declare class OAuthUserAgent implements FetchHandlerObject {
|
|
6
6
|
#private;
|
|
7
7
|
session: Session;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-agent.d.ts","sourceRoot":"","sources":["../../lib/agents/user-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,KAAK,iBAAiB,EAAmC,MAAM,eAAe,CAAC;AAExF,qBAAa,cAAe,YAAW,kBAAkB;;
|
|
1
|
+
{"version":3,"file":"user-agent.d.ts","sourceRoot":"","sources":["../../lib/agents/user-agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAG5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,EAAE,KAAK,iBAAiB,EAAmC,MAAM,eAAe,CAAC;AAExF,qBAAa,cAAe,YAAW,kBAAkB;;IAIxD,OAAO,EAAE,OAAO,CAAC;IAEjB,YAAY,OAAO,EAAE,OAAO,EAG3B;IAED,IAAI,GAAG,IAAI,GAAG,CAEb;IAED,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAexD;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAW7B;IAEK,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkCpE;CACD"}
|
|
@@ -2,9 +2,9 @@ import { createDPoPFetch } from '../dpop.js';
|
|
|
2
2
|
import { OAuthServerAgent } from './server-agent.js';
|
|
3
3
|
import { deleteStoredSession, getSession } from './sessions.js';
|
|
4
4
|
export class OAuthUserAgent {
|
|
5
|
-
session;
|
|
6
5
|
#fetch;
|
|
7
6
|
#getSessionPromise;
|
|
7
|
+
session;
|
|
8
8
|
constructor(session) {
|
|
9
9
|
this.session = session;
|
|
10
10
|
this.#fetch = createDPoPFetch(session.dpopKey, false);
|
|
@@ -17,7 +17,7 @@ export class OAuthUserAgent {
|
|
|
17
17
|
promise
|
|
18
18
|
.then((session) => {
|
|
19
19
|
this.session = session;
|
|
20
|
-
})
|
|
20
|
+
}, () => { })
|
|
21
21
|
.finally(() => {
|
|
22
22
|
this.#getSessionPromise = undefined;
|
|
23
23
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-agent.js","sourceRoot":"","sources":["../../lib/agents/user-agent.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAA0B,mBAAmB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAExF,MAAM,OAAO,cAAc;
|
|
1
|
+
{"version":3,"file":"user-agent.js","sourceRoot":"","sources":["../../lib/agents/user-agent.ts"],"names":[],"mappings":"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"}
|
package/dist/dpop.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const createDPoPSignage: (dpopKey: DPoPKey) => (method: string, htu: string, nonce: string | undefined, ath: string | undefined) => Promise<string>;
|
|
4
|
-
export declare const createDPoPFetch: (dpopKey: DPoPKey, isAuthServer?: boolean | undefined) => typeof fetch;
|
|
1
|
+
import { type DpopPrivateJwk } from '@atcute/oauth-crypto';
|
|
2
|
+
export declare const createDPoPFetch: (dpopKey: DpopPrivateJwk, isAuthServer?: boolean) => typeof fetch;
|
|
5
3
|
//# sourceMappingURL=dpop.d.ts.map
|
package/dist/dpop.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dpop.d.ts","sourceRoot":"","sources":["../lib/dpop.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dpop.d.ts","sourceRoot":"","sources":["../lib/dpop.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAKnG,eAAO,MAAM,eAAe,YAAa,cAAc,iBAAiB,OAAO,KAAG,OAAO,KA4FxF,CAAC"}
|
package/dist/dpop.js
CHANGED
|
@@ -1,92 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { encodeUtf8 } from '@atcute/uint8array';
|
|
3
|
-
import { nanoid } from 'nanoid';
|
|
1
|
+
import { createDpopProofSigner, sha256Base64Url } from '@atcute/oauth-crypto';
|
|
4
2
|
import { database } from './environment.js';
|
|
5
3
|
import { extractContentType } from './utils/response.js';
|
|
6
|
-
import { stringToSha256 } from './utils/runtime.js';
|
|
7
|
-
const ES256_ALG = { name: 'ECDSA', namedCurve: 'P-256' };
|
|
8
|
-
export const createES256Key = async () => {
|
|
9
|
-
const pair = await crypto.subtle.generateKey(ES256_ALG, true, ['sign', 'verify']);
|
|
10
|
-
const key = await crypto.subtle.exportKey('pkcs8', pair.privateKey);
|
|
11
|
-
const { ext: _ext, key_ops: _key_opts, ...jwk } = await crypto.subtle.exportKey('jwk', pair.publicKey);
|
|
12
|
-
const canonicalJwk = JSON.stringify({ crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y });
|
|
13
|
-
const jkt = await stringToSha256(canonicalJwk);
|
|
14
|
-
return {
|
|
15
|
-
typ: 'ES256',
|
|
16
|
-
key: toBase64Url(new Uint8Array(key)),
|
|
17
|
-
jwt: toBase64Url(encodeUtf8(JSON.stringify({ typ: 'dpop+jwt', alg: 'ES256', jwk: jwk }))),
|
|
18
|
-
jkt: jkt,
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
export const createDPoPSignage = (dpopKey) => {
|
|
22
|
-
const headerString = dpopKey.jwt;
|
|
23
|
-
const keyPromise = crypto.subtle.importKey('pkcs8', fromBase64Url(dpopKey.key), ES256_ALG, true, ['sign']);
|
|
24
|
-
const constructPayload = (htm, htu, nonce, ath) => {
|
|
25
|
-
const payload = {
|
|
26
|
-
ath: ath,
|
|
27
|
-
htm: htm,
|
|
28
|
-
htu: htu,
|
|
29
|
-
iat: Math.floor(Date.now() / 1_000),
|
|
30
|
-
jti: nanoid(24),
|
|
31
|
-
nonce: nonce,
|
|
32
|
-
};
|
|
33
|
-
return toBase64Url(encodeUtf8(JSON.stringify(payload)));
|
|
34
|
-
};
|
|
35
|
-
return async (method, htu, nonce, ath) => {
|
|
36
|
-
const payloadString = constructPayload(method, htu, nonce, ath);
|
|
37
|
-
const signed = await crypto.subtle.sign({ name: 'ECDSA', hash: { name: 'SHA-256' } }, await keyPromise, encodeUtf8(headerString + '.' + payloadString));
|
|
38
|
-
const signatureString = toBase64Url(new Uint8Array(signed));
|
|
39
|
-
return headerString + '.' + payloadString + '.' + signatureString;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
4
|
export const createDPoPFetch = (dpopKey, isAuthServer) => {
|
|
43
5
|
const nonces = database.dpopNonces;
|
|
44
6
|
const pending = database.inflightDpop;
|
|
45
|
-
const sign =
|
|
7
|
+
const sign = createDpopProofSigner(dpopKey);
|
|
46
8
|
return async (input, init) => {
|
|
47
9
|
const request = new Request(input, init);
|
|
48
10
|
const authorizationHeader = request.headers.get('authorization');
|
|
49
11
|
const ath = authorizationHeader?.startsWith('DPoP ')
|
|
50
|
-
? await
|
|
12
|
+
? await sha256Base64Url(authorizationHeader.slice(5))
|
|
51
13
|
: undefined;
|
|
52
14
|
const { method, url } = request;
|
|
53
15
|
const { origin, pathname } = new URL(url);
|
|
54
16
|
const htu = origin + pathname;
|
|
55
|
-
// See if we have a pending promise for this origin, we'll await before
|
|
56
|
-
// proceeding with this request, next comment describes what the promise
|
|
57
|
-
// is meant to be.
|
|
58
17
|
let deferred = pending.get(origin);
|
|
59
18
|
if (deferred) {
|
|
60
19
|
await deferred.promise;
|
|
61
20
|
deferred = undefined;
|
|
62
21
|
}
|
|
63
|
-
// Get our persisted nonce value for this origin
|
|
64
22
|
let initNonce;
|
|
65
23
|
let expiredOrMissing = false;
|
|
66
24
|
try {
|
|
67
25
|
const [nonce, lapsed] = nonces.getWithLapsed(origin);
|
|
68
26
|
initNonce = nonce;
|
|
69
|
-
// The problem with DPoP nonces is that we don't have insight as to when
|
|
70
|
-
// they'll expire, either we have a nonce value or we don't.
|
|
71
|
-
//
|
|
72
|
-
// Which is very unfortunate, if the client makes multiple requests at the
|
|
73
|
-
// same time, there's a chance that all of them will fail due to the nonce
|
|
74
|
-
// value having expired.
|
|
75
|
-
//
|
|
76
|
-
// To make this less painful, if it's been over 3 minutes since we last
|
|
77
|
-
// had a nonce value, or we never had one to begin with, we'll let this
|
|
78
|
-
// request through and defer everyone else until we get a possibly fresh
|
|
79
|
-
// nonce value.
|
|
80
|
-
//
|
|
81
|
-
// 3 minutes being the DPoP nonce expiration time set by the reference PDS
|
|
82
|
-
// implementation.
|
|
83
27
|
expiredOrMissing = lapsed > 3 * 60 * 1_000;
|
|
84
28
|
}
|
|
85
29
|
catch {
|
|
86
|
-
//
|
|
30
|
+
// ignore read errors
|
|
87
31
|
}
|
|
88
32
|
if (expiredOrMissing) {
|
|
89
|
-
// Defer everyone else until this request finishes.
|
|
90
33
|
pending.set(origin, (deferred = Promise.withResolvers()));
|
|
91
34
|
}
|
|
92
35
|
let nextNonce;
|
|
@@ -96,52 +39,40 @@ export const createDPoPFetch = (dpopKey, isAuthServer) => {
|
|
|
96
39
|
const initResponse = await fetch(request);
|
|
97
40
|
nextNonce = initResponse.headers.get('dpop-nonce');
|
|
98
41
|
if (nextNonce === null || nextNonce === initNonce) {
|
|
99
|
-
// No nonce was returned or it is the same as the one we sent. No need to
|
|
100
|
-
// update the nonce store, or retry the request.
|
|
101
42
|
return initResponse;
|
|
102
43
|
}
|
|
103
|
-
// Store the fresh nonce for future requests
|
|
104
44
|
try {
|
|
105
45
|
nonces.set(origin, nextNonce);
|
|
106
46
|
}
|
|
107
47
|
catch {
|
|
108
|
-
//
|
|
48
|
+
// ignore write errors
|
|
109
49
|
}
|
|
110
50
|
const shouldRetry = await isUseDpopNonceError(initResponse, isAuthServer);
|
|
111
51
|
if (!shouldRetry) {
|
|
112
|
-
// Not a "use_dpop_nonce" error, so there is no need to retry
|
|
113
52
|
return initResponse;
|
|
114
53
|
}
|
|
115
54
|
if (input === request || init?.body instanceof ReadableStream) {
|
|
116
|
-
// If the input stream was already consumed, we cannot retry the request. A
|
|
117
|
-
// solution would be to clone() the request but that would bufferize the
|
|
118
|
-
// entire stream in memory which can lead to memory starvation. Instead, we
|
|
119
|
-
// will return the original response and let the calling code handle retries.
|
|
120
55
|
return initResponse;
|
|
121
56
|
}
|
|
122
57
|
}
|
|
123
58
|
finally {
|
|
124
|
-
// Now everyone can have their turn.
|
|
125
59
|
if (deferred) {
|
|
126
60
|
pending.delete(origin);
|
|
127
61
|
deferred.resolve();
|
|
128
62
|
}
|
|
129
63
|
}
|
|
130
|
-
// We got here because we were asked to retry the request (due to missing
|
|
131
|
-
// nonce value in the first request), let's do just that.
|
|
132
64
|
{
|
|
133
65
|
const nextProof = await sign(method, htu, nextNonce, ath);
|
|
134
66
|
const nextRequest = new Request(input, init);
|
|
135
67
|
nextRequest.headers.set('dpop', nextProof);
|
|
136
68
|
const retryResponse = await fetch(nextRequest);
|
|
137
|
-
// Check if the server returned another new nonce in the retry response
|
|
138
69
|
const retryNonce = retryResponse.headers.get('dpop-nonce');
|
|
139
70
|
if (retryNonce !== null && retryNonce !== nextNonce) {
|
|
140
71
|
try {
|
|
141
72
|
nonces.set(origin, retryNonce);
|
|
142
73
|
}
|
|
143
74
|
catch {
|
|
144
|
-
//
|
|
75
|
+
// ignore write errors
|
|
145
76
|
}
|
|
146
77
|
}
|
|
147
78
|
return retryResponse;
|
|
@@ -149,8 +80,6 @@ export const createDPoPFetch = (dpopKey, isAuthServer) => {
|
|
|
149
80
|
};
|
|
150
81
|
};
|
|
151
82
|
const isUseDpopNonceError = async (response, isAuthServer) => {
|
|
152
|
-
// https://datatracker.ietf.org/doc/html/rfc6750#section-3
|
|
153
|
-
// https://datatracker.ietf.org/doc/html/rfc9449#name-resource-server-provided-no
|
|
154
83
|
if (isAuthServer === undefined || isAuthServer === false) {
|
|
155
84
|
if (response.status === 401) {
|
|
156
85
|
const wwwAuth = response.headers.get('www-authenticate');
|
|
@@ -159,7 +88,6 @@ const isUseDpopNonceError = async (response, isAuthServer) => {
|
|
|
159
88
|
}
|
|
160
89
|
}
|
|
161
90
|
}
|
|
162
|
-
// https://datatracker.ietf.org/doc/html/rfc9449#name-authorization-server-provid
|
|
163
91
|
if (isAuthServer === undefined || isAuthServer === true) {
|
|
164
92
|
if (response.status === 400 && extractContentType(response.headers) === 'application/json') {
|
|
165
93
|
try {
|
|
@@ -167,7 +95,6 @@ const isUseDpopNonceError = async (response, isAuthServer) => {
|
|
|
167
95
|
return typeof json === 'object' && json?.['error'] === 'use_dpop_nonce';
|
|
168
96
|
}
|
|
169
97
|
catch {
|
|
170
|
-
// Response too big (to be "use_dpop_nonce" error) or invalid JSON
|
|
171
98
|
return false;
|
|
172
99
|
}
|
|
173
100
|
}
|
package/dist/dpop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dpop.js","sourceRoot":"","sources":["../lib/dpop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"dpop.js","sourceRoot":"","sources":["../lib/dpop.ts"],"names":[],"mappings":"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"}
|