Skip to content

Commit ef00971

Browse files
pix-service-auto-mergeHEYGUL
authored andcommitted
[FEATURE] ✨ Ajoute une stratégie de contrôle plus strict pour l'accès au endpoint Parcoursup (PIX-15801)
#10881
2 parents 7c44432 + b996366 commit ef00971

File tree

5 files changed

+115
-15
lines changed

5 files changed

+115
-15
lines changed

api/lib/infrastructure/authentication.js

+7
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ const authentication = {
8888
validate: validateClientApplication,
8989
},
9090
},
91+
{
92+
name: 'jwt-parcoursup',
93+
configuration: {
94+
key: config.jwtConfig.parcoursup.secret,
95+
validate: validateClientApplication,
96+
},
97+
},
9198
],
9299

93100
defaultStrategy: 'jwt-user',

api/src/parcoursup/application/certification-route.js

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Joi from 'joi';
22

3-
import { securityPreHandlers } from '../../shared/application/security-pre-handlers.js';
43
import { studentIdentifierType } from '../../shared/domain/types/identifiers-type.js';
54
import { certificationController } from './certification-controller.js';
65

@@ -9,18 +8,13 @@ const register = async function (server) {
98
method: 'GET',
109
path: '/api/parcoursup/students/{ine}/certification',
1110
config: {
11+
auth: 'jwt-parcoursup',
1212
validate: {
1313
params: Joi.object({
1414
ine: studentIdentifierType,
1515
}),
1616
},
1717
handler: certificationController.getCertificationResult,
18-
pre: [
19-
{
20-
method: securityPreHandlers.checkAdminMemberHasRoleSuperAdmin,
21-
assign: 'hasAuthorizationToAccessAdminScope',
22-
},
23-
],
2418
tags: ['api', 'parcoursup'],
2519
notes: [
2620
'- **Cette route est accessible uniquement à Parcours Sup**\n' +

api/src/shared/config.js

+17
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ const configuration = (function () {
139139
scope: 'statistics',
140140
source: 'pixData',
141141
},
142+
{
143+
clientId: process.env.APIM_PIX_PARCOURSUP_CLIENT_ID,
144+
clientSecret: process.env.APIM_PIX_PARCOURSUP_CLIENT_SECRET,
145+
scope: 'parcoursup',
146+
source: 'parcoursup',
147+
},
142148
],
143149
auditLogger: {
144150
isEnabled: toBoolean(process.env.PIX_AUDIT_LOGGER_ENABLED),
@@ -291,6 +297,10 @@ const configuration = (function () {
291297
secret: process.env.PIX_DATA_AUTH_SECRET,
292298
tokenLifespan: process.env.TOKEN_LIFE_SPAN || '1h',
293299
},
300+
parcoursup: {
301+
secret: process.env.PIX_PARCOURSUP_AUTH_SECRET,
302+
tokenLifespan: process.env.TOKEN_LIFE_SPAN || '1h',
303+
},
294304
certificationResults: {
295305
scope: process.env.CERTIFICATION_RESULTS_JWT_SCOPE || 'certificationResultsLink',
296306
tokenLifespan: process.env.CERTIFICATION_RESULTS_JWT_TOKEN_LIFE_SPAN || '30d',
@@ -539,6 +549,12 @@ const configuration = (function () {
539549
scope: 'statistics',
540550
source: 'pixData',
541551
},
552+
{
553+
clientId: 'parcoursupClientId',
554+
clientSecret: 'parcoursupClientSecret',
555+
scope: 'parcoursup',
556+
source: 'parcoursup',
557+
},
542558
];
543559

544560
config.cpf.storage = {
@@ -573,6 +589,7 @@ const configuration = (function () {
573589
config.jwtConfig.livretScolaire = { secret: 'secretosmose', tokenLifespan: '1h' };
574590
config.jwtConfig.poleEmploi = { secret: 'secretPoleEmploi', tokenLifespan: '1h' };
575591
config.jwtConfig.pixData = { secret: 'secretPixData', tokenLifespan: '1h' };
592+
config.jwtConfig.parcoursup = { secret: 'secretPixParcoursup', tokenLifespan: '1h' };
576593

577594
config.logging.enabled = toBoolean(process.env.TEST_LOG_ENABLED);
578595
config.logging.enableLogKnexQueries = false;

api/tests/parcoursup/acceptance/application/certification-routes_test.js renamed to api/tests/parcoursup/acceptance/application/certification-route_test.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ import {
22
createServer,
33
databaseBuilder,
44
expect,
5-
generateValidRequestAuthorizationHeader,
6-
insertUserWithRoleSuperAdmin,
5+
generateValidRequestAuthorizationHeaderForApplication,
76
} from '../../../test-helper.js';
87

98
describe('Parcoursup | Acceptance | Application | certification-route', function () {
109
let server;
1110

11+
const PARCOURSUP_CLIENT_ID = 'parcoursupClientId';
12+
const PARCOURSUP_SCOPE = 'parcoursup';
13+
const PARCOURSUP_SOURCE = 'parcoursup';
14+
1215
beforeEach(async function () {
1316
server = await createServer();
1417
});
@@ -17,12 +20,15 @@ describe('Parcoursup | Acceptance | Application | certification-route', function
1720
it('should return 200 HTTP status code and a certification for a given INE', async function () {
1821
// given
1922
const ine = '123456789OK';
20-
const superAdmin = await insertUserWithRoleSuperAdmin();
2123
const options = {
2224
method: 'GET',
2325
url: `/api/parcoursup/students/${ine}/certification`,
2426
headers: {
25-
authorization: generateValidRequestAuthorizationHeader(superAdmin.id),
27+
authorization: generateValidRequestAuthorizationHeaderForApplication(
28+
PARCOURSUP_CLIENT_ID,
29+
PARCOURSUP_SOURCE,
30+
PARCOURSUP_SCOPE,
31+
),
2632
},
2733
};
2834

Original file line numberDiff line numberDiff line change
@@ -1,23 +1,99 @@
11
import { certificationController } from '../../../../src/parcoursup/application/certification-controller.js';
22
import * as moduleUnderTest from '../../../../src/parcoursup/application/certification-route.js';
3-
import { securityPreHandlers } from '../../../../src/shared/application/security-pre-handlers.js';
4-
import { expect, HttpTestServer, sinon } from '../../../test-helper.js';
3+
import {
4+
expect,
5+
generateValidRequestAuthorizationHeaderForApplication,
6+
HttpTestServer,
7+
sinon,
8+
} from '../../../test-helper.js';
59

610
describe('Parcoursup | Unit | Application | Routes | Certification', function () {
711
describe('GET /parcoursup/students/{ine}/certification', function () {
812
it('should return 200', async function () {
913
//given
10-
sinon.stub(securityPreHandlers, 'checkAdminMemberHasRoleSuperAdmin').returns(true);
1114
sinon.stub(certificationController, 'getCertificationResult').callsFake((request, h) => h.response().code(200));
1215

1316
const httpTestServer = new HttpTestServer();
17+
httpTestServer.setupAuthentication();
1418
await httpTestServer.register(moduleUnderTest);
1519

20+
const PARCOURSUP_CLIENT_ID = 'parcoursupClientId';
21+
const PARCOURSUP_SCOPE = 'parcoursup';
22+
const PARCOURSUP_SOURCE = 'parcoursup';
23+
24+
const method = 'GET';
25+
const url = '/api/parcoursup/students/123456789OK/certification';
26+
const headers = {
27+
authorization: generateValidRequestAuthorizationHeaderForApplication(
28+
PARCOURSUP_CLIENT_ID,
29+
PARCOURSUP_SOURCE,
30+
PARCOURSUP_SCOPE,
31+
),
32+
};
33+
1634
// when
17-
const response = await httpTestServer.request('GET', '/api/parcoursup/students/123456789OK/certification');
35+
const response = await httpTestServer.request(method, url, null, null, headers);
1836

1937
// then
2038
expect(response.statusCode).to.equal(200);
2139
});
40+
41+
context('with the wrong scope', function () {
42+
it('should return 403', async function () {
43+
//given
44+
const httpTestServer = new HttpTestServer();
45+
httpTestServer.setupAuthentication();
46+
await httpTestServer.register(moduleUnderTest);
47+
48+
const PARCOURSUP_CLIENT_ID = 'parcoursupClientId';
49+
const PARCOURSUP_SCOPE = 'a-wrong-scope';
50+
const PARCOURSUP_SOURCE = 'parcoursup';
51+
52+
const method = 'GET';
53+
const url = '/api/parcoursup/students/123456789OK/certification';
54+
const headers = {
55+
authorization: generateValidRequestAuthorizationHeaderForApplication(
56+
PARCOURSUP_CLIENT_ID,
57+
PARCOURSUP_SOURCE,
58+
PARCOURSUP_SCOPE,
59+
),
60+
};
61+
62+
// when
63+
const response = await httpTestServer.request(method, url, null, null, headers);
64+
65+
// then
66+
expect(response.statusCode).to.equal(403);
67+
});
68+
});
69+
70+
context('with the wrong clientId', function () {
71+
it('should return 401', async function () {
72+
//given
73+
const httpTestServer = new HttpTestServer();
74+
httpTestServer.setupAuthentication();
75+
await httpTestServer.register(moduleUnderTest);
76+
77+
const PARCOURSUP_CLIENT_ID = 'wrongClientId';
78+
const PARCOURSUP_SCOPE = 'parcoursup';
79+
const PARCOURSUP_SOURCE = 'parcoursup';
80+
81+
const method = 'GET';
82+
const url = '/api/parcoursup/students/123456789OK/certification';
83+
const headers = {
84+
authorization: generateValidRequestAuthorizationHeaderForApplication(
85+
PARCOURSUP_CLIENT_ID,
86+
PARCOURSUP_SOURCE,
87+
PARCOURSUP_SCOPE,
88+
),
89+
};
90+
91+
// when
92+
const response = await httpTestServer.request(method, url, null, null, headers);
93+
94+
// then
95+
expect(response.statusCode).to.equal(401);
96+
});
97+
});
2298
});
2399
});

0 commit comments

Comments
 (0)