mirror of
https://github.com/logto-io/logto.git
synced 2025-01-13 21:30:30 -05:00
fix(core): remove grant id of token exchange (#6497)
This commit is contained in:
parent
f0bbc2a1f4
commit
06f98634c1
4 changed files with 22 additions and 10 deletions
|
@ -10,6 +10,7 @@ import {
|
||||||
import { generateStandardId } from '@logto/shared';
|
import { generateStandardId } from '@logto/shared';
|
||||||
import { conditional, trySafe } from '@silverhand/essentials';
|
import { conditional, trySafe } from '@silverhand/essentials';
|
||||||
import { type KoaContextWithOIDC, type UnknownObject } from 'oidc-provider';
|
import { type KoaContextWithOIDC, type UnknownObject } from 'oidc-provider';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { EnvSet } from '#src/env-set/index.js';
|
import { EnvSet } from '#src/env-set/index.js';
|
||||||
import { type CloudConnectionLibrary } from '#src/libraries/cloud-connection.js';
|
import { type CloudConnectionLibrary } from '#src/libraries/cloud-connection.js';
|
||||||
|
@ -142,10 +143,17 @@ export const getExtraTokenClaimsForJwtCustomization = async (
|
||||||
(await libraries.jwtCustomizers.getUserContext(token.accountId))
|
(await libraries.jwtCustomizers.getUserContext(token.accountId))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const subjectTokenResult = z
|
||||||
|
.object({
|
||||||
|
subjectTokenId: z.string(),
|
||||||
|
})
|
||||||
|
.safeParse(token.extra);
|
||||||
const subjectToken =
|
const subjectToken =
|
||||||
isTokenClientCredentials || token.gty !== GrantType.TokenExchange
|
isTokenClientCredentials || token.gty !== GrantType.TokenExchange
|
||||||
? undefined
|
? undefined
|
||||||
: await trySafe(async () => queries.subjectTokens.findSubjectToken(token.grantId));
|
: subjectTokenResult.success
|
||||||
|
? await queries.subjectTokens.findSubjectToken(subjectTokenResult.data.subjectTokenId)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const payload: CustomJwtFetcher = {
|
const payload: CustomJwtFetcher = {
|
||||||
script,
|
script,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { generateStandardShortId } from '@logto/shared';
|
|
||||||
import { trySafe } from '@silverhand/essentials';
|
import { trySafe } from '@silverhand/essentials';
|
||||||
import { errors } from 'oidc-provider';
|
import { errors } from 'oidc-provider';
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ export const validateSubjectToken = async (
|
||||||
queries: Queries,
|
queries: Queries,
|
||||||
subjectToken: string,
|
subjectToken: string,
|
||||||
type: string
|
type: string
|
||||||
): Promise<{ userId: string; grantId: string; subjectTokenId?: string }> => {
|
): Promise<{ userId: string; subjectTokenId?: string }> => {
|
||||||
const {
|
const {
|
||||||
subjectTokens: { findSubjectToken },
|
subjectTokens: { findSubjectToken },
|
||||||
personalAccessTokens: { findByValue },
|
personalAccessTokens: { findByValue },
|
||||||
|
@ -27,7 +26,6 @@ export const validateSubjectToken = async (
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userId: token.userId,
|
userId: token.userId,
|
||||||
grantId: token.id,
|
|
||||||
subjectTokenId: token.id,
|
subjectTokenId: token.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -39,7 +37,7 @@ export const validateSubjectToken = async (
|
||||||
new InvalidGrant('subject token is expired')
|
new InvalidGrant('subject token is expired')
|
||||||
);
|
);
|
||||||
|
|
||||||
return { userId: token.userId, grantId: generateStandardShortId() };
|
return { userId: token.userId };
|
||||||
}
|
}
|
||||||
throw new InvalidGrant('unsupported subject token type');
|
throw new InvalidGrant('unsupported subject token type');
|
||||||
};
|
};
|
||||||
|
|
|
@ -180,7 +180,6 @@ describe('token exchange', () => {
|
||||||
expect(value).toMatchObject({
|
expect(value).toMatchObject({
|
||||||
accountId,
|
accountId,
|
||||||
clientId,
|
clientId,
|
||||||
grantId: subjectTokenId,
|
|
||||||
gty: 'urn:ietf:params:oauth:grant-type:token-exchange',
|
gty: 'urn:ietf:params:oauth:grant-type:token-exchange',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -244,7 +243,6 @@ describe('token exchange', () => {
|
||||||
expect(value).toMatchObject({
|
expect(value).toMatchObject({
|
||||||
accountId,
|
accountId,
|
||||||
clientId,
|
clientId,
|
||||||
grantId: subjectTokenId,
|
|
||||||
aud: 'urn:logto:organization:some_org_id',
|
aud: 'urn:logto:organization:some_org_id',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -82,7 +82,7 @@ export const buildHandler: (
|
||||||
scopes: oidcScopes,
|
scopes: oidcScopes,
|
||||||
} = providerInstance.configuration();
|
} = providerInstance.configuration();
|
||||||
|
|
||||||
const { userId, grantId, subjectTokenId } = await validateSubjectToken(
|
const { userId, subjectTokenId } = await validateSubjectToken(
|
||||||
queries,
|
queries,
|
||||||
String(params.subject_token),
|
String(params.subject_token),
|
||||||
String(params.subject_token_type)
|
String(params.subject_token_type)
|
||||||
|
@ -103,9 +103,14 @@ export const buildHandler: (
|
||||||
clientId: client.clientId,
|
clientId: client.clientId,
|
||||||
gty: GrantType.TokenExchange,
|
gty: GrantType.TokenExchange,
|
||||||
client,
|
client,
|
||||||
grantId,
|
// The token exchange grant type does not have a grant ID or grant object,
|
||||||
|
// so we use an empty string here.
|
||||||
|
grantId: '',
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
scope: undefined!,
|
scope: undefined!,
|
||||||
|
extra: {
|
||||||
|
...(subjectTokenId ? { subjectTokenId } : {}),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await handleDPoP(ctx, accessToken);
|
await handleDPoP(ctx, accessToken);
|
||||||
|
@ -184,7 +189,10 @@ export const buildHandler: (
|
||||||
// @see https://github.com/panva/node-oidc-provider/blob/main/lib/models/formats/jwt.js#L118
|
// @see https://github.com/panva/node-oidc-provider/blob/main/lib/models/formats/jwt.js#L118
|
||||||
// We save the `act` data in the `extra` field temporarily,
|
// We save the `act` data in the `extra` field temporarily,
|
||||||
// so that we can get this context it in the `extraTokenClaims` function and add it to the JWT.
|
// so that we can get this context it in the `extraTokenClaims` function and add it to the JWT.
|
||||||
accessToken.extra = { act: { sub: actorId } } satisfies TokenExchangeAct;
|
accessToken.extra = {
|
||||||
|
...accessToken.extra,
|
||||||
|
...({ act: { sub: actorId } } satisfies TokenExchangeAct),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.oidc.entity('AccessToken', accessToken);
|
ctx.oidc.entity('AccessToken', accessToken);
|
||||||
|
|
Loading…
Add table
Reference in a new issue