Skip to content

Commit a0fd0c6

Browse files
[CF-447] Use paginated requests (#61)
* fix: filter client grants by client & audience * feat: use paginated requests for resource servers * version 2.4.1
1 parent 98631db commit a0fd0c6

File tree

8 files changed

+219
-13
lines changed

8 files changed

+219
-13
lines changed

package-lock.json

Lines changed: 142 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "auth0-sso-dashboard",
3-
"version": "2.4.0",
3+
"version": "2.4.1",
44
"description": "This extension provides your users with a dashboard for all of their applications.",
55
"engines": {
66
"node": ">=4.x"
@@ -156,6 +156,7 @@
156156
"redux-simple-router": "^2.0.4",
157157
"redux-static": "^1.0.0",
158158
"rimraf": "^2.5.2",
159+
"sinon": "^9.0.2",
159160
"style-loader": "^0.13.1",
160161
"uglifyjs-webpack-plugin": "^1.2.4",
161162
"url-loader": "^1.0.1",

server/lib/multipartRequest.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { snakeCase } from 'lodash';
12
import Promise from 'bluebird';
23
import { ArgumentError } from 'auth0-extension-tools';
34

@@ -21,7 +22,7 @@ export default function (client, entity, opts = {}, perPage = 100, concurrency =
2122
.then((response) => {
2223
total = response.total || 0;
2324
pageCount = Math.ceil(total / perPage);
24-
const data = response[entity] || response || [];
25+
const data = response[entity] || response[snakeCase(entity)] || response || [];
2526
data.forEach(item => result.push(item));
2627
return null;
2728
});

server/lib/queries.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { managementApi, ValidationError } from 'auth0-extension-tools';
66

77
import config from './config';
88
import logger from './logger';
9+
import multipartRequest from './multipartRequest';
910

1011

1112
const getAuthorizationApiUrl = () => {
@@ -136,12 +137,16 @@ const getToken = (req) => {
136137
const makeRequest = (req, path, method, payload) =>
137138
new Promise((resolve, reject) => getToken(req).then((token) => {
138139
request(method, `https://${config('AUTH0_DOMAIN')}/api/v2/${path}`)
139-
.send(payload || {})
140+
.query(method === 'GET' ? payload : {})
141+
.send(method === 'GET' ? null : payload || {})
140142
.set('Content-Type', 'application/json')
141143
.set('Authorization', `Bearer ${token}`)
142144
.end((err, res) => {
143145
if (err) {
144-
logger.error(res.body);
146+
if (res && res.body) {
147+
logger.error(res.body);
148+
}
149+
145150
return reject(err);
146151
}
147152

@@ -151,7 +156,7 @@ const makeRequest = (req, path, method, payload) =>
151156
);
152157

153158
export const getResourceServer = (req, audience) =>
154-
makeRequest(req, 'resource-servers', 'GET')
159+
multipartRequest(req.auth0, 'resourceServers')
155160
.then((apis) => {
156161
const api = apis.filter(item => item.identifier === audience);
157162
return api.length && api[0];
@@ -183,7 +188,7 @@ export const deleteResourceServer = req =>
183188
});
184189

185190
const getGrantId = req =>
186-
makeRequest(req, 'client-grants', 'GET')
191+
makeRequest(req, 'client-grants', 'GET', { client_id: config('AUTH0_CLIENT_ID'), audience: 'urn:auth0-authz-api' })
187192
.then(grants => grants.filter(item => (item.client_id === config('AUTH0_CLIENT_ID') && item.audience === 'urn:auth0-authz-api')))
188193
.then(grants => grants[0] && grants[0].id);
189194

server/routes/api.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export default (storage) => {
4343
});
4444
api.use('/applications', applications(auth0, storage));
4545
api.use('/groups', groups(storage));
46-
api.use('/authorization', authorization(storage));
46+
api.use('/authorization', authorization(auth0, storage));
4747
api.use('/connections', connections(auth0));
4848
api.get('/status', (req, res) => {
4949
res.json({ isAdmin: (req.user.scope && req.user.scope.indexOf('manage:applications') > -1) });

server/routes/authorization.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import config from '../lib/config';
44
import * as authorization from '../lib/authorization';
55
import { requireScope } from '../lib/middlewares';
66

7-
export default (storage) => {
7+
export default (auth0, storage) => {
88
const api = Router();
99

10-
api.get('/', requireScope('manage:authorization'), (req, res, next) => {
10+
api.get('/', auth0, requireScope('manage:authorization'), (req, res, next) => {
1111
if (!config('ALLOW_AUTHZ')) {
1212
return res.json({ authorizationApiAvailable: false });
1313
}
@@ -17,7 +17,7 @@ export default (storage) => {
1717
.catch(next);
1818
});
1919

20-
api.post('/', requireScope('manage:authorization'), (req, res, next) => {
20+
api.post('/', auth0, requireScope('manage:authorization'), (req, res, next) => {
2121
if (!config('ALLOW_AUTHZ')) {
2222
return next();
2323
}
@@ -27,7 +27,7 @@ export default (storage) => {
2727
.catch(next);
2828
});
2929

30-
api.delete('/', requireScope('manage:authorization'), (req, res, next) => {
30+
api.delete('/', auth0, requireScope('manage:authorization'), (req, res, next) => {
3131
if (!config('ALLOW_AUTHZ')) {
3232
return next();
3333
}

tests/server/lib/queries.tests.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* eslint-disable import/no-extraneous-dependencies */
2+
import { expect } from 'chai';
3+
import sinon from 'sinon';
4+
import nock from 'nock';
5+
import { setProvider } from '../../../server/lib/config';
6+
import { getResourceServer, removeGrant } from '../../../server/lib/queries';
7+
8+
describe('queries', () => {
9+
before(() => {
10+
setProvider(() => 'auth0.example.com');
11+
});
12+
13+
describe('getResourceServer', () => {
14+
it('should fetch the resource servers with pagination', () => {
15+
const req = {
16+
auth0: {
17+
resourceServers: {
18+
getAll: sinon.spy(() => {
19+
return Promise.resolve({ total: 1, resource_servers: [{ identifier: 'http://audience' }] });
20+
})
21+
}
22+
}
23+
};
24+
return getResourceServer(req, 'http://audience').then((resourceServer) => {
25+
expect(resourceServer).to.eql({ identifier: 'http://audience' });
26+
sinon.assert.calledOnce(req.auth0.resourceServers.getAll);
27+
sinon.assert.calledWith(req.auth0.resourceServers.getAll, { include_totals: true, page: 0, per_page: 100 });
28+
});
29+
});
30+
});
31+
32+
describe('removeGrant', () => {
33+
afterEach(() => {
34+
nock.restore();
35+
});
36+
37+
it('should delete the grant if it exists', () => {
38+
const get = nock('https://auth0.example.com')
39+
.get('/api/v2/client-grants')
40+
.query({ client_id: 'auth0.example.com',audience: 'urn:auth0-authz-api' })
41+
.reply(200, [ { client_id: 'auth0.example.com',audience: 'urn:auth0-authz-api', id: 'id1' }]);
42+
43+
const del = nock('https://auth0.example.com')
44+
.delete('/api/v2/client-grants/id1')
45+
.reply(204)
46+
47+
const req = {
48+
user: {
49+
access_token: 'token'
50+
}
51+
};
52+
return removeGrant(req).then(() => {
53+
get.done();
54+
del.done();
55+
});
56+
});
57+
});
58+
});

webtask.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"title": "SSO Dashboard",
33
"name": "auth0-sso-dashboard",
4-
"version": "2.4.0",
4+
"version": "2.4.1",
55
"preVersion": "2.2.1",
66
"author": "Auth0",
77
"useHashName": false,

0 commit comments

Comments
 (0)