Skip to content

Commit

Permalink
feat(core): handle oidc scopes for token exchange
Browse files Browse the repository at this point in the history
  • Loading branch information
wangsijie committed Jul 3, 2024
1 parent d15f6bc commit ca7202f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
11 changes: 9 additions & 2 deletions packages/core/src/oidc/grants/token-exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export const buildHandler: (
const providerInstance = instance(provider);
const {
features: { userinfo, resourceIndicators },
scopes: oidcScopes,
} = providerInstance.configuration();

const subjectToken = await trySafe(async () => findSubjectToken(String(params.subject_token)));
Expand Down Expand Up @@ -186,9 +187,15 @@ export const buildHandler: (
.filter(Set.prototype.has.bind(accessToken.resourceServer.scopes))
.join(' ');
} else {
// TODO: (LOG-9166) Check claims and scopes
accessToken.claims = ctx.oidc.claims;
accessToken.scope = Array.from(scope).join(' ');
// Filter scopes from `oidcScopes`,
// in other grants, this is done by `Grant` class
// See https://github.com/panva/node-oidc-provider/blob/0c569cf5c36dd5faa105fb931a43b2e587530def/lib/helpers/oidc_context.js#L159
accessToken.scope = Array.from(scope)
// Wrong typing for oidc-provider, `oidcScopes` is actully a Set,
// wrap it with `new Set` to make it work
.filter((name) => new Set(oidcScopes).has(name))
.join(' ');
}
/* eslint-enable @silverhand/fp/no-mutation, @typescript-eslint/no-unsafe-assignment */

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { buildOrganizationUrn } from '@logto/core-kit';
import { UserScope, buildOrganizationUrn } from '@logto/core-kit';
import { decodeAccessToken } from '@logto/js';
import { ApplicationType, GrantType, MfaFactor } from '@logto/schemas';
import { formUrlEncodedHeaders } from '@logto/shared';
Expand Down Expand Up @@ -137,6 +137,28 @@ describe('Token Exchange', () => {

await deleteApplication(thirdPartyApplication.id);
});

it('should filter out non-oidc scopes', async () => {
const { subjectToken } = await createSubjectToken(userId);

const body = await oidcApi
.post('token', {
headers: formUrlEncodedHeaders,
body: new URLSearchParams({
client_id: applicationId,
grant_type: GrantType.TokenExchange,
subject_token: subjectToken,
subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',
scope: [UserScope.Profile, 'non-oidc-scope'].join(' '),
}),
})
.json();

expect(body).toHaveProperty('access_token');
expect(body).toHaveProperty('token_type', 'Bearer');
expect(body).toHaveProperty('expires_in');
expect(body).toHaveProperty('scope', UserScope.Profile);
});
});

describe('get access token for organization', () => {
Expand Down

0 comments on commit ca7202f

Please sign in to comment.