mirror of
https://github.com/logto-io/logto.git
synced 2025-01-20 21:32:31 -05:00
fix(core): fix consent scopes filter rule for non-3rd-party app (#5859)
This commit is contained in:
parent
304d948511
commit
1c414f1889
2 changed files with 68 additions and 10 deletions
|
@ -5,6 +5,7 @@ import { errors } from 'oidc-provider';
|
|||
import {
|
||||
filterResourceScopesForTheThirdPartyApplication,
|
||||
findResourceScopes,
|
||||
isThirdPartyApplication,
|
||||
} from '#src/oidc/resource.js';
|
||||
import type Libraries from '#src/tenants/Libraries.js';
|
||||
import type Queries from '#src/tenants/Queries.js';
|
||||
|
@ -118,19 +119,23 @@ export const filterAndParseMissingResourceScopes = async ({
|
|||
organizationId,
|
||||
});
|
||||
|
||||
const isThirdPartyApp = await isThirdPartyApplication(queries, applicationId);
|
||||
|
||||
// Filter the scopes for the third-party application.
|
||||
// Although the "missingResourceScopes" from the prompt details are already filtered,
|
||||
// there may be duplicated scopes from either resources or organization resources.
|
||||
const filteredScopes = await filterResourceScopesForTheThirdPartyApplication(
|
||||
libraries,
|
||||
applicationId,
|
||||
resourceIndicator,
|
||||
scopes,
|
||||
{
|
||||
includeOrganizationResourceScopes: Boolean(organizationId),
|
||||
includeResourceScopes: !organizationId,
|
||||
}
|
||||
);
|
||||
const filteredScopes = isThirdPartyApp
|
||||
? await filterResourceScopesForTheThirdPartyApplication(
|
||||
libraries,
|
||||
applicationId,
|
||||
resourceIndicator,
|
||||
scopes,
|
||||
{
|
||||
includeOrganizationResourceScopes: Boolean(organizationId),
|
||||
includeResourceScopes: !organizationId,
|
||||
}
|
||||
)
|
||||
: scopes;
|
||||
|
||||
return [
|
||||
resourceIndicator,
|
||||
|
|
|
@ -8,6 +8,7 @@ import { createApplication, deleteApplication } from '#src/api/application.js';
|
|||
import { consent, getConsentInfo, putInteraction } from '#src/api/interaction.js';
|
||||
import { OrganizationScopeApi } from '#src/api/organization-scope.js';
|
||||
import { createResource, deleteResource } from '#src/api/resource.js';
|
||||
import { assignUsersToRole, createRole, deleteRole } from '#src/api/role.js';
|
||||
import { createScope } from '#src/api/scope.js';
|
||||
import { initClient } from '#src/helpers/client.js';
|
||||
import { OrganizationApiTest, OrganizationRoleApiTest } from '#src/helpers/organization.js';
|
||||
|
@ -24,6 +25,7 @@ import {
|
|||
describe('consent api', () => {
|
||||
const applications = new Map<string, Application>();
|
||||
const thirdPartyApplicationName = 'consent-third-party-app';
|
||||
const firstPartyApplicationName = 'consent-first-party-app';
|
||||
const redirectUri = 'http://example.com';
|
||||
|
||||
const bootStrapApplication = async () => {
|
||||
|
@ -39,7 +41,20 @@ describe('consent api', () => {
|
|||
}
|
||||
);
|
||||
|
||||
const firstPartyApplication = await createApplication(
|
||||
firstPartyApplicationName,
|
||||
ApplicationType.Traditional,
|
||||
{
|
||||
isThirdParty: false,
|
||||
oidcClientMetadata: {
|
||||
redirectUris: [redirectUri],
|
||||
postLogoutRedirectUris: [],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
applications.set(thirdPartyApplicationName, thirdPartyApplication);
|
||||
applications.set(firstPartyApplicationName, firstPartyApplication);
|
||||
|
||||
await assignUserConsentScopes(thirdPartyApplication.id, {
|
||||
userScopes: [UserScope.Profile],
|
||||
|
@ -253,6 +268,44 @@ describe('consent api', () => {
|
|||
});
|
||||
|
||||
describe('submit consent info', () => {
|
||||
it('should not affect first party app', async () => {
|
||||
const application = applications.get(firstPartyApplicationName);
|
||||
assert(application, new Error('application.not_found'));
|
||||
|
||||
const { userProfile, user } = await generateNewUser({ username: true, password: true });
|
||||
const resource = await createResource(generateResourceName(), generateResourceIndicator());
|
||||
const scope = await createScope(resource.id, generateScopeName());
|
||||
const role = await createRole({ name: generateRoleName(), scopeIds: [scope.id] });
|
||||
await assignUsersToRole([user.id], role.id);
|
||||
|
||||
const client = await initClient(
|
||||
{
|
||||
appId: application.id,
|
||||
appSecret: application.secret,
|
||||
// First party app should block the scope, even though it is not assigned to the app
|
||||
scopes: [UserScope.Profile, scope.name],
|
||||
resources: [resource.indicator],
|
||||
},
|
||||
redirectUri
|
||||
);
|
||||
|
||||
await client.successSend(putInteraction, {
|
||||
event: InteractionEvent.SignIn,
|
||||
identifier: {
|
||||
username: userProfile.username,
|
||||
password: userProfile.password,
|
||||
},
|
||||
});
|
||||
|
||||
const { redirectTo } = await client.submitInteraction();
|
||||
|
||||
await client.processSession(redirectTo);
|
||||
|
||||
await deleteResource(resource.id);
|
||||
await deleteUser(user.id);
|
||||
await deleteRole(role.id);
|
||||
});
|
||||
|
||||
it('should perform manual consent successfully', async () => {
|
||||
const application = applications.get(thirdPartyApplicationName);
|
||||
assert(application, new Error('application.not_found'));
|
Loading…
Add table
Reference in a new issue