Skip to content

Commit

Permalink
fix(core): fix consent scopes filter rule for non-3rd-party app
Browse files Browse the repository at this point in the history
  • Loading branch information
wangsijie committed May 14, 2024
1 parent 062d217 commit 2845329
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 10 deletions.
25 changes: 15 additions & 10 deletions packages/core/src/routes/interaction/consent/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -118,19 +119,23 @@ export const filterAndParseMissingResourceScopes = async ({
organizationId,
});

const isThirdPartyApp = await isThirdPartyApplication(queries, applicationId);

Check warning on line 123 in packages/core/src/routes/interaction/consent/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/routes/interaction/consent/utils.ts#L122-L123

Added lines #L122 - L123 were not covered by tests
// 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;

Check warning on line 138 in packages/core/src/routes/interaction/consent/utils.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/routes/interaction/consent/utils.ts#L127-L138

Added lines #L127 - L138 were not covered by tests

return [
resourceIndicator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 () => {
Expand All @@ -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],
Expand Down Expand Up @@ -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'));
Expand Down

0 comments on commit 2845329

Please sign in to comment.