Skip to content

Commit

Permalink
Generalize wildcard matching in scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
satazor committed Aug 3, 2024
1 parent 5952fd9 commit 997dc59
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 16 deletions.
22 changes: 8 additions & 14 deletions src/utils/security.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { createScopesMismatchError } from '../errors/index.js';
import _ from 'lodash-es';

const getValueForHttpSchemeType = (request, securityScheme) => {
if (securityScheme.scheme === 'bearer') {
Expand Down Expand Up @@ -61,23 +60,18 @@ export const extractSecuritySchemeValueFromRequest = (request, securityScheme) =
};

export const verifyScopes = (providedScopes, requiredScopes) => {
const missingScopes = [];
const missingScopes = requiredScopes.filter(requiredScope => {
const hasMatchingScope = providedScopes.some(providedScope => {
if (providedScope.endsWith('*')) {
const prefixScope = providedScope.match(/(.*)\*$/)[1];

requiredScopes.forEach(requiredScope => {
if (providedScopes.includes(requiredScope)) {
return;
}
return requiredScope.startsWith(prefixScope);
}

const parts = requiredScope.split(':');
const wildcardScopes = parts.map((part, index) => {
return _.trimStart(parts.slice(0, index).join(':') + ':*', ':');
return providedScope === requiredScope;
});

const matches = wildcardScopes.some(matchingScope => providedScopes.includes(matchingScope));

if (!matches) {
missingScopes.push(requiredScope);
}
return !hasMatchingScope;
});

if (missingScopes.length > 0) {
Expand Down
26 changes: 24 additions & 2 deletions src/utils/security.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('verifyScopes()', () => {
};

it('should verify regular scopes correctly against required scopes', async () => {
let provided = ['read', 'write'];
const provided = ['read', 'write'];

runTest({ missing: [], provided, required: [] });
runTest({ missing: [], provided, required: ['read', 'write'] });
Expand All @@ -49,7 +49,7 @@ describe('verifyScopes()', () => {
});

it('should verify regular scopes correctly against * suffix', async () => {
const provided = ['user:*', 'transaction:foo:*'];
let provided = ['user:*', 'transaction:foo:*'];

runTest({ missing: [], provided, required: ['user:foo'] });
runTest({ missing: [], provided, required: ['user:foo:bar'] });
Expand All @@ -60,6 +60,28 @@ describe('verifyScopes()', () => {
runTest({ missing: ['transaction:foo'], provided, required: ['transaction:foo'] });
runTest({ missing: ['transaction::'], provided, required: ['transaction::'] });
runTest({ missing: [''], provided, required: [''] });

provided = ['user.*', 'transaction.foo.*'];

runTest({ missing: [], provided, required: ['user.foo'] });
runTest({ missing: [], provided, required: ['user.foo.bar'] });
runTest({ missing: [], provided, required: ['user.'] });
runTest({ missing: [], provided, required: ['transaction.foo.bar'] });
runTest({ missing: [], provided, required: ['transaction.foo.'] });
runTest({ missing: ['user'], provided, required: ['user'] });
runTest({ missing: ['transaction.foo'], provided, required: ['transaction.foo'] });
runTest({ missing: ['transaction..'], provided, required: ['transaction..'] });
runTest({ missing: [''], provided, required: [''] });

provided = ['user*', 'transaction:foo*'];

runTest({ missing: [], provided, required: ['userfoo'] });
runTest({ missing: [], provided, required: ['user'] });
runTest({ missing: [], provided, required: ['transaction:foo'] });
runTest({ missing: [], provided, required: ['transaction:foobar'] });
runTest({ missing: ['use'], provided, required: ['use'] });
runTest({ missing: ['transaction:foz'], provided, required: ['transaction:foz'] });
runTest({ missing: [''], provided, required: [''] });
});
});

Expand Down

0 comments on commit 997dc59

Please sign in to comment.