mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
fix(core): fix getResourceServerInfo userId (#2919)
This commit is contained in:
parent
849c7fb784
commit
f66fad07b9
4 changed files with 67 additions and 15 deletions
|
@ -92,9 +92,8 @@ export default function initOidc(queries: Queries): Provider {
|
||||||
throw new errors.InvalidTarget();
|
throw new errors.InvalidTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
const scopes = ctx.oidc.account
|
const userId = ctx.oidc.session?.accountId;
|
||||||
? await findUserScopesForResourceId(ctx.oidc.account.accountId, resourceServer.id)
|
const scopes = userId ? await findUserScopesForResourceId(userId, resourceServer.id) : [];
|
||||||
: [];
|
|
||||||
|
|
||||||
const { accessTokenTtl: accessTokenTTL } = resourceServer;
|
const { accessTokenTtl: accessTokenTTL } = resourceServer;
|
||||||
|
|
||||||
|
|
|
@ -1,49 +1,79 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import { fetchTokenByRefreshToken } from '@logto/js';
|
import { fetchTokenByRefreshToken } from '@logto/js';
|
||||||
import { managementResource, InteractionEvent } from '@logto/schemas';
|
import {
|
||||||
|
managementResource,
|
||||||
|
InteractionEvent,
|
||||||
|
adminConsoleAdminRoleId,
|
||||||
|
managementResourceScope,
|
||||||
|
} from '@logto/schemas';
|
||||||
import { assert } from '@silverhand/essentials';
|
import { assert } from '@silverhand/essentials';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
import { putInteraction } from '#src/api/index.js';
|
import { putInteraction } from '#src/api/index.js';
|
||||||
|
import { assignUsersToRole } from '#src/api/role.js';
|
||||||
import MockClient, { defaultConfig } from '#src/client/index.js';
|
import MockClient, { defaultConfig } from '#src/client/index.js';
|
||||||
import { logtoUrl } from '#src/constants.js';
|
import { logtoUrl } from '#src/constants.js';
|
||||||
import { processSession } from '#src/helpers/client.js';
|
import { processSession } from '#src/helpers/client.js';
|
||||||
import { createUserByAdmin } from '#src/helpers/index.js';
|
import { createUserByAdmin } from '#src/helpers/index.js';
|
||||||
import { enableAllPasswordSignInMethods } from '#src/helpers/sign-in-experience.js';
|
import { enableAllPasswordSignInMethods } from '#src/helpers/sign-in-experience.js';
|
||||||
import { generateUsername, generatePassword } from '#src/utils.js';
|
import { generateUsername, generatePassword, getAccessTokenPayload } from '#src/utils.js';
|
||||||
|
|
||||||
describe('get access token', () => {
|
describe('get access token', () => {
|
||||||
const username = generateUsername();
|
const username = generateUsername();
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
|
const guestUsername = generateUsername();
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await createUserByAdmin(username, password);
|
await createUserByAdmin(guestUsername, password);
|
||||||
|
const user = await createUserByAdmin(username, password);
|
||||||
|
await assignUsersToRole([user.id], adminConsoleAdminRoleId);
|
||||||
await enableAllPasswordSignInMethods();
|
await enableAllPasswordSignInMethods();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sign-in and getAccessToken', async () => {
|
it('sign-in and getAccessToken with admin user', async () => {
|
||||||
const client = new MockClient({ resources: [managementResource.indicator] });
|
const client = new MockClient({
|
||||||
|
resources: [managementResource.indicator],
|
||||||
|
scopes: [managementResourceScope.name],
|
||||||
|
});
|
||||||
await client.initSession();
|
await client.initSession();
|
||||||
|
|
||||||
await client.successSend(putInteraction, {
|
await client.successSend(putInteraction, {
|
||||||
event: InteractionEvent.SignIn,
|
event: InteractionEvent.SignIn,
|
||||||
identifier: { username, password },
|
identifier: { username, password },
|
||||||
});
|
});
|
||||||
|
|
||||||
const { redirectTo } = await client.submitInteraction();
|
const { redirectTo } = await client.submitInteraction();
|
||||||
|
|
||||||
await processSession(client, redirectTo);
|
await processSession(client, redirectTo);
|
||||||
|
|
||||||
const accessToken = await client.getAccessToken(managementResource.indicator);
|
const accessToken = await client.getAccessToken(managementResource.indicator);
|
||||||
|
|
||||||
expect(accessToken).not.toBeNull();
|
expect(accessToken).not.toBeNull();
|
||||||
|
expect(getAccessTokenPayload(accessToken)).toHaveProperty(
|
||||||
|
'scope',
|
||||||
|
managementResourceScope.name
|
||||||
|
);
|
||||||
|
|
||||||
// Request for invalid resource should throw
|
// Request for invalid resource should throw
|
||||||
void expect(client.getAccessToken('api.foo.com')).rejects.toThrow();
|
void expect(client.getAccessToken('api.foo.com')).rejects.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sign-in and getAccessToken with guest user', async () => {
|
||||||
|
const client = new MockClient({
|
||||||
|
resources: [managementResource.indicator],
|
||||||
|
scopes: [managementResourceScope.name],
|
||||||
|
});
|
||||||
|
await client.initSession();
|
||||||
|
await client.successSend(putInteraction, {
|
||||||
|
event: InteractionEvent.SignIn,
|
||||||
|
identifier: { username: guestUsername, password },
|
||||||
|
});
|
||||||
|
const { redirectTo } = await client.submitInteraction();
|
||||||
|
await processSession(client, redirectTo);
|
||||||
|
const accessToken = await client.getAccessToken(managementResource.indicator);
|
||||||
|
|
||||||
|
expect(getAccessTokenPayload(accessToken)).not.toHaveProperty(
|
||||||
|
'scope',
|
||||||
|
managementResourceScope.name
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('sign-in and get multiple Access Token by the same Refresh Token within refreshTokenReuseInterval', async () => {
|
it('sign-in and get multiple Access Token by the same Refresh Token within refreshTokenReuseInterval', async () => {
|
||||||
const client = new MockClient({ resources: [managementResource.indicator] });
|
const client = new MockClient({ resources: [managementResource.indicator] });
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { assert } from '@silverhand/essentials';
|
||||||
|
|
||||||
export const generateName = () => crypto.randomUUID();
|
export const generateName = () => crypto.randomUUID();
|
||||||
export const generateUserId = () => crypto.randomUUID();
|
export const generateUserId = () => crypto.randomUUID();
|
||||||
export const generateUsername = () => `usr_${crypto.randomUUID().replaceAll('-', '_')}`;
|
export const generateUsername = () => `usr_${crypto.randomUUID().replaceAll('-', '_')}`;
|
||||||
|
@ -19,3 +21,12 @@ export const waitFor = async (ms: number) =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
setTimeout(resolve, ms);
|
setTimeout(resolve, ms);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getAccessTokenPayload = (accessToken: string): Record<string, unknown> => {
|
||||||
|
const payloadPart = accessToken.split('.')[1];
|
||||||
|
assert(typeof payloadPart === 'string', new Error('Invalid access token'));
|
||||||
|
const payload = Buffer.from(payloadPart, 'base64').toString();
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
return JSON.parse(payload) as Record<string, unknown>;
|
||||||
|
};
|
||||||
|
|
|
@ -2330,6 +2330,18 @@ packages:
|
||||||
lodash.once: 4.1.1
|
lodash.once: 4.1.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@logto/client/1.0.0-beta.15:
|
||||||
|
resolution: {integrity: sha512-+CrgyUcBcTILpfMPtwIEwBD60XgXUCdu7MpnvNZjd0sNaUpAoyFbUiRKzvbFeF7w9Nc4zO/kgAwbk36kqTXsvw==}
|
||||||
|
dependencies:
|
||||||
|
'@logto/core-kit': 1.0.0-beta.20
|
||||||
|
'@logto/js': 1.0.0-beta.14
|
||||||
|
'@silverhand/essentials': 1.3.0
|
||||||
|
camelcase-keys: 7.0.2
|
||||||
|
jose: 4.11.1
|
||||||
|
lodash.get: 4.4.2
|
||||||
|
lodash.once: 4.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@logto/core-kit/1.0.0-beta.20:
|
/@logto/core-kit/1.0.0-beta.20:
|
||||||
resolution: {integrity: sha512-seYvL/aGYRfO4d0FYfKIW/Cu9PnFMRpRM5/oRXwXbcbv+LY1a3TcAX0itrVXeBygIrxiAmWd9DL7CGIWzb48Qg==}
|
resolution: {integrity: sha512-seYvL/aGYRfO4d0FYfKIW/Cu9PnFMRpRM5/oRXwXbcbv+LY1a3TcAX0itrVXeBygIrxiAmWd9DL7CGIWzb48Qg==}
|
||||||
engines: {node: ^16.0.0}
|
engines: {node: ^16.0.0}
|
||||||
|
@ -2362,7 +2374,7 @@ packages:
|
||||||
/@logto/node/1.0.0-beta.14:
|
/@logto/node/1.0.0-beta.14:
|
||||||
resolution: {integrity: sha512-+0S6lBBcG3pOmjEMRQnD+6X0MJ3V3E/4In59ckl/uVr/UgIufvOKWJwWCfsVKyguaO3QweJn19x7YkF8FyO31g==}
|
resolution: {integrity: sha512-+0S6lBBcG3pOmjEMRQnD+6X0MJ3V3E/4In59ckl/uVr/UgIufvOKWJwWCfsVKyguaO3QweJn19x7YkF8FyO31g==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@logto/client': 1.0.0-beta.14
|
'@logto/client': 1.0.0-beta.15
|
||||||
'@silverhand/essentials': 1.3.0
|
'@silverhand/essentials': 1.3.0
|
||||||
js-base64: 3.7.3
|
js-base64: 3.7.3
|
||||||
node-fetch: 2.6.7
|
node-fetch: 2.6.7
|
||||||
|
|
Loading…
Reference in a new issue