Skip to content

Commit a25450f

Browse files
committed
fix: add cryptographic validation to getUserFromSession for security and update JSDocs
1 parent d7cae17 commit a25450f

File tree

5 files changed

+45
-5
lines changed

5 files changed

+45
-5
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ describe('token-utils', () => {
117117
validationDetails
118118
);
119119

120-
const storedUser = await getUserFromSession(sessionManager);
120+
const storedUser = await getUserFromSession(sessionManager, validationDetails);
121121
const expectedUser = {
122122
family_name: idTokenPayload.family_name,
123123
given_name: idTokenPayload.given_name,

lib/sdk/clients/browser/authcode-with-pkce.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ const createAuthCodeWithPKCEClient = (options: BrowserPKCEClientOptions) => {
114114
if (!(await isAuthenticated())) {
115115
throw new Error('Cannot get user details, no authentication credential found');
116116
}
117-
return (await utilities.getUserFromSession(sessionManager))!;
117+
return (await utilities.getUserFromSession(sessionManager, client.tokenValidationDetails))!;
118118
};
119119

120120
/**

lib/sdk/clients/server/authorization-code.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ const createAuthorizationCodeClient = (
139139
if (!(await isAuthenticated(sessionManager))) {
140140
throw new Error('Cannot get user details, no authentication credential found');
141141
}
142-
return (await utilities.getUserFromSession(sessionManager))!;
142+
return (await utilities.getUserFromSession(sessionManager, client.tokenValidationDetails))!;
143143
};
144144

145145
/**

lib/sdk/utilities/token-claims.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { jwtDecoder } from '@kinde/jwt-decoder';
55
/**
66
* Method extracts the provided claim from the provided token type in the
77
* current session.
8+
*
9+
* Security Model: This function assumes tokens have been cryptographically
10+
* validated during session commit via commitTokensToSession. It performs
11+
* decoding only on pre-validated tokens without re-validation by design.
12+
*
813
* @param {SessionManager} sessionManager
914
* @param {string} claim
1015
* @param {ClaimTokenType} type
@@ -24,6 +29,11 @@ export const getClaimValue = async (
2429
/**
2530
* Method extracts the provided claim from the provided token type in the
2631
* current session, the returned object includes the provided claim.
32+
*
33+
* Security Model: This function assumes tokens have been cryptographically
34+
* validated during session commit via commitTokensToSession. It performs
35+
* decoding only on pre-validated tokens without re-validation by design.
36+
*
2737
* @param {SessionManager} sessionManager
2838
* @param {string} claim
2939
* @param {ClaimTokenType} type
@@ -44,6 +54,11 @@ export const getClaim = async (
4454
* Method returns the organization code from the current session and returns
4555
* a boolean in the returned object indicating if the provided permission is
4656
* present in the session.
57+
*
58+
* Security Model: This function assumes tokens have been cryptographically
59+
* validated during session commit via commitTokensToSession. It performs
60+
* decoding only on pre-validated tokens without re-validation by design.
61+
*
4762
* @param {SessionManager} sessionManager
4863
* @param {string} name
4964
* @returns {{ orgCode: string | null, isGranted: boolean }}
@@ -68,6 +83,11 @@ export const getPermission = async (
6883

6984
/**
7085
* Method extracts the organization code from the current session.
86+
*
87+
* Security Model: This function assumes tokens have been cryptographically
88+
* validated during session commit via commitTokensToSession. It performs
89+
* decoding only on pre-validated tokens without re-validation by design.
90+
*
7191
* @param {SessionManager} sessionManager
7292
* @returns {{ orgCode: string | null }}
7393
*/
@@ -82,6 +102,11 @@ export const getOrganization = async (
82102
/**
83103
* Method extracts all the permission and the organization code in the access
84104
* token in the current session.
105+
*
106+
* Security Model: This function assumes tokens have been cryptographically
107+
* validated during session commit via commitTokensToSession. It performs
108+
* decoding only on pre-validated tokens without re-validation by design.
109+
*
85110
* @param {SessionManager} sessionManager
86111
* @returns {{ permissions: string[], orgCode: string | null }}
87112
*/
@@ -105,6 +130,11 @@ export const getPermissions = async (
105130
/**
106131
* Method extracts all organization codes from the id token in the current
107132
* session.
133+
*
134+
* Security Model: This function assumes tokens have been cryptographically
135+
* validated during session commit via commitTokensToSession. It performs
136+
* decoding only on pre-validated tokens without re-validation by design.
137+
*
108138
* @param {SessionManager} sessionManager
109139
* @returns {{ orgCodes: string[] }}
110140
*/

lib/sdk/utilities/token-utils.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,22 @@ export const getAccessToken = async (
111111
* Extracts the user information from the current session returns null if
112112
* the token is not found.
113113
* @param {SessionManager} sessionManager
114-
* @returns {string | null}
114+
* @param {TokenValidationDetailsType} validationDetails
115+
* @returns {UserType | null}
115116
*/
116117
export const getUserFromSession = async (
117-
sessionManager: SessionManager
118+
sessionManager: SessionManager,
119+
validationDetails: TokenValidationDetailsType
118120
): Promise<UserType | null> => {
119121
const idTokenString = (await sessionManager.getSessionItem('id_token')) as string;
122+
const validation = await validateToken({
123+
token: idTokenString,
124+
domain: validationDetails.issuer,
125+
});
126+
if (!validation.valid) {
127+
throw new Error('Invalid ID token');
128+
}
129+
120130
const payload: Record<string, unknown> = jwtDecoder(idTokenString) ?? {};
121131
if (Object.keys(payload).length === 0) {
122132
throw new Error('Invalid ID token');

0 commit comments

Comments
 (0)