Skip to content

Commit 82e4198

Browse files
shawn weeryhuz
authored andcommitted
[MOL-13183][SW] add getUserInfo method
- deprecated non-PKCE flow methods
1 parent 430b14e commit 82e4198

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

src/singpass/singpass-helper-ndi.ts

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { AxiosInstance, AxiosProxyConfig } from "axios";
2+
import { generators } from "openid-client";
23
import * as querystringUtil from "querystring";
34
import { createClient } from "../client/axios-client";
45
import { JweUtil } from "../util";
56
import { SingpassMyInfoError } from "../util/error/SingpassMyinfoError";
6-
import { logger } from "../util/Logger";
7-
import { TokenPayload, TokenResponse } from "./shared-constants";
87
import { Key } from "../util/KeyUtil";
8+
import { logger } from "../util/Logger";
99
import { createClientAssertion } from "../util/SigningUtil";
10-
import { generators } from "openid-client";
10+
import { TokenPayload, TokenResponse } from "./shared-constants";
1111

1212
export interface NdiOidcHelperConstructor {
1313
oidcConfigUrl: string;
@@ -21,6 +21,7 @@ export interface NdiOidcHelperConstructor {
2121
interface OidcConfig {
2222
issuer: string;
2323
authorization_endpoint: string;
24+
userinfo_endpoint: string;
2425
token_endpoint: string;
2526
jwks_uri: string;
2627
}
@@ -117,19 +118,58 @@ export class NdiOidcHelper {
117118
logger.error("Failed to get ID token: invalid response data", response.data);
118119
throw new SingpassMyInfoError("Failed to get ID token");
119120
}
121+
if (!response.data.access_token) {
122+
logger.error("Failed to get access token: invalid response data", response.data);
123+
throw new SingpassMyInfoError("Failed to get access token");
124+
}
120125
return response.data;
121126
};
122127

128+
public getUserInfo = async (jweResponse: string, overrideDecryptKey?: Key) => {
129+
try {
130+
const keys = await this.getKeys();
131+
132+
const finalDecryptionKey = overrideDecryptKey ?? this.jweDecryptKey;
133+
const decryptedJwe = await JweUtil.decryptJWE(
134+
jweResponse,
135+
finalDecryptionKey.key,
136+
finalDecryptionKey.format,
137+
);
138+
const jwsPayload = decryptedJwe.payload.toString();
139+
try {
140+
const verified = await JweUtil.verifyJwsUsingKeyStore(jwsPayload, keys);
141+
return JSON.parse(verified.payload.toString()) as TokenPayload;
142+
} catch (e) {
143+
logger.error("could not verify user info payload", e);
144+
throw e;
145+
}
146+
} catch (e) {
147+
logger.error("Failed to get user info", e);
148+
throw e;
149+
}
150+
};
151+
152+
private getKeys = async () => {
153+
const { jwks_uri } = await this.oidcConfig;
154+
const {
155+
data: { keys },
156+
} = await this.axiosClient.get<{ keys: object[] }>(jwks_uri);
157+
158+
return keys;
159+
};
160+
161+
// =============================================================================
162+
// Deprecated
163+
// =============================================================================
123164
/**
165+
* @deprecated should not be used with full NDI PKCE flow
166+
*
124167
* Decrypts the ID Token JWT inside the TokenResponse to get the payload
125168
* Use extractNricAndUuidFromPayload on the returned Token Payload to get the NRIC and UUID
126169
*/
127170
public async getIdTokenPayload(tokens: TokenResponse, overrideDecryptKey?: Key): Promise<TokenPayload> {
128171
try {
129-
const { jwks_uri } = await this.oidcConfig;
130-
const {
131-
data: { keys },
132-
} = await this.axiosClient.get<{ keys: object[] }>(jwks_uri);
172+
const keys = await this.getKeys();
133173

134174
const { id_token } = tokens;
135175

@@ -150,6 +190,8 @@ export class NdiOidcHelper {
150190
}
151191

152192
/**
193+
* @deprecated should not be used with full NDI PKCE flow
194+
*
153195
* Returns the nric and uuid from the token payload
154196
*/
155197
public extractNricAndUuidFromPayload(payload: TokenPayload): { nric: string; uuid: string } {

0 commit comments

Comments
 (0)