@nymphjs/tilmeld 1.0.0-beta.2 → 1.0.0-beta.21

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/src/conf/d.ts CHANGED
@@ -9,7 +9,7 @@ import User, { UserData } from '../User';
9
9
  */
10
10
  export interface Config {
11
11
  /**
12
- * The name of the app. Used in emails sent to users.
12
+ * The name of the app. Used in emails sent to users and as the TOTP issuer.
13
13
  */
14
14
  appName: string;
15
15
  /**
@@ -217,6 +217,11 @@ export interface Config {
217
217
  * How long from current time, in seconds, the JWT token expires.
218
218
  */
219
219
  jwtExpire: number;
220
+ /**
221
+ * How long from current time, in seconds, the JWT token for a user switch
222
+ * expires.
223
+ */
224
+ jwtSwitchExpire: number;
220
225
  /**
221
226
  * How long, in seconds, before the JWT token expires to give the user a new
222
227
  * one.
@@ -225,21 +230,25 @@ export interface Config {
225
230
  /**
226
231
  * Function to build the JWT for user sessions.
227
232
  */
228
- jwtBuilder: (config: Config, user: User) => string;
233
+ jwtBuilder: (
234
+ config: Config,
235
+ user: User & UserData,
236
+ switchToken?: boolean
237
+ ) => string;
229
238
  /**
230
- * Function to verify that a JWT was signed with the secret key, vaildate its
231
- * data, validate the XSRF token, and extract the GUID.
239
+ * Function to verify that a JWT was signed with the secret key, validate its
240
+ * data, validate the XSRF token, and extract the GUID and dates.
232
241
  *
233
242
  * If no XSRF token is supplied, ignore it.
234
243
  *
235
- * Return false if the JWT is not valid, or an array of GUID and expire
236
- * timestamp otherwise.
244
+ * Return false if the JWT is not valid, or an object with GUID, issued date,
245
+ * and expire date otherwise.
237
246
  */
238
247
  jwtExtract: (
239
248
  config: Config,
240
249
  token: string,
241
250
  xsrfToken?: string
242
- ) => { guid: string; expire: Date } | null;
251
+ ) => { guid: string; issued: Date; expire: Date } | null;
243
252
  /**
244
253
  * The absolute path to the email template directory. Used by the default
245
254
  * email sender.
@@ -52,8 +52,9 @@ export default {
52
52
  maxUsernameLength: 128,
53
53
  jwtSecret: '',
54
54
  jwtExpire: 60 * 60 * 24 * 7 * 8, // 8 weeks(ish)
55
+ jwtSwitchExpire: 60 * 60 * 6, // 6 hours
55
56
  jwtRenew: 60 * 60 * 24 * 7 * 2, // 2 weeks(ish)
56
- jwtBuilder: (config, user) => {
57
+ jwtBuilder: (config, user, switchToken) => {
57
58
  const secret = config.jwtSecret;
58
59
  if (secret === '') {
59
60
  throw new Error('JWT secret is not configured.');
@@ -67,7 +68,7 @@ export default {
67
68
  xsrfToken: 'TILMELDXSRF-' + nanoid(),
68
69
  },
69
70
  secret,
70
- { expiresIn: config.jwtExpire }
71
+ { expiresIn: switchToken ? config.jwtSwitchExpire : config.jwtExpire }
71
72
  );
72
73
  },
73
74
  jwtExtract: (config, token, xsrfToken?) => {
@@ -86,7 +87,7 @@ export default {
86
87
  return null;
87
88
  }
88
89
 
89
- const { guid, xsrfToken: jwtXsrfToken, exp } = payload;
90
+ const { guid, xsrfToken: jwtXsrfToken, exp, nbf } = payload;
90
91
 
91
92
  if (xsrfToken != null && xsrfToken !== jwtXsrfToken) {
92
93
  return null;
@@ -96,13 +97,19 @@ export default {
96
97
  return null;
97
98
  }
98
99
 
100
+ if (nbf == null) {
101
+ return null;
102
+ }
103
+
104
+ const issued = new Date(nbf * 1000);
105
+
99
106
  if (exp == null) {
100
107
  return null;
101
108
  }
102
109
 
103
110
  const expire = new Date(exp * 1000);
104
111
 
105
- return { guid, expire };
112
+ return { guid, issued, expire };
106
113
  } catch (e: any) {
107
114
  return null;
108
115
  }
@@ -308,6 +315,12 @@ export default {
308
315
  recoverSecretDate: Joi.number(),
309
316
  salt: Joi.string().trim(false),
310
317
  password: Joi.string().trim(false).required(),
318
+ revokeTokenDate: Joi.number(),
319
+ totpSecret: Joi.string()
320
+ .trim(false)
321
+ .min(24)
322
+ .max(40)
323
+ .pattern(/^[A-Z234567]+$/, 'base32 encoded unpadded'),
311
324
  }),
312
325
  'Invalid User: '
313
326
  );
@@ -0,0 +1,20 @@
1
+ import { Entity, EntityConstructor, Nymph } from '@nymphjs/nymph';
2
+
3
+ import Tilmeld from './Tilmeld';
4
+
5
+ export function enforceTilmeld(object: Nymph | Entity | EntityConstructor) {
6
+ let tilmeld: Tilmeld | undefined;
7
+ if (object instanceof Entity) {
8
+ tilmeld = object.$nymph.tilmeld as Tilmeld | undefined;
9
+ } else if (object instanceof Nymph) {
10
+ tilmeld = object.tilmeld as Tilmeld | undefined;
11
+ } else {
12
+ tilmeld = object.nymph.tilmeld as Tilmeld | undefined;
13
+ }
14
+
15
+ if (tilmeld == null) {
16
+ throw new Error('Tilmeld was not configured on this Nymph instance!');
17
+ }
18
+
19
+ return tilmeld;
20
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export * from './conf';
2
2
 
3
+ export * from './enforceTilmeld';
4
+
3
5
  export * from './errors';
4
6
 
5
7
  import AbleObject from './AbleObject';