|
1 | 1 | ```js [callback:NodeJS]
|
2 | 2 |
|
3 |
| -params // data from your request handling |
4 |
| -storage // your own memory system |
5 |
| - |
6 |
| -// Retrieve GET query params from your own framework / http handler |
7 |
| -const { code, state } = params; |
8 |
| - |
9 |
| -// Retrieve your app's Client ID with your own logic |
10 |
| -const pimUrl = storage.get("PIM_URL"); |
11 |
| -const appState = storage.get("APP_STATE"); |
12 |
| -const clientId = storage.get("CLIENT_ID"); |
13 |
| -const clientSecret = storage.get("CLIENT_SECRET"); |
14 |
| - |
15 |
| -// Control the security state integrity previously defined, to avoid attacks |
16 |
| -if (state !== appState) { |
17 |
| - return response(403, |
18 |
| - { |
19 |
| - "error": "Forbidden", |
20 |
| - "error_description": "State integrity failed", |
21 |
| - } |
22 |
| - ) |
23 |
| -} |
| 3 | +import express from 'express'; |
| 4 | +import crypto from 'crypto'; |
| 5 | +import fetch from 'node-fetch'; // https://www.npmjs.com/package/node-fetch |
| 6 | + |
| 7 | +const app = express(); |
| 8 | + |
| 9 | +app.get('/callback', async (req, res, next) => { |
| 10 | + try { |
| 11 | + const appClientSecret = "CLIENT_SECRET"; |
| 12 | + const appClientId = "CLIENT_ID"; |
| 13 | + |
| 14 | + const session = req.session; |
| 15 | + |
| 16 | + const pimUrl = session.pim_url; |
| 17 | + const state = req.query.state; |
| 18 | + const authorizationCode = req.query.code; |
| 19 | + |
| 20 | + if (!pimUrl) { |
| 21 | + throw new Error( |
| 22 | + "Can't retrieve PIM url, please restart the authorization process." |
| 23 | + ); |
| 24 | + } |
| 25 | + |
| 26 | + // We check if the received state is the same as in the session, for security. |
| 27 | + if (!state || state != session.state) { |
| 28 | + throw new Error("Invalid state"); |
| 29 | + } |
24 | 30 |
|
25 |
| -// Generate a new challenge code |
26 |
| -// a sha256 concatenation of a code_identifier and the client_secret |
27 |
| -const codeIdentifier = require('crypto').randomBytes(32).toString('hex') |
28 |
| -const codeChallenge = require('crypto') |
29 |
| - .createHash('sha256') |
30 |
| - .update(`${codeIdentifier}${clientSecret}`) |
31 |
| - .digest('hex') |
32 |
| - |
33 |
| -// Send the payload to the PIM instance, ask for an API Token |
34 |
| -fetch |
35 |
| - .post(`${storage.get('PIM_URL')}/connect/apps/v1/oauth2/token`, { |
36 |
| - code, |
37 |
| - grant_type: 'authorization_code', |
38 |
| - client_id: clientId, |
39 |
| - code_identifier: codeIdentifier, |
40 |
| - code_challenge: codeChallenge, |
41 |
| - }) |
42 |
| - .then(({ data }) => { |
43 |
| - // Retrieve the fresh token and store it with your own system |
44 |
| - const { access_token: accessToken } = data |
45 |
| - storage.set('API_TOKEN', accessToken) |
46 |
| - redirect('/') |
47 |
| - }) |
48 |
| - .catch((data) => { |
49 |
| - // handle error |
50 |
| - res.status(400).send(data) |
51 |
| - }) |
| 31 | + if (!authorizationCode) { |
| 32 | + throw new Error("Missing authorization code"); |
| 33 | + } |
| 34 | + |
| 35 | + // Generate code for token request |
| 36 | + const codeidentifier = crypto.randomBytes(64).toString("hex"); |
| 37 | + const codeChallenge = crypto |
| 38 | + .createHash("sha256") |
| 39 | + .update(codeidentifier + appClientSecret) |
| 40 | + .digest("hex"); |
| 41 | + |
| 42 | + // Build form data to post |
| 43 | + const accessTokenRequestPayload = new URLSearchParams({ |
| 44 | + grant_type: "authorization_code", |
| 45 | + code: authorizationCode, |
| 46 | + client_id: appClientId, |
| 47 | + code_identifier: codeidentifier, |
| 48 | + code_challenge: codeChallenge, |
| 49 | + }); |
| 50 | + |
| 51 | + // Make an authenticated call to the API |
| 52 | + const accessTokenUrl = pimUrl + "/connect/apps/v1/oauth2/token"; |
| 53 | + const response = await fetch(accessTokenUrl, { |
| 54 | + method: "post", |
| 55 | + body: accessTokenRequestPayload, |
| 56 | + headers: {"Content-Type": "application/x-www-form-urlencoded"}, |
| 57 | + }); |
| 58 | + |
| 59 | + const result = await response.json(); |
| 60 | + |
| 61 | + const accessToken = result.access_token; |
| 62 | + |
| 63 | + console.log(accessToken); |
| 64 | + } catch (err) { |
| 65 | + next(err); |
| 66 | + } |
| 67 | +} |
52 | 68 |
|
53 | 69 | ```
|
0 commit comments