@atproto/oauth-provider 0.20.2 → 0.21.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 (37) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/account/login-hint.d.ts +10 -0
  3. package/dist/account/login-hint.d.ts.map +1 -0
  4. package/dist/account/login-hint.js +19 -0
  5. package/dist/account/login-hint.js.map +1 -0
  6. package/dist/client/client-manager.d.ts.map +1 -1
  7. package/dist/client/client-manager.js +4 -6
  8. package/dist/client/client-manager.js.map +1 -1
  9. package/dist/client/client.d.ts +16 -0
  10. package/dist/client/client.d.ts.map +1 -1
  11. package/dist/client/client.js +31 -1
  12. package/dist/client/client.js.map +1 -1
  13. package/dist/oauth-constants.d.ts +14 -8
  14. package/dist/oauth-constants.d.ts.map +1 -1
  15. package/dist/oauth-constants.js +14 -8
  16. package/dist/oauth-constants.js.map +1 -1
  17. package/dist/oauth-provider.d.ts +1 -1
  18. package/dist/oauth-provider.d.ts.map +1 -1
  19. package/dist/oauth-provider.js +14 -14
  20. package/dist/oauth-provider.js.map +1 -1
  21. package/dist/request/request-manager.d.ts.map +1 -1
  22. package/dist/request/request-manager.js +4 -4
  23. package/dist/request/request-manager.js.map +1 -1
  24. package/dist/result/authorization-result-authorize-page.d.ts +6 -0
  25. package/dist/result/authorization-result-authorize-page.d.ts.map +1 -1
  26. package/dist/result/authorization-result-authorize-page.js.map +1 -1
  27. package/dist/router/assets/send-authorization-page.js +3 -3
  28. package/dist/router/assets/send-authorization-page.js.map +1 -1
  29. package/dist/router/create-api-middleware.d.ts.map +1 -1
  30. package/dist/router/create-api-middleware.js +27 -5
  31. package/dist/router/create-api-middleware.js.map +1 -1
  32. package/dist/signer/access-token-payload.d.ts +39 -39
  33. package/dist/token/token-manager.d.ts +2 -2
  34. package/dist/token/token-manager.d.ts.map +1 -1
  35. package/dist/token/token-manager.js +22 -8
  36. package/dist/token/token-manager.js.map +1 -1
  37. package/package.json +14 -12
@@ -1219,7 +1219,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1219
1219
  alg?: "HS256" | "HS384" | "HS512" | undefined;
1220
1220
  k: string;
1221
1221
  }) & {
1222
- kid: {};
1222
+ kid: NonNullable<unknown>;
1223
1223
  }, {
1224
1224
  kid?: string | undefined;
1225
1225
  use?: "enc" | "sig" | undefined;
@@ -1367,7 +1367,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1367
1367
  t?: string | undefined;
1368
1368
  }[] | undefined;
1369
1369
  } & {
1370
- kid: {};
1370
+ kid: NonNullable<unknown>;
1371
1371
  }) | ({
1372
1372
  kid?: string | undefined;
1373
1373
  use?: "enc" | "sig" | undefined;
@@ -1391,7 +1391,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1391
1391
  y: string;
1392
1392
  d?: string | undefined;
1393
1393
  } & {
1394
- kid: {};
1394
+ kid: NonNullable<unknown>;
1395
1395
  }) | ({
1396
1396
  kid?: string | undefined;
1397
1397
  use?: "enc" | "sig" | undefined;
@@ -1415,7 +1415,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1415
1415
  y: string;
1416
1416
  d?: string | undefined;
1417
1417
  } & {
1418
- kid: {};
1418
+ kid: NonNullable<unknown>;
1419
1419
  }) | ({
1420
1420
  kid?: string | undefined;
1421
1421
  use?: "enc" | "sig" | undefined;
@@ -1438,7 +1438,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1438
1438
  x: string;
1439
1439
  d?: string | undefined;
1440
1440
  } & {
1441
- kid: {};
1441
+ kid: NonNullable<unknown>;
1442
1442
  })) & {
1443
1443
  d?: never;
1444
1444
  }, {
@@ -1588,7 +1588,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1588
1588
  t?: string | undefined;
1589
1589
  }[] | undefined;
1590
1590
  } & {
1591
- kid: {};
1591
+ kid: NonNullable<unknown>;
1592
1592
  }) | ({
1593
1593
  kid?: string | undefined;
1594
1594
  use?: "enc" | "sig" | undefined;
@@ -1612,7 +1612,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1612
1612
  y: string;
1613
1613
  d?: string | undefined;
1614
1614
  } & {
1615
- kid: {};
1615
+ kid: NonNullable<unknown>;
1616
1616
  }) | ({
1617
1617
  kid?: string | undefined;
1618
1618
  use?: "enc" | "sig" | undefined;
@@ -1636,7 +1636,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1636
1636
  y: string;
1637
1637
  d?: string | undefined;
1638
1638
  } & {
1639
- kid: {};
1639
+ kid: NonNullable<unknown>;
1640
1640
  }) | ({
1641
1641
  kid?: string | undefined;
1642
1642
  use?: "enc" | "sig" | undefined;
@@ -1659,7 +1659,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1659
1659
  x: string;
1660
1660
  d?: string | undefined;
1661
1661
  } & {
1662
- kid: {};
1662
+ kid: NonNullable<unknown>;
1663
1663
  })) & {
1664
1664
  d?: never;
1665
1665
  }, {
@@ -1817,7 +1817,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1817
1817
  t?: string | undefined;
1818
1818
  }[] | undefined;
1819
1819
  } & {
1820
- kid: {};
1820
+ kid: NonNullable<unknown>;
1821
1821
  }) | ({
1822
1822
  kid?: string | undefined;
1823
1823
  use?: "enc" | "sig" | undefined;
@@ -1841,7 +1841,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1841
1841
  y: string;
1842
1842
  d?: string | undefined;
1843
1843
  } & {
1844
- kid: {};
1844
+ kid: NonNullable<unknown>;
1845
1845
  }) | ({
1846
1846
  kid?: string | undefined;
1847
1847
  use?: "enc" | "sig" | undefined;
@@ -1865,7 +1865,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1865
1865
  y: string;
1866
1866
  d?: string | undefined;
1867
1867
  } & {
1868
- kid: {};
1868
+ kid: NonNullable<unknown>;
1869
1869
  }) | ({
1870
1870
  kid?: string | undefined;
1871
1871
  use?: "enc" | "sig" | undefined;
@@ -1888,7 +1888,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
1888
1888
  x: string;
1889
1889
  d?: string | undefined;
1890
1890
  } & {
1891
- kid: {};
1891
+ kid: NonNullable<unknown>;
1892
1892
  })) & {
1893
1893
  d?: never;
1894
1894
  }) | undefined;
@@ -3317,7 +3317,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3317
3317
  alg?: "HS256" | "HS384" | "HS512" | undefined;
3318
3318
  k: string;
3319
3319
  }) & {
3320
- kid: {};
3320
+ kid: NonNullable<unknown>;
3321
3321
  }, {
3322
3322
  kid?: string | undefined;
3323
3323
  use?: "enc" | "sig" | undefined;
@@ -3465,7 +3465,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3465
3465
  t?: string | undefined;
3466
3466
  }[] | undefined;
3467
3467
  } & {
3468
- kid: {};
3468
+ kid: NonNullable<unknown>;
3469
3469
  }) | ({
3470
3470
  kid?: string | undefined;
3471
3471
  use?: "enc" | "sig" | undefined;
@@ -3489,7 +3489,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3489
3489
  y: string;
3490
3490
  d?: string | undefined;
3491
3491
  } & {
3492
- kid: {};
3492
+ kid: NonNullable<unknown>;
3493
3493
  }) | ({
3494
3494
  kid?: string | undefined;
3495
3495
  use?: "enc" | "sig" | undefined;
@@ -3513,7 +3513,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3513
3513
  y: string;
3514
3514
  d?: string | undefined;
3515
3515
  } & {
3516
- kid: {};
3516
+ kid: NonNullable<unknown>;
3517
3517
  }) | ({
3518
3518
  kid?: string | undefined;
3519
3519
  use?: "enc" | "sig" | undefined;
@@ -3536,7 +3536,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3536
3536
  x: string;
3537
3537
  d?: string | undefined;
3538
3538
  } & {
3539
- kid: {};
3539
+ kid: NonNullable<unknown>;
3540
3540
  })) & {
3541
3541
  d?: never;
3542
3542
  }, {
@@ -3686,7 +3686,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3686
3686
  t?: string | undefined;
3687
3687
  }[] | undefined;
3688
3688
  } & {
3689
- kid: {};
3689
+ kid: NonNullable<unknown>;
3690
3690
  }) | ({
3691
3691
  kid?: string | undefined;
3692
3692
  use?: "enc" | "sig" | undefined;
@@ -3710,7 +3710,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3710
3710
  y: string;
3711
3711
  d?: string | undefined;
3712
3712
  } & {
3713
- kid: {};
3713
+ kid: NonNullable<unknown>;
3714
3714
  }) | ({
3715
3715
  kid?: string | undefined;
3716
3716
  use?: "enc" | "sig" | undefined;
@@ -3734,7 +3734,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3734
3734
  y: string;
3735
3735
  d?: string | undefined;
3736
3736
  } & {
3737
- kid: {};
3737
+ kid: NonNullable<unknown>;
3738
3738
  }) | ({
3739
3739
  kid?: string | undefined;
3740
3740
  use?: "enc" | "sig" | undefined;
@@ -3757,7 +3757,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3757
3757
  x: string;
3758
3758
  d?: string | undefined;
3759
3759
  } & {
3760
- kid: {};
3760
+ kid: NonNullable<unknown>;
3761
3761
  })) & {
3762
3762
  d?: never;
3763
3763
  }, {
@@ -3915,7 +3915,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3915
3915
  t?: string | undefined;
3916
3916
  }[] | undefined;
3917
3917
  } & {
3918
- kid: {};
3918
+ kid: NonNullable<unknown>;
3919
3919
  }) | ({
3920
3920
  kid?: string | undefined;
3921
3921
  use?: "enc" | "sig" | undefined;
@@ -3939,7 +3939,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3939
3939
  y: string;
3940
3940
  d?: string | undefined;
3941
3941
  } & {
3942
- kid: {};
3942
+ kid: NonNullable<unknown>;
3943
3943
  }) | ({
3944
3944
  kid?: string | undefined;
3945
3945
  use?: "enc" | "sig" | undefined;
@@ -3963,7 +3963,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3963
3963
  y: string;
3964
3964
  d?: string | undefined;
3965
3965
  } & {
3966
- kid: {};
3966
+ kid: NonNullable<unknown>;
3967
3967
  }) | ({
3968
3968
  kid?: string | undefined;
3969
3969
  use?: "enc" | "sig" | undefined;
@@ -3986,7 +3986,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
3986
3986
  x: string;
3987
3987
  d?: string | undefined;
3988
3988
  } & {
3989
- kid: {};
3989
+ kid: NonNullable<unknown>;
3990
3990
  })) & {
3991
3991
  d?: never;
3992
3992
  }) | undefined;
@@ -5415,7 +5415,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5415
5415
  alg?: "HS256" | "HS384" | "HS512" | undefined;
5416
5416
  k: string;
5417
5417
  }) & {
5418
- kid: {};
5418
+ kid: NonNullable<unknown>;
5419
5419
  }, {
5420
5420
  kid?: string | undefined;
5421
5421
  use?: "enc" | "sig" | undefined;
@@ -5563,7 +5563,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5563
5563
  t?: string | undefined;
5564
5564
  }[] | undefined;
5565
5565
  } & {
5566
- kid: {};
5566
+ kid: NonNullable<unknown>;
5567
5567
  }) | ({
5568
5568
  kid?: string | undefined;
5569
5569
  use?: "enc" | "sig" | undefined;
@@ -5587,7 +5587,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5587
5587
  y: string;
5588
5588
  d?: string | undefined;
5589
5589
  } & {
5590
- kid: {};
5590
+ kid: NonNullable<unknown>;
5591
5591
  }) | ({
5592
5592
  kid?: string | undefined;
5593
5593
  use?: "enc" | "sig" | undefined;
@@ -5611,7 +5611,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5611
5611
  y: string;
5612
5612
  d?: string | undefined;
5613
5613
  } & {
5614
- kid: {};
5614
+ kid: NonNullable<unknown>;
5615
5615
  }) | ({
5616
5616
  kid?: string | undefined;
5617
5617
  use?: "enc" | "sig" | undefined;
@@ -5634,7 +5634,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5634
5634
  x: string;
5635
5635
  d?: string | undefined;
5636
5636
  } & {
5637
- kid: {};
5637
+ kid: NonNullable<unknown>;
5638
5638
  })) & {
5639
5639
  d?: never;
5640
5640
  }, {
@@ -5784,7 +5784,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5784
5784
  t?: string | undefined;
5785
5785
  }[] | undefined;
5786
5786
  } & {
5787
- kid: {};
5787
+ kid: NonNullable<unknown>;
5788
5788
  }) | ({
5789
5789
  kid?: string | undefined;
5790
5790
  use?: "enc" | "sig" | undefined;
@@ -5808,7 +5808,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5808
5808
  y: string;
5809
5809
  d?: string | undefined;
5810
5810
  } & {
5811
- kid: {};
5811
+ kid: NonNullable<unknown>;
5812
5812
  }) | ({
5813
5813
  kid?: string | undefined;
5814
5814
  use?: "enc" | "sig" | undefined;
@@ -5832,7 +5832,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5832
5832
  y: string;
5833
5833
  d?: string | undefined;
5834
5834
  } & {
5835
- kid: {};
5835
+ kid: NonNullable<unknown>;
5836
5836
  }) | ({
5837
5837
  kid?: string | undefined;
5838
5838
  use?: "enc" | "sig" | undefined;
@@ -5855,7 +5855,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
5855
5855
  x: string;
5856
5856
  d?: string | undefined;
5857
5857
  } & {
5858
- kid: {};
5858
+ kid: NonNullable<unknown>;
5859
5859
  })) & {
5860
5860
  d?: never;
5861
5861
  }, {
@@ -6013,7 +6013,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
6013
6013
  t?: string | undefined;
6014
6014
  }[] | undefined;
6015
6015
  } & {
6016
- kid: {};
6016
+ kid: NonNullable<unknown>;
6017
6017
  }) | ({
6018
6018
  kid?: string | undefined;
6019
6019
  use?: "enc" | "sig" | undefined;
@@ -6037,7 +6037,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
6037
6037
  y: string;
6038
6038
  d?: string | undefined;
6039
6039
  } & {
6040
- kid: {};
6040
+ kid: NonNullable<unknown>;
6041
6041
  }) | ({
6042
6042
  kid?: string | undefined;
6043
6043
  use?: "enc" | "sig" | undefined;
@@ -6061,7 +6061,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
6061
6061
  y: string;
6062
6062
  d?: string | undefined;
6063
6063
  } & {
6064
- kid: {};
6064
+ kid: NonNullable<unknown>;
6065
6065
  }) | ({
6066
6066
  kid?: string | undefined;
6067
6067
  use?: "enc" | "sig" | undefined;
@@ -6084,7 +6084,7 @@ export declare const accessTokenPayloadSchema: z.ZodObject<z.objectUtil.extendSh
6084
6084
  x: string;
6085
6085
  d?: string | undefined;
6086
6086
  } & {
6087
- kid: {};
6087
+ kid: NonNullable<unknown>;
6088
6088
  })) & {
6089
6089
  d?: never;
6090
6090
  }) | undefined;
@@ -26,12 +26,12 @@ export declare class TokenManager {
26
26
  protected readonly accessTokenMode: AccessTokenMode;
27
27
  protected readonly tokenMaxAge: number;
28
28
  constructor(store: TokenStore, lexiconManager: LexiconManager, signer: Signer, hooks: OAuthHooks, accessTokenMode: AccessTokenMode, tokenMaxAge?: number);
29
- protected createTokenExpiry(now?: Date): Date;
29
+ protected createTokenExpiry(client: Client, now: Date, sessionCreationDate?: Date): Date;
30
30
  protected createAccessToken(tokenId: TokenId, client: Client, account: Account, parameters: OAuthAuthorizationRequestParameters, issuedAt: Date, expiresAt: Date, scope: OAuthScope): Promise<OAuthAccessToken>;
31
31
  createToken(client: Client, clientAuth: ClientAuth, clientMetadata: RequestMetadata, account: Account, deviceId: null | DeviceId, parameters: OAuthAuthorizationRequestParameters, code: Code): Promise<OAuthTokenResponse>;
32
32
  protected validateTokenParams(client: Client, clientAuth: ClientAuth, parameters: OAuthAuthorizationRequestParameters): Promise<void>;
33
33
  protected buildTokenResponse(tokenType: OAuthTokenType, accessToken: OAuthAccessToken, refreshToken: string | undefined, expiresAt: Date, did: Did, scope: string): OAuthTokenResponse;
34
- rotateToken(client: Client, clientAuth: ClientAuth, clientMetadata: RequestMetadata, tokenInfo: TokenInfo): Promise<OAuthTokenResponse>;
34
+ rotateToken(client: Client, clientAuth: ClientAuth, clientMetadata: RequestMetadata, tokenInfo: TokenInfo, now?: Date): Promise<OAuthTokenResponse>;
35
35
  /**
36
36
  * @note The token validity is not guaranteed. The caller must ensure that the
37
37
  * token is valid before using the returned token info.
@@ -1 +1 @@
1
- {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/token/token-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/token/token-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,cAAc,CAAA;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,KAAK,EACV,gBAAgB,EAChB,mCAAmC,EACnC,UAAU,EACV,kBAAkB,EAClB,cAAc,EACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAA;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAItD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAO7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,KAAK,IAAI,EAAU,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,KAAK,OAAO,EAA8B,MAAM,eAAe,CAAA;AACxE,OAAO,KAAK,EAAmB,SAAS,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE9E,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,CAAA;AAClC,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,CAAA;AAEtC,qBAAa,YAAY;IAErB,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU;IACpC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc;IACjD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACjC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,UAAU;IACpC,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,eAAe;IACnD,SAAS,CAAC,QAAQ,CAAC,WAAW;IANhC,YACqB,KAAK,EAAE,UAAU,EACjB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU,EACjB,eAAe,EAAE,eAAe,EAChC,WAAW,SAAgB,EAC5C;IAEJ,SAAS,CAAC,iBAAiB,CACzB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,IAAI,EACT,mBAAmB,GAAE,IAAU,GAC9B,IAAI,CAcN;IAED,UAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,mCAAmC,EAC/C,QAAQ,EAAE,IAAI,EACd,SAAS,EAAE,IAAI,EACf,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,gBAAgB,CAAC,CA8B3B;IAEK,WAAW,CACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,eAAe,EAC/B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,IAAI,GAAG,QAAQ,EACzB,UAAU,EAAE,mCAAmC,EAC/C,IAAI,EAAE,IAAI,GACT,OAAO,CAAC,kBAAkB,CAAC,CA0E7B;IAED,UAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,mCAAmC,GAC9C,OAAO,CAAC,IAAI,CAAC,CAMf;IAED,SAAS,CAAC,kBAAkB,CAC1B,SAAS,EAAE,cAAc,EACzB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,SAAS,EAAE,IAAI,EACf,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,MAAM,GACZ,kBAAkB,CAkBpB;IAEK,WAAW,CACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,cAAc,EAAE,eAAe,EAC/B,SAAS,EAAE,SAAS,EACpB,GAAG,OAAa,GACf,OAAO,CAAC,kBAAkB,CAAC,CA6D7B;IAED;;;OAGG;IACU,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAY/D;IAEY,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAiB1E;IAED,UAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAE3B;IAEY,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,CAAC,CAyBxE;IAEY,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAE7D;IAEY,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAExD;IAEK,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAE9D;IAED;;;;OAIG;IACG,eAAe,CACnB,SAAS,EAAE,cAAc,EACzB,YAAY,EAAE,kBAAkB,GAC/B,OAAO,CAAC,WAAW,CAAC,CAmCtB;IAEK,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CActD;CACF"}
@@ -5,7 +5,7 @@ import { InvalidGrantError } from '../errors/invalid-grant-error.js';
5
5
  import { InvalidRequestError } from '../errors/invalid-request-error.js';
6
6
  import { InvalidTokenError } from '../errors/invalid-token-error.js';
7
7
  import { dateToEpoch, dateToRelativeSeconds } from '../lib/util/date.js';
8
- import { TOKEN_MAX_AGE } from '../oauth-constants.js';
8
+ import { REFRESH_LIFETIME_EXTENDED, SESSION_LIFETIME_EXTENDED, TOKEN_MAX_AGE, } from '../oauth-constants.js';
9
9
  import { isCode } from '../request/code.js';
10
10
  import { Signer } from '../signer/signer.js';
11
11
  import { generateRefreshToken, isRefreshToken, } from './refresh-token.js';
@@ -20,8 +20,16 @@ export class TokenManager {
20
20
  this.accessTokenMode = accessTokenMode;
21
21
  this.tokenMaxAge = tokenMaxAge;
22
22
  }
23
- createTokenExpiry(now = new Date()) {
24
- return new Date(now.getTime() + this.tokenMaxAge);
23
+ createTokenExpiry(client, now, sessionCreationDate = now) {
24
+ const lifetime = Math.min(this.tokenMaxAge,
25
+ // Make sure the token does not stay valid beyond the session lifetime.
26
+ sessionCreationDate.getTime() + client.sessionLifetime - now.getTime());
27
+ // We account for a small buffer to avoid the token being valid for a few
28
+ // milliseconds
29
+ if (lifetime <= 250) {
30
+ throw new InvalidGrantError(`Session expired`);
31
+ }
32
+ return new Date(now.getTime() + lifetime);
25
33
  }
26
34
  async createAccessToken(tokenId, client, account, parameters, issuedAt, expiresAt, scope) {
27
35
  const claims = {
@@ -56,7 +64,7 @@ export class TokenManager {
56
64
  ? await generateRefreshToken()
57
65
  : undefined;
58
66
  const now = new Date();
59
- const expiresAt = this.createTokenExpiry(now);
67
+ const expiresAt = this.createTokenExpiry(client, now);
60
68
  const scope = await this.lexiconManager
61
69
  .buildTokenScope(parameters.scope)
62
70
  .catch((err) => {
@@ -122,14 +130,13 @@ export class TokenManager {
122
130
  sub: did,
123
131
  };
124
132
  }
125
- async rotateToken(client, clientAuth, clientMetadata, tokenInfo) {
133
+ async rotateToken(client, clientAuth, clientMetadata, tokenInfo, now = new Date()) {
126
134
  const { account, data } = tokenInfo;
127
135
  const { parameters } = data;
128
136
  await this.validateTokenParams(client, clientAuth, parameters);
129
137
  const nextTokenId = await generateTokenId();
130
138
  const nextRefreshToken = await generateRefreshToken();
131
- const now = new Date();
132
- const expiresAt = this.createTokenExpiry(now);
139
+ const expiresAt = this.createTokenExpiry(client, now, tokenInfo.data.createdAt);
133
140
  // @NOTE since the permission sets are stored in a persistent store,
134
141
  // it's fine to propagate a 500 (server_error) here as the values should
135
142
  // be retrievable from the store.
@@ -266,7 +273,14 @@ export class TokenManager {
266
273
  const results = await this.store.listAccountTokens(did);
267
274
  return results
268
275
  .filter((tokenInfo) => tokenInfo.account.did === did) // Fool proof
269
- .filter((tokenInfo) => !isCurrentTokenExpired(tokenInfo));
276
+ .filter(
277
+ // The session are still active if they are within the session lifetime
278
+ // and refresh lifetime. We pre-filter here, based on the maximum
279
+ // possible lifetime of a session, to avoid loading the client metadata
280
+ // for sessions that are for sure expired. The client metadata is needed
281
+ // to determine the actual session and refresh lifetimes.
282
+ ({ data }) => Date.now() - data.createdAt.getTime() < SESSION_LIFETIME_EXTENDED &&
283
+ Date.now() - data.updatedAt.getTime() < REFRESH_LIFETIME_EXTENDED);
270
284
  }
271
285
  }
272
286
  function isCurrentTokenExpired(tokenInfo) {
@@ -1 +1 @@
1
- {"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/token/token-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Did } from '@atproto/did'\nimport { type SignedJwt, isSignedJwt } from '@atproto/jwk'\nimport { LexResolverError } from '@atproto/lex-resolver'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport type {\n OAuthAccessToken,\n OAuthAuthorizationRequestParameters,\n OAuthScope,\n OAuthTokenResponse,\n OAuthTokenType,\n} from '@atproto/oauth-types'\nimport { AccessTokenMode } from '../access-token/access-token-mode.js'\nimport type { ClientAuth } from '../client/client-auth.js'\nimport type { Client } from '../client/client.js'\nimport type { DeviceId } from '../device/device-id.js'\nimport { InvalidGrantError } from '../errors/invalid-grant-error.js'\nimport { InvalidRequestError } from '../errors/invalid-request-error.js'\nimport { InvalidTokenError } from '../errors/invalid-token-error.js'\nimport type { LexiconManager } from '../lexicon/lexicon-manager.js'\nimport type { RequestMetadata } from '../lib/http/request.js'\nimport { dateToEpoch, dateToRelativeSeconds } from '../lib/util/date.js'\nimport { TOKEN_MAX_AGE } from '../oauth-constants.js'\nimport type { OAuthHooks } from '../oauth-hooks.js'\nimport { type Code, isCode } from '../request/code.js'\nimport type { AccessTokenPayload } from '../signer/access-token-payload.js'\nimport { Signer } from '../signer/signer.js'\nimport {\n type RefreshToken,\n generateRefreshToken,\n isRefreshToken,\n} from './refresh-token.js'\nimport type { TokenClaims } from './token-claims.js'\nimport { type TokenId, generateTokenId, isTokenId } from './token-id.js'\nimport type { CreateTokenData, TokenInfo, TokenStore } from './token-store.js'\n\nexport { AccessTokenMode, Signer }\nexport type { OAuthHooks, TokenStore }\n\nexport class TokenManager {\n constructor(\n protected readonly store: TokenStore,\n protected readonly lexiconManager: LexiconManager,\n protected readonly signer: Signer,\n protected readonly hooks: OAuthHooks,\n protected readonly accessTokenMode: AccessTokenMode,\n protected readonly tokenMaxAge = TOKEN_MAX_AGE,\n ) {}\n\n protected createTokenExpiry(now = new Date()) {\n return new Date(now.getTime() + this.tokenMaxAge)\n }\n\n protected async createAccessToken(\n tokenId: TokenId,\n client: Client,\n account: Account,\n parameters: OAuthAuthorizationRequestParameters,\n issuedAt: Date,\n expiresAt: Date,\n scope: OAuthScope,\n ): Promise<OAuthAccessToken> {\n const claims: TokenClaims = {\n jti: tokenId,\n sub: account.did,\n iat: dateToEpoch(issuedAt),\n exp: dateToEpoch(expiresAt),\n aud: account.pds,\n\n ...(parameters.dpop_jkt && {\n cnf: { jkt: parameters.dpop_jkt },\n }),\n\n // Because tokens can end-up being quite big, we only include the scope in\n // stateless mode.\n ...(this.accessTokenMode === AccessTokenMode.stateless && {\n scope,\n }),\n\n // https://datatracker.ietf.org/doc/html/rfc8693#section-4.3\n client_id: client.id,\n }\n\n const claimsOverride = await this.hooks.onCreateToken?.call(null, {\n client,\n account,\n parameters,\n claims,\n })\n\n return this.signer.createAccessToken(claimsOverride ?? claims)\n }\n\n async createToken(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n account: Account,\n deviceId: null | DeviceId,\n parameters: OAuthAuthorizationRequestParameters,\n code: Code,\n ): Promise<OAuthTokenResponse> {\n await this.validateTokenParams(client, clientAuth, parameters)\n\n const tokenId = await generateTokenId()\n const refreshToken = client.metadata.grant_types.includes('refresh_token')\n ? await generateRefreshToken()\n : undefined\n\n const now = new Date()\n const expiresAt = this.createTokenExpiry(now)\n\n const scope = await this.lexiconManager\n .buildTokenScope(parameters.scope!)\n .catch((err) => {\n // Parse expected errors\n if (err instanceof LexResolverError) {\n throw new InvalidRequestError(err.message, err)\n }\n\n // Unexpected error\n throw err\n })\n\n const accessToken = await this.createAccessToken(\n tokenId,\n client,\n account,\n parameters,\n now,\n expiresAt,\n scope,\n )\n\n const response = this.buildTokenResponse(\n inferTokenType(parameters),\n accessToken,\n refreshToken,\n expiresAt,\n account.did,\n scope,\n )\n\n const tokenData: CreateTokenData = {\n createdAt: now,\n updatedAt: now,\n expiresAt,\n clientId: client.id,\n clientAuth,\n deviceId,\n did: account.did,\n parameters,\n details: null,\n scope,\n code,\n }\n\n await this.store.createToken(tokenId, tokenData, refreshToken)\n\n try {\n await this.hooks.onTokenCreated?.call(null, {\n client,\n clientAuth,\n clientMetadata,\n account,\n parameters,\n })\n\n return response\n } catch (err) {\n // If the hook fails, we delete the token to avoid leaving a dangling\n // token in the store.\n await this.deleteToken(tokenId)\n throw err\n }\n }\n\n protected async validateTokenParams(\n client: Client,\n clientAuth: ClientAuth,\n parameters: OAuthAuthorizationRequestParameters,\n ): Promise<void> {\n if (client.metadata.dpop_bound_access_tokens && !parameters.dpop_jkt) {\n throw new InvalidGrantError(\n `DPoP JKT is required for DPoP bound access tokens`,\n )\n }\n }\n\n protected buildTokenResponse(\n tokenType: OAuthTokenType,\n accessToken: OAuthAccessToken,\n refreshToken: string | undefined,\n expiresAt: Date,\n did: Did,\n scope: string,\n ): OAuthTokenResponse {\n return {\n access_token: accessToken,\n token_type: tokenType,\n refresh_token: refreshToken,\n scope,\n\n // @NOTE using a getter so that the value gets computed when the JSON\n // response is generated, allowing to value to be as accurate as possible.\n get expires_in() {\n return dateToRelativeSeconds(expiresAt)\n },\n\n // ATPROTO extension: add the sub claim to the token response to allow\n // clients to resolve the PDS url (audience) using the did resolution\n // mechanism.\n sub: did,\n }\n }\n\n async rotateToken(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n tokenInfo: TokenInfo,\n ): Promise<OAuthTokenResponse> {\n const { account, data } = tokenInfo\n const { parameters } = data\n\n await this.validateTokenParams(client, clientAuth, parameters)\n\n const nextTokenId = await generateTokenId()\n const nextRefreshToken = await generateRefreshToken()\n\n const now = new Date()\n const expiresAt = this.createTokenExpiry(now)\n\n // @NOTE since the permission sets are stored in a persistent store,\n // it's fine to propagate a 500 (server_error) here as the values should\n // be retrievable from the store.\n const scope = await this.lexiconManager.buildTokenScope(parameters.scope!)\n\n await this.store.rotateToken(tokenInfo.id, nextTokenId, nextRefreshToken, {\n updatedAt: now,\n expiresAt,\n // @NOTE Normally, the clientAuth not change over time. There are two\n // exceptions:\n // - Upgrade from a legacy representation of client authentication to\n // a modern one.\n // - Allow clients to become \"confidential\" if they were previously\n // \"public\"\n clientAuth,\n scope,\n })\n\n const accessToken = await this.createAccessToken(\n nextTokenId,\n client,\n account,\n parameters,\n now,\n expiresAt,\n scope,\n )\n\n const response = this.buildTokenResponse(\n inferTokenType(parameters),\n accessToken,\n nextRefreshToken,\n expiresAt,\n account.did,\n scope,\n )\n\n await this.hooks.onTokenRefreshed?.call(null, {\n client,\n clientAuth,\n clientMetadata,\n account,\n parameters,\n })\n\n return response\n }\n\n /**\n * @note The token validity is not guaranteed. The caller must ensure that the\n * token is valid before using the returned token info.\n */\n public async findToken(token: string): Promise<null | TokenInfo> {\n if (isTokenId(token)) {\n return this.getTokenInfo(token)\n } else if (isCode(token)) {\n return this.findByCode(token)\n } else if (isRefreshToken(token)) {\n return this.findByRefreshToken(token)\n } else if (isSignedJwt(token)) {\n return this.findByAccessToken(token)\n } else {\n throw new InvalidRequestError(`Invalid token`)\n }\n }\n\n public async findByAccessToken(token: SignedJwt): Promise<null | TokenInfo> {\n const { payload } = await this.signer.verifyAccessToken(token, {\n clockTolerance: Infinity,\n })\n\n const tokenInfo = await this.getTokenInfo(payload.jti)\n if (!tokenInfo) return null\n\n // Fool-proof: Invalid store implementation ?\n if (payload.sub !== tokenInfo.account.did) {\n await this.deleteToken(tokenInfo.id)\n throw new Error(\n `Account sub (${tokenInfo.account.did}) does not match token sub (${payload.sub})`,\n )\n }\n\n return tokenInfo\n }\n\n protected async findByRefreshToken(\n token: RefreshToken,\n ): Promise<null | TokenInfo> {\n return this.store.findTokenByRefreshToken(token)\n }\n\n public async consumeRefreshToken(token: RefreshToken): Promise<TokenInfo> {\n // @NOTE concurrent refreshes of the same refresh token could theoretically\n // lead to two new tokens (access & refresh) being created. This is deemed\n // acceptable for now (as the mechanism can only be used once since only one\n // of the two refresh token created will be valid, and any future refresh\n // attempts from outdated tokens will cause the entire session to be\n // invalidated). Ideally, the store should be able to handle this case by\n // atomically consuming the refresh token and returning the token info.\n\n // @TODO Add another store method that atomically consumes the refresh token\n // with a lock.\n const tokenInfo = await this.findByRefreshToken(token).catch((err) => {\n throw InvalidGrantError.from(err, `Invalid refresh token`)\n })\n\n if (!tokenInfo) {\n throw new InvalidGrantError(`Invalid refresh token`)\n }\n\n if (tokenInfo.currentRefreshToken !== token) {\n await this.deleteToken(tokenInfo.id)\n throw new InvalidGrantError(`Refresh token replayed`)\n }\n\n return tokenInfo\n }\n\n public async findByCode(code: Code): Promise<null | TokenInfo> {\n return this.store.findTokenByCode(code)\n }\n\n public async deleteToken(tokenId: TokenId): Promise<void> {\n return this.store.deleteToken(tokenId)\n }\n\n async getTokenInfo(tokenId: TokenId): Promise<null | TokenInfo> {\n return this.store.readToken(tokenId)\n }\n\n /**\n * This method is called to when decoding a token that was encoded in\n * {@link AccessTokenMode.light} mode, using data from the store to fill the\n * data that was omitted in the token itself.\n */\n async loadTokenClaims(\n tokenType: OAuthTokenType,\n tokenPayload: AccessTokenPayload,\n ): Promise<TokenClaims> {\n const tokenId = tokenPayload.jti\n const tokenInfo = await this.getTokenInfo(tokenId).catch((err) => {\n throw InvalidTokenError.from(err, tokenType)\n })\n\n if (!tokenInfo) {\n throw new InvalidTokenError(tokenType, `Invalid token`)\n }\n\n const { account, data } = tokenInfo\n\n // Fool proof, make sure that the database & token payload are consistent.\n // These should both be either undefined or a string so it's safe to compare\n // the values directly.\n if (tokenPayload.cnf?.jkt !== data.parameters.dpop_jkt) {\n await this.deleteToken(tokenId)\n throw new InvalidTokenError(tokenType, `Invalid token`)\n }\n\n if (isCurrentTokenExpired(tokenInfo)) {\n await this.deleteToken(tokenId)\n throw new InvalidTokenError(tokenType, `Token expired`)\n }\n\n return {\n jti: tokenId,\n sub: account.did,\n iat: dateToEpoch(data.updatedAt),\n exp: dateToEpoch(data.expiresAt),\n aud: account.pds,\n scope: data.scope ?? data.parameters.scope,\n // https://datatracker.ietf.org/doc/html/rfc8693#section-4.3\n client_id: data.clientId,\n }\n }\n\n async listAccountTokens(did: Did): Promise<TokenInfo[]> {\n const results = await this.store.listAccountTokens(did)\n return results\n .filter((tokenInfo) => tokenInfo.account.did === did) // Fool proof\n .filter((tokenInfo) => !isCurrentTokenExpired(tokenInfo))\n }\n}\n\nfunction isCurrentTokenExpired(tokenInfo: TokenInfo): boolean {\n return tokenInfo.data.expiresAt.getTime() < Date.now()\n}\n\nfunction inferTokenType(\n parameters: OAuthAuthorizationRequestParameters,\n): OAuthTokenType {\n if (parameters.dpop_jkt) {\n return 'DPoP'\n }\n return 'Bearer'\n}\n"]}
1
+ {"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/token/token-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Did } from '@atproto/did'\nimport { type SignedJwt, isSignedJwt } from '@atproto/jwk'\nimport { LexResolverError } from '@atproto/lex-resolver'\nimport type { Account } from '@atproto/oauth-provider-api'\nimport type {\n OAuthAccessToken,\n OAuthAuthorizationRequestParameters,\n OAuthScope,\n OAuthTokenResponse,\n OAuthTokenType,\n} from '@atproto/oauth-types'\nimport { AccessTokenMode } from '../access-token/access-token-mode.js'\nimport type { ClientAuth } from '../client/client-auth.js'\nimport type { Client } from '../client/client.js'\nimport type { DeviceId } from '../device/device-id.js'\nimport { InvalidGrantError } from '../errors/invalid-grant-error.js'\nimport { InvalidRequestError } from '../errors/invalid-request-error.js'\nimport { InvalidTokenError } from '../errors/invalid-token-error.js'\nimport type { LexiconManager } from '../lexicon/lexicon-manager.js'\nimport type { RequestMetadata } from '../lib/http/request.js'\nimport { dateToEpoch, dateToRelativeSeconds } from '../lib/util/date.js'\nimport {\n REFRESH_LIFETIME_EXTENDED,\n SESSION_LIFETIME_EXTENDED,\n TOKEN_MAX_AGE,\n} from '../oauth-constants.js'\nimport type { OAuthHooks } from '../oauth-hooks.js'\nimport { type Code, isCode } from '../request/code.js'\nimport type { AccessTokenPayload } from '../signer/access-token-payload.js'\nimport { Signer } from '../signer/signer.js'\nimport {\n type RefreshToken,\n generateRefreshToken,\n isRefreshToken,\n} from './refresh-token.js'\nimport type { TokenClaims } from './token-claims.js'\nimport { type TokenId, generateTokenId, isTokenId } from './token-id.js'\nimport type { CreateTokenData, TokenInfo, TokenStore } from './token-store.js'\n\nexport { AccessTokenMode, Signer }\nexport type { OAuthHooks, TokenStore }\n\nexport class TokenManager {\n constructor(\n protected readonly store: TokenStore,\n protected readonly lexiconManager: LexiconManager,\n protected readonly signer: Signer,\n protected readonly hooks: OAuthHooks,\n protected readonly accessTokenMode: AccessTokenMode,\n protected readonly tokenMaxAge = TOKEN_MAX_AGE,\n ) {}\n\n protected createTokenExpiry(\n client: Client,\n now: Date,\n sessionCreationDate: Date = now,\n ): Date {\n const lifetime = Math.min(\n this.tokenMaxAge,\n // Make sure the token does not stay valid beyond the session lifetime.\n sessionCreationDate.getTime() + client.sessionLifetime - now.getTime(),\n )\n\n // We account for a small buffer to avoid the token being valid for a few\n // milliseconds\n if (lifetime <= 250) {\n throw new InvalidGrantError(`Session expired`)\n }\n\n return new Date(now.getTime() + lifetime)\n }\n\n protected async createAccessToken(\n tokenId: TokenId,\n client: Client,\n account: Account,\n parameters: OAuthAuthorizationRequestParameters,\n issuedAt: Date,\n expiresAt: Date,\n scope: OAuthScope,\n ): Promise<OAuthAccessToken> {\n const claims: TokenClaims = {\n jti: tokenId,\n sub: account.did,\n iat: dateToEpoch(issuedAt),\n exp: dateToEpoch(expiresAt),\n aud: account.pds,\n\n ...(parameters.dpop_jkt && {\n cnf: { jkt: parameters.dpop_jkt },\n }),\n\n // Because tokens can end-up being quite big, we only include the scope in\n // stateless mode.\n ...(this.accessTokenMode === AccessTokenMode.stateless && {\n scope,\n }),\n\n // https://datatracker.ietf.org/doc/html/rfc8693#section-4.3\n client_id: client.id,\n }\n\n const claimsOverride = await this.hooks.onCreateToken?.call(null, {\n client,\n account,\n parameters,\n claims,\n })\n\n return this.signer.createAccessToken(claimsOverride ?? claims)\n }\n\n async createToken(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n account: Account,\n deviceId: null | DeviceId,\n parameters: OAuthAuthorizationRequestParameters,\n code: Code,\n ): Promise<OAuthTokenResponse> {\n await this.validateTokenParams(client, clientAuth, parameters)\n\n const tokenId = await generateTokenId()\n const refreshToken = client.metadata.grant_types.includes('refresh_token')\n ? await generateRefreshToken()\n : undefined\n\n const now = new Date()\n const expiresAt = this.createTokenExpiry(client, now)\n\n const scope = await this.lexiconManager\n .buildTokenScope(parameters.scope!)\n .catch((err) => {\n // Parse expected errors\n if (err instanceof LexResolverError) {\n throw new InvalidRequestError(err.message, err)\n }\n\n // Unexpected error\n throw err\n })\n\n const accessToken = await this.createAccessToken(\n tokenId,\n client,\n account,\n parameters,\n now,\n expiresAt,\n scope,\n )\n\n const response = this.buildTokenResponse(\n inferTokenType(parameters),\n accessToken,\n refreshToken,\n expiresAt,\n account.did,\n scope,\n )\n\n const tokenData: CreateTokenData = {\n createdAt: now,\n updatedAt: now,\n expiresAt,\n clientId: client.id,\n clientAuth,\n deviceId,\n did: account.did,\n parameters,\n details: null,\n scope,\n code,\n }\n\n await this.store.createToken(tokenId, tokenData, refreshToken)\n\n try {\n await this.hooks.onTokenCreated?.call(null, {\n client,\n clientAuth,\n clientMetadata,\n account,\n parameters,\n })\n\n return response\n } catch (err) {\n // If the hook fails, we delete the token to avoid leaving a dangling\n // token in the store.\n await this.deleteToken(tokenId)\n throw err\n }\n }\n\n protected async validateTokenParams(\n client: Client,\n clientAuth: ClientAuth,\n parameters: OAuthAuthorizationRequestParameters,\n ): Promise<void> {\n if (client.metadata.dpop_bound_access_tokens && !parameters.dpop_jkt) {\n throw new InvalidGrantError(\n `DPoP JKT is required for DPoP bound access tokens`,\n )\n }\n }\n\n protected buildTokenResponse(\n tokenType: OAuthTokenType,\n accessToken: OAuthAccessToken,\n refreshToken: string | undefined,\n expiresAt: Date,\n did: Did,\n scope: string,\n ): OAuthTokenResponse {\n return {\n access_token: accessToken,\n token_type: tokenType,\n refresh_token: refreshToken,\n scope,\n\n // @NOTE using a getter so that the value gets computed when the JSON\n // response is generated, allowing to value to be as accurate as possible.\n get expires_in() {\n return dateToRelativeSeconds(expiresAt)\n },\n\n // ATPROTO extension: add the sub claim to the token response to allow\n // clients to resolve the PDS url (audience) using the did resolution\n // mechanism.\n sub: did,\n }\n }\n\n async rotateToken(\n client: Client,\n clientAuth: ClientAuth,\n clientMetadata: RequestMetadata,\n tokenInfo: TokenInfo,\n now = new Date(),\n ): Promise<OAuthTokenResponse> {\n const { account, data } = tokenInfo\n const { parameters } = data\n\n await this.validateTokenParams(client, clientAuth, parameters)\n\n const nextTokenId = await generateTokenId()\n const nextRefreshToken = await generateRefreshToken()\n\n const expiresAt = this.createTokenExpiry(\n client,\n now,\n tokenInfo.data.createdAt,\n )\n\n // @NOTE since the permission sets are stored in a persistent store,\n // it's fine to propagate a 500 (server_error) here as the values should\n // be retrievable from the store.\n const scope = await this.lexiconManager.buildTokenScope(parameters.scope!)\n\n await this.store.rotateToken(tokenInfo.id, nextTokenId, nextRefreshToken, {\n updatedAt: now,\n expiresAt,\n // @NOTE Normally, the clientAuth not change over time. There are two\n // exceptions:\n // - Upgrade from a legacy representation of client authentication to\n // a modern one.\n // - Allow clients to become \"confidential\" if they were previously\n // \"public\"\n clientAuth,\n scope,\n })\n\n const accessToken = await this.createAccessToken(\n nextTokenId,\n client,\n account,\n parameters,\n now,\n expiresAt,\n scope,\n )\n\n const response = this.buildTokenResponse(\n inferTokenType(parameters),\n accessToken,\n nextRefreshToken,\n expiresAt,\n account.did,\n scope,\n )\n\n await this.hooks.onTokenRefreshed?.call(null, {\n client,\n clientAuth,\n clientMetadata,\n account,\n parameters,\n })\n\n return response\n }\n\n /**\n * @note The token validity is not guaranteed. The caller must ensure that the\n * token is valid before using the returned token info.\n */\n public async findToken(token: string): Promise<null | TokenInfo> {\n if (isTokenId(token)) {\n return this.getTokenInfo(token)\n } else if (isCode(token)) {\n return this.findByCode(token)\n } else if (isRefreshToken(token)) {\n return this.findByRefreshToken(token)\n } else if (isSignedJwt(token)) {\n return this.findByAccessToken(token)\n } else {\n throw new InvalidRequestError(`Invalid token`)\n }\n }\n\n public async findByAccessToken(token: SignedJwt): Promise<null | TokenInfo> {\n const { payload } = await this.signer.verifyAccessToken(token, {\n clockTolerance: Infinity,\n })\n\n const tokenInfo = await this.getTokenInfo(payload.jti)\n if (!tokenInfo) return null\n\n // Fool-proof: Invalid store implementation ?\n if (payload.sub !== tokenInfo.account.did) {\n await this.deleteToken(tokenInfo.id)\n throw new Error(\n `Account sub (${tokenInfo.account.did}) does not match token sub (${payload.sub})`,\n )\n }\n\n return tokenInfo\n }\n\n protected async findByRefreshToken(\n token: RefreshToken,\n ): Promise<null | TokenInfo> {\n return this.store.findTokenByRefreshToken(token)\n }\n\n public async consumeRefreshToken(token: RefreshToken): Promise<TokenInfo> {\n // @NOTE concurrent refreshes of the same refresh token could theoretically\n // lead to two new tokens (access & refresh) being created. This is deemed\n // acceptable for now (as the mechanism can only be used once since only one\n // of the two refresh token created will be valid, and any future refresh\n // attempts from outdated tokens will cause the entire session to be\n // invalidated). Ideally, the store should be able to handle this case by\n // atomically consuming the refresh token and returning the token info.\n\n // @TODO Add another store method that atomically consumes the refresh token\n // with a lock.\n const tokenInfo = await this.findByRefreshToken(token).catch((err) => {\n throw InvalidGrantError.from(err, `Invalid refresh token`)\n })\n\n if (!tokenInfo) {\n throw new InvalidGrantError(`Invalid refresh token`)\n }\n\n if (tokenInfo.currentRefreshToken !== token) {\n await this.deleteToken(tokenInfo.id)\n throw new InvalidGrantError(`Refresh token replayed`)\n }\n\n return tokenInfo\n }\n\n public async findByCode(code: Code): Promise<null | TokenInfo> {\n return this.store.findTokenByCode(code)\n }\n\n public async deleteToken(tokenId: TokenId): Promise<void> {\n return this.store.deleteToken(tokenId)\n }\n\n async getTokenInfo(tokenId: TokenId): Promise<null | TokenInfo> {\n return this.store.readToken(tokenId)\n }\n\n /**\n * This method is called to when decoding a token that was encoded in\n * {@link AccessTokenMode.light} mode, using data from the store to fill the\n * data that was omitted in the token itself.\n */\n async loadTokenClaims(\n tokenType: OAuthTokenType,\n tokenPayload: AccessTokenPayload,\n ): Promise<TokenClaims> {\n const tokenId = tokenPayload.jti\n const tokenInfo = await this.getTokenInfo(tokenId).catch((err) => {\n throw InvalidTokenError.from(err, tokenType)\n })\n\n if (!tokenInfo) {\n throw new InvalidTokenError(tokenType, `Invalid token`)\n }\n\n const { account, data } = tokenInfo\n\n // Fool proof, make sure that the database & token payload are consistent.\n // These should both be either undefined or a string so it's safe to compare\n // the values directly.\n if (tokenPayload.cnf?.jkt !== data.parameters.dpop_jkt) {\n await this.deleteToken(tokenId)\n throw new InvalidTokenError(tokenType, `Invalid token`)\n }\n\n if (isCurrentTokenExpired(tokenInfo)) {\n await this.deleteToken(tokenId)\n throw new InvalidTokenError(tokenType, `Token expired`)\n }\n\n return {\n jti: tokenId,\n sub: account.did,\n iat: dateToEpoch(data.updatedAt),\n exp: dateToEpoch(data.expiresAt),\n aud: account.pds,\n scope: data.scope ?? data.parameters.scope,\n // https://datatracker.ietf.org/doc/html/rfc8693#section-4.3\n client_id: data.clientId,\n }\n }\n\n async listAccountTokens(did: Did): Promise<TokenInfo[]> {\n const results = await this.store.listAccountTokens(did)\n return results\n .filter((tokenInfo) => tokenInfo.account.did === did) // Fool proof\n .filter(\n // The session are still active if they are within the session lifetime\n // and refresh lifetime. We pre-filter here, based on the maximum\n // possible lifetime of a session, to avoid loading the client metadata\n // for sessions that are for sure expired. The client metadata is needed\n // to determine the actual session and refresh lifetimes.\n ({ data }) =>\n Date.now() - data.createdAt.getTime() < SESSION_LIFETIME_EXTENDED &&\n Date.now() - data.updatedAt.getTime() < REFRESH_LIFETIME_EXTENDED,\n )\n }\n}\n\nfunction isCurrentTokenExpired(tokenInfo: TokenInfo): boolean {\n return tokenInfo.data.expiresAt.getTime() < Date.now()\n}\n\nfunction inferTokenType(\n parameters: OAuthAuthorizationRequestParameters,\n): OAuthTokenType {\n if (parameters.dpop_jkt) {\n return 'DPoP'\n }\n return 'Bearer'\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/oauth-provider",
3
- "version": "0.20.2",
3
+ "version": "0.21.0",
4
4
  "license": "MIT",
5
5
  "description": "Generic OAuth2 and OpenID Connect provider for Node.js. Currently only supports features needed for Atproto.",
6
6
  "keywords": [
@@ -72,20 +72,20 @@
72
72
  "ioredis": "^5.3.2",
73
73
  "jose": "^5.2.0",
74
74
  "zod": "^3.23.8",
75
- "@atproto-labs/fetch-node": "^0.3.5",
76
- "@atproto-labs/simple-store": "^0.4.4",
77
- "@atproto-labs/simple-store-memory": "^0.2.4",
78
- "@atproto/did": "^0.5.4",
75
+ "@atproto-labs/fetch-node": "^0.3.6",
79
76
  "@atproto-labs/pipe": "^0.2.4",
80
- "@atproto/jwk": "^0.7.4",
81
- "@atproto/jwk-jose": "^0.2.4",
77
+ "@atproto-labs/simple-store": "^0.5.0",
78
+ "@atproto-labs/simple-store-memory": "^0.2.5",
79
+ "@atproto/did": "^0.5.4",
82
80
  "@atproto/common": "^0.7.2",
83
- "@atproto/lex-resolver": "^0.2.2",
81
+ "@atproto/jwk": "^0.7.4",
84
82
  "@atproto/lex-document": "^0.1.6",
83
+ "@atproto/lex-resolver": "^0.2.3",
84
+ "@atproto/jwk-jose": "^0.2.4",
85
+ "@atproto/oauth-provider-ui": "0.8.8",
85
86
  "@atproto/oauth-types": "^0.7.5",
86
- "@atproto/oauth-provider-api": "0.7.6",
87
- "@atproto/oauth-scopes": "^0.5.6",
88
- "@atproto/oauth-provider-ui": "0.8.7",
87
+ "@atproto/oauth-provider-api": "0.7.7",
88
+ "@atproto/oauth-scopes": "^0.5.7",
89
89
  "@atproto/syntax": "^0.7.2"
90
90
  },
91
91
  "devDependencies": {
@@ -93,9 +93,11 @@
93
93
  "@types/forwarded": "0.1.3",
94
94
  "@types/http-errors": "^2.0.4",
95
95
  "@types/send": "^0.17.4",
96
+ "vitest": "^4.0.16",
96
97
  "@atproto-labs/rollup-plugin-bundle-manifest": "^0.3.3"
97
98
  },
98
99
  "scripts": {
99
- "build": "tsgo --build tsconfig.build.json"
100
+ "build": "tsgo --build tsconfig.build.json",
101
+ "test": "vitest run"
100
102
  }
101
103
  }