Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expose id token #68

Merged
merged 6 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/SgidClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,20 @@ export class SgidClient {
{ nonce: nonce ?? undefined, code_verifier: codeVerifier },
)
const { sub } = tokenSet.claims()
const { access_token: accessToken } = tokenSet

const { access_token: accessToken, id_token: idToken } = tokenSet

// Note that this falsey check for the id token will never be run
// because the nodejs openid-client library already does it for us
// Doing a check here just for type safety
if (!idToken) throw new Error(Errors.NO_ID_TOKEN_ERROR)
if (!sub) {
throw new Error(Errors.NO_SUB_ERROR)
}
if (!accessToken) {
throw new Error(Errors.NO_ACCESS_TOKEN_ERROR)
}
return { sub, accessToken }
return { sub, accessToken, idToken }
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const MISSING_REDIRECT_URI_ERROR =
export const NO_SUB_ERROR = 'Authorization server did not return the sub claim'
export const NO_ACCESS_TOKEN_ERROR =
'Authorization server did not return an access token'
export const NO_ID_TOKEN_ERROR =
'Authorization server did not return an ID token'

// userinfo errors
export const PRIVATE_KEY_IMPORT_ERROR =
Expand Down
6 changes: 5 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export type CallbackParams = {
codeVerifier: string
}

export type CallbackReturn = { sub: string; accessToken: string }
export type CallbackReturn = {
sub: string
accessToken: string
idToken: string
}

export type UserInfoParams = {
sub: string
Expand Down
6 changes: 6 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ export function isStringifiedArrayOrObject(
)
}

export function isNonEmptyString(value: unknown): value is string {
if (typeof value !== 'string') return false
if (value === '') return false
return true
}

export function safeJsonParse(jsonString: string): ParsedSgidDataValue {
try {
return JSON.parse(jsonString)
Expand Down
12 changes: 12 additions & 0 deletions test/unit/SgidClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
MOCK_USERINFO_PLAINTEXT,
} from './mocks/constants'
import {
tokenHandlerNoIdToken,
tokenHandlerNoSub,
tokenHandlerNoToken,
userInfoHandlerMalformedData,
Expand Down Expand Up @@ -327,6 +328,17 @@ describe('SgidClient', () => {
).rejects.toThrow('Authorization server did not return an access token')
})

it('should throw when no ID token is returned', async () => {
server.use(tokenHandlerNoIdToken)

await expect(
client.callback({
code: MOCK_AUTH_CODE,
codeVerifier: MOCK_CODE_VERIFIER,
}),
).rejects.toThrow('id_token not present in TokenSet')
})

it('should throw when sub is empty', async () => {
server.use(tokenHandlerNoSub)

Expand Down
15 changes: 15 additions & 0 deletions test/unit/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,21 @@ export const tokenHandlerNoToken = rest.post(
},
)

/**
* Handler to test case where server doesn't return an id token
*/
export const tokenHandlerNoIdToken = rest.post(
MOCK_TOKEN_ENDPOINT,
(_req, res, ctx) => {
return res(
ctx.status(200),
ctx.json({
access_token: MOCK_ACCESS_TOKEN,
}),
)
},
)

/**
* Handler to test case where sub is empty
*/
Expand Down