@openstax/ts-utils 1.15.5 → 1.16.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.
@@ -1,5 +1,5 @@
1
1
  import type { ConfigProviderForConfig } from '../../config';
2
- import { CookieAuthProvider } from '.';
2
+ import { AuthProvider, CookieAuthProvider } from '.';
3
3
  declare type Config = {
4
4
  cookieName: string;
5
5
  encryptionPrivateKey: string;
@@ -8,9 +8,12 @@ declare type Config = {
8
8
  interface Initializer<C> {
9
9
  configSpace?: C;
10
10
  }
11
+ export declare type DecryptionAuthProvider = CookieAuthProvider<AuthProvider & {
12
+ getTokenExpiration: () => Promise<number | undefined>;
13
+ }>;
11
14
  export declare const decryptionAuthProvider: <C extends string = "decryption">(initializer: Initializer<C>) => (configProvider: { [key in C]: {
12
15
  cookieName: import("../../config").ConfigValueProvider<string>;
13
16
  encryptionPrivateKey: import("../../config").ConfigValueProvider<string>;
14
17
  signaturePublicKey: import("../../config").ConfigValueProvider<string>;
15
- }; }) => CookieAuthProvider;
18
+ }; }) => DecryptionAuthProvider;
16
19
  export {};
@@ -21,12 +21,18 @@ const decryptionAuthProvider = (initializer) => (configProvider) => {
21
21
  }
22
22
  return { headers };
23
23
  };
24
- const loadUser = async () => {
24
+ const getPayload = async () => {
25
25
  const [token] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
26
26
  if (!token) {
27
27
  return undefined;
28
28
  }
29
- const result = (0, decryptAndVerify_1.decryptAndVerify)(token, await encryptionPrivateKey(), await signaturePublicKey());
29
+ return (0, decryptAndVerify_1.decryptAndVerify)(token, await encryptionPrivateKey(), await signaturePublicKey());
30
+ };
31
+ const loadUser = async () => {
32
+ const result = await getPayload();
33
+ if (!result) {
34
+ return undefined;
35
+ }
30
36
  if ('error' in result && result.error == 'expired token') {
31
37
  throw new errors_1.SessionExpiredError();
32
38
  }
@@ -34,12 +40,16 @@ const decryptionAuthProvider = (initializer) => (configProvider) => {
34
40
  };
35
41
  return {
36
42
  getAuthorizedFetchConfig,
43
+ getTokenExpiration: async () => {
44
+ const result = await getPayload();
45
+ return result ? result.exp : undefined;
46
+ },
37
47
  getUser: async () => {
38
48
  if (!user) {
39
49
  user = await loadUser();
40
50
  }
41
51
  return user;
42
- }
52
+ },
43
53
  };
44
54
  };
45
55
  };
@@ -45,9 +45,9 @@ export declare type CookieAuthProviderRequest = {
45
45
  headers: HttpHeaders;
46
46
  queryStringParameters?: QueryParams;
47
47
  };
48
- export declare type CookieAuthProvider = (inputs: {
48
+ export declare type CookieAuthProvider<T extends AuthProvider = AuthProvider> = (inputs: {
49
49
  request: CookieAuthProviderRequest;
50
- }) => AuthProvider;
50
+ }) => T;
51
51
  export declare type StubAuthProvider = (user: User | undefined) => AuthProvider;
52
52
  export declare const stubAuthProvider: (user?: User | undefined) => AuthProvider;
53
53
  export declare const getAuthTokenOrCookie: (request: CookieAuthProviderRequest, cookieName: string, queryKey?: string) => [string, {
@@ -17,11 +17,13 @@ export declare const verifyJws: (jws: string, signaturePublicKey: Buffer | strin
17
17
  * @param token the encrypted token
18
18
  * @param encryptionPrivateKey the private key used to encrypt the token
19
19
  * @param signaturePublicKey the public key used to verify the decrypted token
20
- * @returns {user: User} (success) or {error: string} (failure)
20
+ * @returns {user: User; exp: number} (success) or {error: string} (failure)
21
21
  */
22
22
  export declare const decryptAndVerify: (token: string, encryptionPrivateKey: string, signaturePublicKey: string) => {
23
23
  user: User;
24
+ exp: number;
24
25
  } | {
25
26
  error: string;
27
+ exp?: number;
26
28
  };
27
29
  export {};
@@ -62,7 +62,7 @@ exports.verifyJws = verifyJws;
62
62
  * @param token the encrypted token
63
63
  * @param encryptionPrivateKey the private key used to encrypt the token
64
64
  * @param signaturePublicKey the public key used to verify the decrypted token
65
- * @returns {user: User} (success) or {error: string} (failure)
65
+ * @returns {user: User; exp: number} (success) or {error: string} (failure)
66
66
  */
67
67
  const decryptAndVerify = (token, encryptionPrivateKey, signaturePublicKey) => {
68
68
  const timestamp = Math.floor(Date.now() / 1000);
@@ -84,8 +84,8 @@ const decryptAndVerify = (token, encryptionPrivateKey, signaturePublicKey) => {
84
84
  return { error: 'invalid token' };
85
85
  }
86
86
  if (payload.exp < timestamp - clockTolerance) {
87
- return { error: 'expired token' };
87
+ return { error: 'expired token', exp: payload.exp };
88
88
  }
89
- return { user: payload.sub };
89
+ return { user: payload.sub, exp: payload.exp };
90
90
  };
91
91
  exports.decryptAndVerify = decryptAndVerify;
@@ -21,7 +21,7 @@ export declare const createLaunchSigner: <C extends string = "launch">({ configS
21
21
  jwks: () => Promise<{
22
22
  keys: JWK.RawKey[];
23
23
  }>;
24
- sign: (subject: string) => Promise<string>;
24
+ sign: (subject: string, maxExpiresIn?: string | number | undefined) => Promise<string>;
25
25
  };
26
26
  export declare type LaunchSigner = ReturnType<ReturnType<typeof createLaunchSigner>>;
27
27
  export {};
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.createLaunchSigner = void 0;
7
7
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ const ms_1 = __importDefault(require("ms"));
8
9
  const node_jose_1 = require("node-jose");
9
10
  const __1 = require("../..");
10
11
  const config_1 = require("../../config");
@@ -33,9 +34,17 @@ const createLaunchSigner = ({ configSpace }) => (configProvider) => {
33
34
  return keystore;
34
35
  });
35
36
  const jwks = async () => (await getKeyStore()).toJSON(false);
36
- const sign = async (subject) => {
37
- const alg = await getAlg();
37
+ const getExpiresInWithMax = async (maxExpiresIn) => {
38
38
  const expiresIn = await getExpiresIn();
39
+ const maxExpiresInSeconds = typeof maxExpiresIn === 'number' ? maxExpiresIn :
40
+ typeof maxExpiresIn === 'string' ? Math.floor((0, ms_1.default)(maxExpiresIn) / 1000) :
41
+ undefined;
42
+ return maxExpiresInSeconds ? Math.min(Math.floor((0, ms_1.default)(expiresIn) / 1000), maxExpiresInSeconds) : expiresIn;
43
+ };
44
+ const sign = async (subject, maxExpiresIn) => {
45
+ const alg = await getAlg();
46
+ // expiresIn can be a number of seconds or a string like '1h' or '1d'
47
+ const expiresIn = await getExpiresInWithMax(maxExpiresIn);
39
48
  const iss = await getIss();
40
49
  const header = { alg, iss };
41
50
  return jsonwebtoken_1.default.sign({}, await getPrivateKey(), { algorithm: alg, expiresIn, header, issuer: iss, subject });