w3home-utils 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,10 +14,21 @@ npm install w3home-utils
14
14
  const {
15
15
  // Authentication
16
16
  getIndetifiers,
17
+ getIndetifiersCognito,
18
+ verifyW3JWT,
17
19
  getUser,
18
20
  getUserType,
19
21
  decodeIdToken,
20
-
22
+ clearUserCache,
23
+
24
+ // W3 User Mapping
25
+ resolveW3UserToHomepayUser,
26
+ clearMappingCache,
27
+
28
+ // Redis/JWKS Cache (advanced)
29
+ getRedisClient,
30
+ getCachedJWKS,
31
+
21
32
  // Authorization
22
33
  authorize,
23
34
  withAuthorization,
@@ -25,12 +36,12 @@ const {
25
36
  authorizeBackofficeProject,
26
37
  ROLES,
27
38
  UserType,
28
-
39
+
29
40
  // Activity Logging
30
41
  logActivity,
31
42
  logPostActivity,
32
43
  withActivityLogging,
33
-
44
+
34
45
  // Common
35
46
  corsHeaders
36
47
  } = require('w3home-utils');
@@ -38,13 +49,22 @@ const {
38
49
 
39
50
  ## Authentication
40
51
 
52
+ ### Dual-Auth Support (W3 Platform + Cognito)
53
+
54
+ **w3home-utils v1.1.0** supports dual authentication via the `AUTH_MODE` environment variable:
55
+
56
+ - `cognito` (default): Legacy Cognito JWT decode
57
+ - `w3`: W3 Platform JWT validation with user mapping
58
+ - `dual`: Try W3 first, fall back to Cognito on failure
59
+
41
60
  ### Get User Identifiers from Request Headers
42
61
 
43
62
  ```javascript
44
63
  const { getIndetifiers } = require('w3home-utils');
45
64
 
46
65
  const handler = async (event) => {
47
- const { userId } = await getIndetifiers(event.headers);
66
+ // Returns: { userId: string|null, w3Sub: string|null, authType?: 'w3'|'cognito' }
67
+ const { userId, w3Sub, authType } = await getIndetifiers(event.headers);
48
68
  if (!userId) {
49
69
  return { statusCode: 401, body: JSON.stringify({ error: 'Unauthorized' }) };
50
70
  }
@@ -52,6 +72,11 @@ const handler = async (event) => {
52
72
  };
53
73
  ```
54
74
 
75
+ **Return shape:**
76
+ - `userId`: Homepay user ID (always present for authenticated users)
77
+ - `w3Sub`: W3 platform user ID (present only for W3-authenticated users)
78
+ - `authType`: `'w3'` or `'cognito'` (indicates which auth backend was used)
79
+
55
80
  ### Get User Details
56
81
 
57
82
  ```javascript
@@ -171,6 +196,8 @@ console.log(UserType.BACKOFFICE_USER); // 'BACKOFFICE_USER'
171
196
 
172
197
  ## Environment Variables
173
198
 
199
+ ### Core Configuration
200
+
174
201
  | Variable | Default | Description |
175
202
  |----------|---------|-------------|
176
203
  | `USERS_TABLE` | `w3HomeUsers` | DynamoDB table for users |
@@ -178,6 +205,36 @@ console.log(UserType.BACKOFFICE_USER); // 'BACKOFFICE_USER'
178
205
  | `CONFIG_TABLE` | `w3home-config` | DynamoDB table for config |
179
206
  | `STAGE` | `dev` | Environment stage |
180
207
 
208
+ ### Authentication Mode (v1.1.0+)
209
+
210
+ | Variable | Values | Description |
211
+ |----------|--------|-------------|
212
+ | `AUTH_MODE` | `cognito` (default), `w3`, `dual` | Authentication backend selector |
213
+
214
+ **Auth modes:**
215
+ - `cognito`: Legacy Cognito JWT decode (backward compatible)
216
+ - `w3`: W3 Platform JWT validation + user mapping lookup
217
+ - `dual`: Try W3 first, fall back to Cognito on failure (recommended for migration)
218
+
219
+ ### W3 Platform Configuration (required when `AUTH_MODE=w3` or `dual`)
220
+
221
+ | Variable | Required | Default | Description |
222
+ |----------|----------|---------|-------------|
223
+ | `W3_JWKS_URL` | Yes | - | W3 platform JWKS endpoint URL |
224
+ | `W3_ISSUER` | Yes | - | W3 platform issuer (iss claim) |
225
+ | `W3_USER_MAPPING_TABLE` | No | `w3UserMapping` | DynamoDB table for w3UserId → homepayUserId mapping |
226
+
227
+ ### Redis Configuration (required for W3 JWKS caching)
228
+
229
+ | Variable | Required | Default | Description |
230
+ |----------|----------|---------|-------------|
231
+ | `REDIS_HOST` | Yes | - | Redis host for JWKS cache |
232
+ | `REDIS_PORT` | No | `6379` | Redis port |
233
+ | `REDIS_PASSWORD` | Yes* | - | Redis password (*required for production) |
234
+ | `REDIS_TLS` | No | `false` | Enable TLS for Redis connection |
235
+
236
+ **JWKS cache TTL:** 10 minutes (reduces load on W3 platform JWKS endpoint)
237
+
181
238
  ## Peer Dependencies
182
239
 
183
240
  This package requires `aws-sdk` as a peer dependency. In Lambda, this is already available. For local development:
@@ -186,6 +243,53 @@ This package requires `aws-sdk` as a peer dependency. In Lambda, this is already
186
243
  npm install aws-sdk --save-dev
187
244
  ```
188
245
 
246
+ ## Migration Guide
247
+
248
+ ### Migrating to W3 Platform Authentication (v1.1.0)
249
+
250
+ **Step 1: Update w3home-utils**
251
+
252
+ ```bash
253
+ npm update w3home-utils
254
+ ```
255
+
256
+ **Step 2: Enable dual-auth mode**
257
+
258
+ Add to your Lambda environment variables:
259
+
260
+ ```bash
261
+ AUTH_MODE=dual
262
+ W3_JWKS_URL=https://api.w3mcp.ai/.well-known/jwks.json
263
+ W3_ISSUER=https://api.w3mcp.ai
264
+ W3_USER_MAPPING_TABLE=w3UserMapping # Optional, defaults to this
265
+ REDIS_HOST=your-redis-host
266
+ REDIS_PORT=6379
267
+ REDIS_PASSWORD=your-redis-password
268
+ REDIS_TLS=true # For production
269
+ ```
270
+
271
+ **Step 3: No code changes needed!**
272
+
273
+ `getIndetifiers()` now returns `{ userId, w3Sub, authType }`. The `userId` field works exactly as before.
274
+
275
+ **Optional:** Use `w3Sub` for enhanced audit trails:
276
+
277
+ ```javascript
278
+ const { userId, w3Sub, authType } = await getIndetifiers(event.headers);
279
+ logActivity({
280
+ event,
281
+ userId,
282
+ w3Sub, // Now captured in activity logs
283
+ action: 'READ',
284
+ resource: 'projects',
285
+ statusCode: 200
286
+ });
287
+ ```
288
+
289
+ **Rollback:** Set `AUTH_MODE=cognito` to instantly revert to Cognito-only auth.
290
+
291
+ **Cutover:** Once all users migrated to W3 platform, set `AUTH_MODE=w3` for W3-only validation (no Cognito fallback).
292
+
189
293
  ## License
190
294
 
191
295
  UNLICENSED - HomePay Internal Use Only
package/package.json CHANGED
@@ -1,25 +1,30 @@
1
1
  {
2
2
  "name": "w3home-utils",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "W3Home Utilities - Authorization, Activity Logging, Auth Utilities",
5
5
  "main": "w3home-utils/index.js",
6
6
  "files": [
7
7
  "w3home-utils/**/*.js"
8
8
  ],
9
9
  "scripts": {
10
- "test": "echo \"No tests specified\" && exit 0",
10
+ "test": "jest --coverage --passWithNoTests",
11
+ "test:watch": "jest --watch",
11
12
  "prepublishOnly": "npm test",
12
13
  "seed:dev": "node seed-tables.js dev",
13
14
  "seed:prd": "node seed-tables.js prd"
14
15
  },
15
16
  "dependencies": {
17
+ "ioredis": "^5.10.0",
18
+ "jose": "^5.10.0",
16
19
  "jsonwebtoken": "^9.0.2"
17
20
  },
18
21
  "peerDependencies": {
19
22
  "aws-sdk": "^2.1000.0"
20
23
  },
21
24
  "devDependencies": {
22
- "aws-sdk": "^2.1692.0"
25
+ "aws-sdk": "^2.1692.0",
26
+ "aws-sdk-mock": "^6.2.2",
27
+ "jest": "^29.7.0"
23
28
  },
24
29
  "keywords": [
25
30
  "authorization",
@@ -39,14 +39,16 @@ function extractRequestContext(event) {
39
39
  };
40
40
  }
41
41
 
42
- function logActivity({ event, userId, action, resource, statusCode, metadata = {}, context }) {
42
+ function logActivity({ event, userId, w3Sub, action, resource, statusCode, metadata = {}, context }) {
43
43
  const identifiers = extractIdentifiers(event, userId);
44
44
  const requestContext = extractRequestContext(event);
45
-
45
+
46
46
  const activityLog = {
47
47
  logType: LOG_PREFIX,
48
48
  timestamp: new Date().toISOString(),
49
49
  userId: identifiers.userId,
50
+ w3Sub: w3Sub || null,
51
+ authMode: process.env.AUTH_MODE || 'cognito',
50
52
  projectId: identifiers.projectId,
51
53
  apartmentId: identifiers.apartmentId,
52
54
  action,
@@ -78,13 +80,23 @@ function withActivityLogging(handler, config = {}) {
78
80
  return async (event, context) => {
79
81
  const resource = config.resource || 'unknown';
80
82
  let userId = null;
83
+ let w3Sub = null;
81
84
  let action = 'CREATE';
82
85
  let statusCode = null;
83
86
  let metadata = {};
84
87
 
85
88
  try {
86
- if (config.extractUserId) userId = await config.extractUserId(event);
87
-
89
+ if (config.extractUserId) {
90
+ const userIdResult = await config.extractUserId(event);
91
+ // Support both string and object return values
92
+ if (typeof userIdResult === 'object' && userIdResult !== null) {
93
+ userId = userIdResult.userId || null;
94
+ w3Sub = userIdResult.w3Sub || null;
95
+ } else {
96
+ userId = userIdResult;
97
+ }
98
+ }
99
+
88
100
  if (config.extractAction) {
89
101
  action = await config.extractAction(event);
90
102
  } else {
@@ -95,15 +107,15 @@ function withActivityLogging(handler, config = {}) {
95
107
 
96
108
  const result = await handler(event, context);
97
109
  statusCode = result.statusCode || 200;
98
-
110
+
99
111
  if (config.extractMetadata) metadata = config.extractMetadata(result, event);
100
- logActivity({ event, userId, action, resource, statusCode, metadata, context });
112
+ logActivity({ event, userId, w3Sub, action, resource, statusCode, metadata, context });
101
113
 
102
114
  return result;
103
115
  } catch (error) {
104
116
  statusCode = 500;
105
117
  metadata = { error: error.message };
106
- logActivity({ event, userId, action, resource, statusCode, metadata, context });
118
+ logActivity({ event, userId, w3Sub, action, resource, statusCode, metadata, context });
107
119
  throw error;
108
120
  }
109
121
  };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Cognito Authentication Utilities
3
+ *
4
+ * Extracted from authUtils.js for dual-auth support.
5
+ * Handles legacy Cognito JWT decode flow (no verification, just decode).
6
+ */
7
+
8
+ const jwt = require('jsonwebtoken');
9
+
10
+ /**
11
+ * Decode Cognito JWT token (no verification - backward compatible)
12
+ * @param {string} idToken - Cognito JWT token
13
+ * @returns {string|null} - Cognito sub claim or null
14
+ */
15
+ function decodeIdToken(idToken) {
16
+ try {
17
+ const decoded = jwt.decode(idToken);
18
+ return decoded?.sub || null;
19
+ } catch (error) {
20
+ console.error('Error decoding Cognito token:', error.message);
21
+ return null;
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Get identifiers using Cognito flow (legacy)
27
+ * @param {string} token - JWT token
28
+ * @returns {Promise<{userId: string|null, w3Sub: null, authType: 'cognito'}>}
29
+ */
30
+ async function getIndetifiersCognito(token) {
31
+ const sub = decodeIdToken(token);
32
+ return {
33
+ userId: sub,
34
+ w3Sub: null,
35
+ authType: 'cognito'
36
+ };
37
+ }
38
+
39
+ module.exports = {
40
+ getIndetifiersCognito,
41
+ decodeIdToken
42
+ };
@@ -1,9 +1,17 @@
1
1
  /**
2
2
  * Authentication Utilities
3
+ *
4
+ * Supports dual-auth mode: Cognito (legacy) and W3 Platform JWT
5
+ * Routing controlled via AUTH_MODE environment variable:
6
+ * - 'cognito' (default): Legacy Cognito JWT decode
7
+ * - 'w3': W3 Platform JWT validation + user mapping
8
+ * - 'dual': Try W3 first, fall back to Cognito on failure
3
9
  */
4
10
 
5
- const jwt = require('jsonwebtoken');
6
11
  const AWS = require('aws-sdk');
12
+ const { getIndetifiersCognito, decodeIdToken } = require('./authUtils.cognito');
13
+ const { verifyW3JWT } = require('./authUtils.w3');
14
+ const { resolveW3UserToHomepayUser } = require('./mappingUtils');
7
15
 
8
16
  const USERS_TABLE = process.env.USERS_TABLE || 'w3HomeUsers';
9
17
  const dynamodb = new AWS.DynamoDB.DocumentClient({ region: 'eu-west-1' });
@@ -11,40 +19,84 @@ const dynamodb = new AWS.DynamoDB.DocumentClient({ region: 'eu-west-1' });
11
19
  const USER_CACHE_TTL = 5 * 60 * 1000;
12
20
  const userCache = new Map();
13
21
 
14
- function decodeIdToken(idToken) {
15
- try {
16
- const decoded = jwt.decode(idToken);
17
- return decoded?.sub || null;
18
- } catch (error) {
19
- console.error('Error decoding token:', error.message);
20
- return null;
21
- }
22
- }
22
+ /**
23
+ * Extract token from various header formats
24
+ * @param {Object} headers - Request headers
25
+ * @returns {string|null} - Extracted token or null
26
+ */
27
+ function extractToken(headers) {
28
+ let token = '';
23
29
 
24
- async function getIndetifiers(headers) {
25
- let authorizationToken = '';
26
-
27
30
  if (headers['Authorization']) {
28
31
  const parts = headers['Authorization'].split(' ');
29
- authorizationToken = parts.length > 1 ? parts[1] : parts[0];
32
+ token = parts.length > 1 ? parts[1] : parts[0];
30
33
  }
31
- if (!authorizationToken && headers['Token']) {
32
- authorizationToken = headers['Token'];
34
+ if (!token && headers['Token']) {
35
+ token = headers['Token'];
33
36
  }
34
- if (!authorizationToken && headers['authorization']) {
37
+ if (!token && headers['authorization']) {
35
38
  const parts = headers['authorization'].split(' ');
36
- authorizationToken = parts.length > 1 ? parts[1] : parts[0];
39
+ token = parts.length > 1 ? parts[1] : parts[0];
37
40
  }
38
- if (!authorizationToken && headers['token']) {
39
- authorizationToken = headers['token'];
41
+ if (!token && headers['token']) {
42
+ token = headers['token'];
40
43
  }
41
-
42
- if (authorizationToken) {
43
- const sub = decodeIdToken(authorizationToken);
44
- if (sub) return { userId: sub };
44
+
45
+ return token || null;
46
+ }
47
+
48
+ /**
49
+ * Get identifiers with W3 Platform JWT validation
50
+ * @param {string} token - JWT token
51
+ * @returns {Promise<{userId: string, w3Sub: string, authType: 'w3'}>}
52
+ */
53
+ async function getIndetifiersW3(token) {
54
+ const payload = await verifyW3JWT(token);
55
+ const homepayUserId = await resolveW3UserToHomepayUser(payload.sub);
56
+
57
+ return {
58
+ userId: homepayUserId,
59
+ w3Sub: payload.sub,
60
+ authType: 'w3'
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Get identifiers with dual-auth routing
66
+ * @param {Object} headers - Request headers
67
+ * @returns {Promise<{userId: string|null, w3Sub: string|null, authType?: string}>}
68
+ */
69
+ async function getIndetifiers(headers) {
70
+ const token = extractToken(headers);
71
+
72
+ if (!token) {
73
+ return { userId: null, w3Sub: null };
74
+ }
75
+
76
+ const authMode = process.env.AUTH_MODE || 'cognito';
77
+
78
+ switch (authMode) {
79
+ case 'cognito':
80
+ return await getIndetifiersCognito(token);
81
+
82
+ case 'w3':
83
+ return await getIndetifiersW3(token);
84
+
85
+ case 'dual':
86
+ // Try W3 first, fall back to Cognito on failure
87
+ try {
88
+ return await getIndetifiersW3(token);
89
+ } catch (error) {
90
+ console.warn(
91
+ 'Dual auth: W3 validation failed, falling back to Cognito.',
92
+ `Error: ${error.message}`
93
+ );
94
+ return await getIndetifiersCognito(token);
95
+ }
96
+
97
+ default:
98
+ throw new Error(`Invalid AUTH_MODE: ${authMode}`);
45
99
  }
46
-
47
- return { userId: null };
48
100
  }
49
101
 
50
102
  async function getUser(userId, options = {}, noCredentials = false) {
@@ -106,7 +158,7 @@ function getUserInstitutionIds(user) {
106
158
  }
107
159
 
108
160
  module.exports = {
109
- decodeIdToken,
161
+ decodeIdToken, // Re-exported from authUtils.cognito for backward compatibility
110
162
  getIndetifiers,
111
163
  getUser,
112
164
  getUserType,
@@ -0,0 +1,62 @@
1
+ /**
2
+ * W3 Platform JWT Authentication Utilities
3
+ *
4
+ * Validates W3 platform JWTs using jose library with RS256 signature verification.
5
+ * Uses Redis-cached JWKS to reduce remote fetches.
6
+ */
7
+
8
+ const { createLocalJWKSet, jwtVerify } = require('jose');
9
+ const { getCachedJWKS } = require('./cacheUtils');
10
+
11
+ /**
12
+ * Verify W3 platform JWT
13
+ *
14
+ * @param {string} token - JWT token to verify
15
+ * @returns {Promise<Object>} Decoded payload with { sub, iss, exp, iat, org, fullPayload }
16
+ * @throws {Error} If token is invalid, expired, or signature verification fails
17
+ */
18
+ async function verifyW3JWT(token) {
19
+ const issuer = process.env.W3_ISSUER;
20
+
21
+ if (!issuer) {
22
+ throw new Error('W3_ISSUER environment variable not set');
23
+ }
24
+
25
+ try {
26
+ // Get JWKS (from Redis cache or fetch)
27
+ const jwks = await getCachedJWKS();
28
+
29
+ // Create local JWK Set for signature verification
30
+ const JWKS = createLocalJWKSet(jwks);
31
+
32
+ // Verify JWT with RS256 algorithm, issuer validation, and 5-minute clock tolerance
33
+ const { payload } = await jwtVerify(token, JWKS, {
34
+ issuer,
35
+ clockTolerance: 300, // 5 minutes (300 seconds)
36
+ algorithms: ['RS256']
37
+ });
38
+
39
+ // Return extracted claims plus full payload
40
+ return {
41
+ sub: payload.sub,
42
+ iss: payload.iss,
43
+ exp: payload.exp,
44
+ iat: payload.iat,
45
+ org: payload.org,
46
+ fullPayload: payload
47
+ };
48
+ } catch (error) {
49
+ // Log error details for debugging
50
+ console.error('W3 JWT verification failed:', {
51
+ code: error.code,
52
+ message: error.message
53
+ });
54
+
55
+ // Re-throw for caller to handle
56
+ throw error;
57
+ }
58
+ }
59
+
60
+ module.exports = {
61
+ verifyW3JWT
62
+ };
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Cache Utilities for W3 JWT Authentication
3
+ *
4
+ * Provides Redis singleton client and JWKS caching layer.
5
+ */
6
+
7
+ const Redis = require('ioredis');
8
+
9
+ // Redis singleton instance
10
+ let redisClient = null;
11
+
12
+ /**
13
+ * Get Redis client singleton
14
+ *
15
+ * @returns {Redis} Singleton Redis client instance
16
+ */
17
+ function getRedisClient() {
18
+ if (!redisClient) {
19
+ const redisConfig = {
20
+ host: process.env.REDIS_HOST || process.env.CACHE_URL || 'localhost',
21
+ port: parseInt(process.env.REDIS_PORT || process.env.CACHE_PORT || '6379', 10),
22
+ lazyConnect: true,
23
+ enableOfflineQueue: true,
24
+ maxRetriesPerRequest: 3,
25
+ retryStrategy(times) {
26
+ const delay = Math.min(times * 50, 2000);
27
+ return delay;
28
+ }
29
+ };
30
+
31
+ // Enable TLS if configured
32
+ if (process.env.REDIS_TLS === 'true') {
33
+ redisConfig.tls = {};
34
+ }
35
+
36
+ redisClient = new Redis(redisConfig);
37
+
38
+ // Event handlers
39
+ redisClient.on('error', (err) => {
40
+ console.error('Redis error:', err.message);
41
+ });
42
+
43
+ redisClient.on('reconnecting', () => {
44
+ console.log('Redis reconnecting...');
45
+ });
46
+ }
47
+
48
+ return redisClient;
49
+ }
50
+
51
+ /**
52
+ * Get cached JWKS from Redis or fetch from W3 platform
53
+ *
54
+ * @returns {Promise<Object>} JWKS object with keys array
55
+ * @throws {Error} If fetch fails (does not throw on Redis errors - falls back to fetch)
56
+ */
57
+ async function getCachedJWKS() {
58
+ const CACHE_KEY = 'w3:jwks:v1';
59
+ const CACHE_TTL = 600; // 10 minutes
60
+ const jwksUrl = process.env.W3_JWKS_URL;
61
+
62
+ if (!jwksUrl) {
63
+ throw new Error('W3_JWKS_URL environment variable not set');
64
+ }
65
+
66
+ try {
67
+ const redis = getRedisClient();
68
+ const cached = await redis.get(CACHE_KEY);
69
+
70
+ if (cached) {
71
+ return JSON.parse(cached);
72
+ }
73
+ } catch (redisError) {
74
+ console.error('Redis cache read failed, falling back to direct fetch:', redisError.message);
75
+ }
76
+
77
+ // Cache miss or Redis error - fetch from URL
78
+ const response = await fetch(jwksUrl);
79
+
80
+ if (!response.ok) {
81
+ throw new Error(`Failed to fetch JWKS from ${jwksUrl}: ${response.status} ${response.statusText}`);
82
+ }
83
+
84
+ const jwks = await response.json();
85
+
86
+ // Cache in Redis (fire-and-forget - don't wait or throw on error)
87
+ try {
88
+ const redis = getRedisClient();
89
+ await redis.setex(CACHE_KEY, CACHE_TTL, JSON.stringify(jwks));
90
+ } catch (cacheWriteError) {
91
+ console.error('Failed to cache JWKS in Redis:', cacheWriteError.message);
92
+ // Continue - we have the JWKS from fetch
93
+ }
94
+
95
+ return jwks;
96
+ }
97
+
98
+ module.exports = {
99
+ getRedisClient,
100
+ getCachedJWKS
101
+ };
@@ -12,6 +12,11 @@ const {
12
12
  getUserInstitutionIds
13
13
  } = require('./authUtils');
14
14
 
15
+ const { verifyW3JWT } = require('./authUtils.w3');
16
+ const { getIndetifiersCognito, decodeIdToken: decodeIdTokenCognito } = require('./authUtils.cognito');
17
+ const { resolveW3UserToHomepayUser, clearMappingCache } = require('./mappingUtils');
18
+ const { getRedisClient, getCachedJWKS } = require('./cacheUtils');
19
+
15
20
  const {
16
21
  authorize,
17
22
  withAuthorization,
@@ -59,7 +64,7 @@ const corsHeaders = {
59
64
  };
60
65
 
61
66
  module.exports = {
62
- // Auth
67
+ // Auth (Legacy Cognito)
63
68
  decodeIdToken,
64
69
  getIndetifiers,
65
70
  getUser,
@@ -67,7 +72,15 @@ module.exports = {
67
72
  clearUserCache,
68
73
  getUserInstitutionId,
69
74
  getUserInstitutionIds,
70
-
75
+
76
+ // W3 Platform Auth (New)
77
+ verifyW3JWT,
78
+ getIndetifiersCognito,
79
+ resolveW3UserToHomepayUser,
80
+ clearMappingCache,
81
+ getRedisClient,
82
+ getCachedJWKS,
83
+
71
84
  // Authorization
72
85
  authorize,
73
86
  withAuthorization,