Skip to content

Commit 3acb2eb

Browse files
authored
Merge pull request #76 from Koosha-Owji/feat/migrate-jose-to-kinde-jwt-validator
Feat/migrate jose to kinde jwt validator/decoder
2 parents f31bd0a + 1d55abf commit 3acb2eb

18 files changed

+138
-120
lines changed

lib/__tests__/mocks.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,24 @@ class ServerSessionManager implements SessionManager {
129129
export const sessionManager = new ServerSessionManager();
130130

131131
global.fetch = fetchClient;
132+
133+
// Mock @kinde/jwt-validator
134+
export const createJwtValidatorMock = () => ({
135+
validateToken: vi.fn().mockImplementation(async ({ token, domain }) => {
136+
if (!token) {
137+
return { valid: false, message: 'Token is required' };
138+
}
139+
140+
if (!domain) {
141+
return { valid: false, message: 'Domain is required' };
142+
}
143+
144+
const jwtParts = token.split('.');
145+
if (jwtParts.length !== 3) {
146+
return { valid: false, message: 'Invalid JWT format' };
147+
}
148+
149+
// If it passes basic validation, return true (simplified for testing)
150+
return { valid: true, message: 'Token is valid' };
151+
}),
152+
});

lib/__tests__/sdk/oauth2-flows/AuthCodeWithPKCE.spec.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { base64UrlEncode, sha256 } from '../../../sdk/utilities';
66
import { AuthCodeWithPKCE } from '../../../sdk/oauth2-flows';
77
import { getSDKHeader } from '../../../sdk/version';
88
import * as mocks from '../../mocks';
9-
import { describe, it, expect, beforeAll, afterEach } from 'vitest';
9+
import { describe, it, expect, afterEach } from 'vitest';
1010

1111
describe('AuthCodeWitPKCE', () => {
1212
const { sessionManager } = mocks;
@@ -17,11 +17,6 @@ describe('AuthCodeWitPKCE', () => {
1717
clientId: 'client-id',
1818
};
1919

20-
beforeAll(async () => {
21-
const { publicKey } = await mocks.getKeys();
22-
clientConfig.jwks = { keys: [publicKey] };
23-
});
24-
2520
describe('new AuthCodeWithPKCE', () => {
2621
it('can construct AuthCodeWithPKCE instance', () => {
2722
expect(() => new AuthCodeWithPKCE(clientConfig)).not.toThrowError();

lib/__tests__/sdk/oauth2-flows/AuthorizationCode.spec.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010

1111
import { KindeSDKError, KindeSDKErrorCode } from '../../../sdk/exceptions';
1212
import { generateRandomString } from '../../../sdk/utilities';
13-
import { describe, it, expect, beforeAll, afterEach } from 'vitest';
13+
import { describe, it, expect, afterEach } from 'vitest';
1414

1515
describe('AuthorizationCode', () => {
1616
const { sessionManager } = mocks;
@@ -22,11 +22,6 @@ describe('AuthorizationCode', () => {
2222
clientId: 'client-id',
2323
};
2424

25-
beforeAll(async () => {
26-
const { publicKey } = await mocks.getKeys();
27-
clientConfig.jwks = { keys: [publicKey] };
28-
});
29-
3025
describe('new AuthorizationCode', () => {
3126
it('can construct AuthorizationCode instance', () => {
3227
expect(

lib/__tests__/sdk/oauth2-flows/ClientCredentials.spec.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { importJWK } from 'jose';
21
import { ClientCredentials } from '../../../sdk/oauth2-flows/ClientCredentials';
32
import { type ClientCredentialsOptions } from '../../../sdk/oauth2-flows/types';
43
import {
@@ -32,14 +31,9 @@ describe('ClientCredentials', () => {
3231
let validationDetails: TokenValidationDetailsType;
3332

3433
beforeAll(async () => {
35-
const { publicKey } = await mocks.getKeys();
36-
3734
validationDetails = {
3835
issuer: clientConfig.authDomain,
39-
keyProvider: async () => await importJWK(publicKey, mocks.mockJwtAlg),
4036
};
41-
42-
clientConfig.jwks = { keys: [publicKey] };
4337
});
4438

4539
const body = new URLSearchParams({

lib/__tests__/sdk/utilities/feature-flags.spec.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,17 @@ import {
77
getFlag,
88
type TokenValidationDetailsType,
99
} from '../../../sdk/utilities';
10-
import { importJWK } from 'jose';
1110

1211
describe('feature-flags', () => {
1312
let mockAccessToken: Awaited<ReturnType<typeof mocks.getMockAccessToken>>;
1413
const { sessionManager } = mocks;
14+
const authDomain = 'local-testing@kinde.com';
1515

1616
let validationDetails: TokenValidationDetailsType;
1717

1818
beforeAll(async () => {
19-
const { publicKey } = await mocks.getKeys();
20-
2119
validationDetails = {
22-
issuer: '',
23-
keyProvider: async () => await importJWK(publicKey, mocks.mockJwtAlg),
20+
issuer: authDomain,
2421
};
2522
});
2623

lib/__tests__/sdk/utilities/token-claims.spec.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,20 @@ import {
88
getClaim,
99
type TokenValidationDetailsType,
1010
} from '../../../sdk/utilities';
11-
import { importJWK } from 'jose';
1211
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
1312

1413
describe('token-claims', () => {
1514
let mockAccessToken: Awaited<ReturnType<typeof mocks.getMockAccessToken>>;
1615
let mockIdToken: Awaited<ReturnType<typeof mocks.getMockIdToken>>;
17-
const authDomain = 'https://local-testing@kinde.com';
16+
const authDomain = 'local-testing@kinde.com';
1817
const { sessionManager } = mocks;
1918

2019
let validationDetails: TokenValidationDetailsType;
2120

2221
beforeAll(async () => {
23-
const { publicKey } = await mocks.getKeys();
24-
2522
validationDetails = {
2623
issuer: authDomain,
27-
keyProvider: async () => await importJWK(publicKey, mocks.mockJwtAlg),
2824
};
29-
3025
mockAccessToken = await mocks.getMockAccessToken();
3126
mockIdToken = await mocks.getMockIdToken();
3227
await sessionManager.setSessionItem('access_token', mockAccessToken.token);

lib/__tests__/sdk/utilities/token-utils.spec.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,15 @@ import {
1010
} from '../../../sdk/utilities';
1111

1212
import { KindeSDKError, KindeSDKErrorCode } from '../../../sdk/exceptions';
13-
import { importJWK } from 'jose';
1413

1514
describe('token-utils', () => {
1615
const domain = 'local-testing@kinde.com';
1716
const { sessionManager } = mocks;
1817
let validationDetails: TokenValidationDetailsType;
1918

2019
beforeAll(async () => {
21-
const { publicKey } = await mocks.getKeys();
22-
2320
validationDetails = {
2421
issuer: domain,
25-
keyProvider: async () => await importJWK(publicKey, mocks.mockJwtAlg),
2622
};
2723
});
2824

lib/sdk/clients/server/index.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import createAuthCodeClient from './authorization-code.js';
2-
import { isNodeEnvironment } from '../../environment.js';
32
import createCCClient from './client-credentials.js';
43
import { GrantType } from '../../oauth2-flows/index.js';
54

@@ -30,10 +29,6 @@ export const createKindeServerClient = <G extends GrantType>(
3029
grantType: G,
3130
options: Options<G>
3231
) => {
33-
if (!isNodeEnvironment()) {
34-
throw new Error('this method must be invoked in a node.js environment');
35-
}
36-
3732
switch (grantType) {
3833
case GrantType.AUTHORIZATION_CODE: {
3934
const clientOptions = options as ACClientOptions;

lib/sdk/oauth2-flows/AuthCodeAbstract.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ import type {
1111
AuthorizationCodeOptions,
1212
AuthURLOptions,
1313
} from './types.js';
14-
import { createLocalJWKSet } from 'jose';
15-
import { getRemoteJwks } from '../utilities/remote-jwks-cache.js';
1614
import type { GeneratePortalUrlParams } from '@kinde/js-utils';
1715

1816
/**
@@ -37,17 +35,9 @@ export abstract class AuthCodeAbstract {
3735
this.userProfileEndpoint = `${authDomain}/oauth2/v2/user_profile`;
3836
this.authorizationEndpoint = `${authDomain}/oauth2/auth`;
3937
this.tokenEndpoint = `${authDomain}/oauth2/token`;
40-
const keyProvider = async () => {
41-
const func =
42-
config.jwks !== undefined
43-
? createLocalJWKSet(config.jwks)
44-
: await getRemoteJwks(authDomain);
45-
return await func({ alg: 'RS256' });
46-
};
4738
this.tokenValidationDetails = {
4839
issuer: config.authDomain,
4940
audience: config.audience,
50-
keyProvider,
5141
};
5242
}
5343

lib/sdk/oauth2-flows/ClientCredentials.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { createLocalJWKSet } from 'jose';
21
import { type SessionManager } from '../session-managers/index.js';
32
import * as utilities from '../utilities/index.js';
43
import { getSDKHeader } from '../version.js';
@@ -8,7 +7,6 @@ import type {
87
ClientCredentialsOptions,
98
OAuth2CCTokenResponse,
109
} from './types.js';
11-
import { getRemoteJwks } from '../utilities/remote-jwks-cache.js';
1210

1311
/**
1412
* Class provides implementation for the client credentials OAuth2.0 flow.
@@ -24,17 +22,9 @@ export class ClientCredentials {
2422
this.logoutEndpoint = `${authDomain}/logout?redirect=${logoutRedirectURL ?? ''}`;
2523
this.tokenEndpoint = `${authDomain}/oauth2/token`;
2624
this.config = config;
27-
const keyProvider = async () => {
28-
const func =
29-
config.jwks !== undefined
30-
? createLocalJWKSet(config.jwks)
31-
: await getRemoteJwks(authDomain);
32-
return await func({ alg: 'RS256' });
33-
};
3425
this.tokenValidationDetails = {
3526
issuer: config.authDomain,
3627
audience: config.audience,
37-
keyProvider,
3828
};
3929
}
4030

0 commit comments

Comments
 (0)