diff --git a/docker-compose.yml b/docker-compose.yml index 11e32ebff4d0c482e9d91d16869909c433877e47..853ea1f21da9f562ec37c645e04f3237c2be7870 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,7 +13,8 @@ services: - OIDC_CLIENT_ID=${DEV_OIDC_CLIENT_ID} - OIDC_CLIENT_SECRET=${DEV_OIDC_CLIENT_SECRET} - GLC_CLIENT_ID=${DEV_GLC_CLIENT_ID} - - GLC_CLIENT_SECRET=${DEV_GLC_CLIENT_SECRET} + - GLC_CLIENT_SECRET=${DEV_GLC_CLIENT_SECRET} + restart: unless-stopped depends_on: - redis @@ -26,6 +27,7 @@ services: - ${REDIS_PORT}:6379 volumes: - redis-data:/data + restart: unless-stopped volumes: redis-data: diff --git a/src/authentication/authentication.controller.ts b/src/authentication/authentication.controller.ts index f3e8020e34a67bcc96038bf6e6649e407461695c..0d9610ba69a81d2a60e0d0d89c92eeac8b01e1fd 100644 --- a/src/authentication/authentication.controller.ts +++ b/src/authentication/authentication.controller.ts @@ -1,320 +1,54 @@ -import { Controller, Get, Res, Req, Param, Query, Logger } from '@nestjs/common'; -import { ConfigService } from '../configuration/config.service'; -import * as request from 'request'; -import * as jwt from 'jsonwebtoken'; -import { ApiResponse } from '@nestjs/swagger'; -import * as redis from 'redis'; -import * as uuid4 from 'uuid/v4'; +import { Controller, Get, Res, Param, Query } from '@nestjs/common'; +import { ApiResponse, ApiUseTags } from '@nestjs/swagger'; + +import { AuthenticationService } from './authentication.service'; + +@ApiUseTags('authentication') @Controller() export class AuthenticationController { - conf: any = {}; constructor( - private configService: ConfigService, - ) { - this.conf = this.configService.config; - this.discoverIdentityProvider('OIDC'); - this.discoverIdentityProvider('GLC'); - } + private _authService: AuthenticationService, + ) {} @Get('/login/:identityProvider') @ApiResponse({ status: 302, description: 'Redirection to the appropriate url allowing the user to connect to the identity provider.' }) @ApiResponse({ status: 500, description: 'Occurs when the service couldn\'t get the identity provider configuration from the discovery endpoint.' }) - login(@Req() req, @Res() res) { - const idp = req.params.identityProvider.toUpperCase(); - if (this.conf && this.conf.providers[idp]) { - const idpConf = this.conf.providers[idp]; - Logger.log('[-] Login'); - - const uuid = uuid4(); - - this.setRedisKeyValue(uuid, idp); - - let url = `${idpConf.discoveryResult.authorization_endpoint}?scope=${idpConf.scopes}`; - url += `&response_type=${idpConf.response_type}&client_id=${idpConf.client_id}`; - url += `&redirect_uri=${this.conf.redirect_uri}&state=${uuid}`; - - const encodedUrl = encodeURI(url); - - Logger.log(' [*] Encoded url:', encodedUrl); - - res.redirect(302, encodedUrl); - } else { - Logger.error(' [x] Error: Failed to get the configuration of the identity provider: ', idp); - res.status(400).send({ message: 'Failed to get the configuration of the identity provider.' }); - } + login(@Param('identityProvider') identityProvider: string, @Res() res) { + const idp = identityProvider.toUpperCase(); // By convention the provider is always uppecased in config and in var env + this._authService.login(idp, (err, encodedUrl) => { + if (err !== null) { + res.status(err.status).send({ message: err.message }); + } else { + res.redirect(302, encodedUrl); + } + }); } @Get('/token') @ApiResponse({ status: 200, description: 'JWT generated' }) - @ApiResponse({ status: 400, description: 'The request failed for the reason indicated in the body of repsonse.' }) - getOidcToken(@Res() res, @Query('code') code: string, @Query('state') state: string) { - Logger.log('[-] Token Endpoint'); - Logger.log(' [*] code: ', code); - Logger.log(' [*] state: ', state); - - this.getRedisValueByKey(state, (idp) => { - if (idp !== null) { - Logger.log(' [*] The state received in parameter is associated to the following identity provider: ', idp); - if (this.conf && this.conf.providers[idp]) { - const idpConf = this.conf.providers[idp]; - - const payload = { - grant_type: idpConf.grant_type, - code, - redirect_uri: this.conf.redirect_uri, - }; - - Logger.log(' [*] payload sent: ', JSON.stringify(payload)); - Logger.log('[-] Token Request'); - - request.post(idpConf.discoveryResult.token_endpoint, { form: payload }, (error: any, response: any, body: any) => { - - Logger.log(' [*] Response Status Code:', response.statusCode); - Logger.log(' [*] Response body:', body); - - if (error || !body || response.statusCode !== 200) { - Logger.error(' [x] error:', error); - res.status(400).send(error); - } else { - if (body) { - body = JSON.parse(body); - const userInfoOptions = { - idp, - idp_conf: idpConf, - access_token: body.access_token, - id_token: body.id_token, - }; - this.getUserInfo(userInfoOptions, (getUserInfoErr: string, userInfo: any) => { - if (getUserInfoErr) { - res.status(400).send(getUserInfoErr); - } else { - this.createOrUpdateKongUser(userInfo.email, (createOrUpdateErr: string, email: string) => { - if (createOrUpdateErr) { - res.status(400).send(createOrUpdateErr); - } else { - this.getUserJWTCredential(email, (getUserJWTCredErr: string, cred: any) => { - if (getUserJWTCredErr) { - res.status(400).send(getUserJWTCredErr); - } else { - userInfo.iss = cred.key; - userInfo.secret = cred.secret; - const jwtToken = this.generateJWT(userInfo); - res.status(200).json({ token: jwtToken }); - } - }); - } - }); - } - }); - } - } - }).auth(idpConf.client_id, idpConf.client_secret, true); - } else { - Logger.error(' [x] Error: Failed to get the configuration of the identity provider: ', idp); - res.status(400).send({ message: 'Failed to get the configuration of the identity provider.' }); - } + @ApiResponse({ status: 400, description: 'The request failed for the reason indicated in the body of response.' }) + @ApiResponse({ status: 500, description: 'The connection to redis server failed.' }) + getTokens(@Res() res, @Query('code') code: string, @Query('state') state: string) { + this._authService.getToken(code, state, (err, token) => { + if (err !== null) { + res.status(err.status).send({ message: err.message }); } else { - Logger.error(' [x] Error: The state received in paramter is not associated to any identity provider. State:', state); - res.status(400).send({ message: 'The state received in paramter is not associated to any identity provider.' }); + res.status(200).json(token); } }); } @Get('/logout') @ApiResponse({ status: 302, description: 'Redirection to the appropriate url allowing the user to logout from the app.' }) + @ApiResponse({ status: 500, description: 'Failed to get the configuration of the identity provider.' }) logout(@Res() res, @Query('id_token') id_token: string, @Query('identity_provider') identity_provider: string) { - Logger.log(`[x] logout from: ${identity_provider}`); - - if (this.conf && this.conf.providers[identity_provider]) { - const idpConf = this.conf.providers[identity_provider]; - - let url = `${idpConf.discoveryResult.end_session_endpoint}?post_logout_redirect_uri=${this.conf.post_logout_redirect_uri}`; - url += `&id_token_hint=${id_token}`; - const encodedUrl = encodeURI(url); - - Logger.log(encodedUrl); - - res.redirect(302, encodedUrl); - } else { - Logger.error(' [x] Error: Failed to get the configuration of the identity provider: ', identity_provider); - res.status(400).send({ message: 'Failed to get the configuration of the identity provider.' }); - } - } - - getUserInfo(opts: { idp: string, idp_conf: any, access_token: string, id_token: string }, done: any) { - const userInfoOpts = { - url: opts.idp_conf.discoveryResult.userinfo_endpoint, - headers: { - Authorization: `Bearer ${opts.access_token}`, - }, - }; - - Logger.log('[-] UserInfo Request'); - - request.get(userInfoOpts, (err: any, response: any, content: any) => { - - Logger.log(' [*] Response Status Code:', response.statusCode); - Logger.log(' [*] Response body:', content); - - if (err || !content || response.statusCode !== 200) { - Logger.error(' [x] Error:', err); - done('User info request failed.'); + this._authService.logout(id_token, identity_provider, (err, encodedUrl) => { + if (err !== null) { + res.status(err.status).send({ message: err.message }); } else { - content = JSON.parse(content); - - content.identity_provider = opts.idp; - content.id_token = opts.id_token; - - done(null, content); + res.redirect(302, encodedUrl); } }); } - - createOrUpdateKongUser(email: string, done: any) { - - Logger.log('[-] Generating Kong User with user name: ', email); - - request.put(`${this.conf.kongConsumers}/${email}`, { form: { username: email } }, (err: any, response: any, content: any) => { - Logger.log(' [*] Response Status Code:', response.statusCode); - Logger.log(' [*] Response body:', content); - - if (err || !content || response.statusCode !== 200) { - Logger.error(' [x] Error creating consumer in kong: ', err); - done('Failed to generate Kong User.'); - } else { - done(null, email); - } - }); - } - - getUserJWTCredential(email: string, done: any) { - - Logger.log('[-] Getting JWT credentials for user: ', email); - - request.get(`${this.conf.kongConsumers}/${email}/jwt`, (err: any, response: any, content: any) => { - - Logger.log(' [*] Response Status Code:', response.statusCode); - Logger.log(' [*] Response body:', content); - - let res = null; - if (err || !content || response.statusCode !== 200) { - Logger.error(' [x] Error getting consumer JWT creadentials: ', err); - done('Failed to get JWT credentials.'); - } else { - content = JSON.parse(content); - if (content.total > 0) { - res = content.data[0]; - } - - if (res === null) { - this.generateUserJWTCredential(email, (generateUserJWTCredentialErr: string, cred: any) => { - done(generateUserJWTCredentialErr, cred); - }); - } else { - done(null, res); - } - } - }); - } - - generateUserJWTCredential(email: string, done: any) { - - Logger.log('[-] Generating JWT credentials for user: ', email); - - request.post(`${this.conf.kongConsumers}/${email}/jwt`, (err: any, response: any, content: any) => { - - Logger.log(' [*] Response Status Code:', response.statusCode); - Logger.log(' [*] Response body:', content); - - if (err || !content || response.statusCode !== 200) { - Logger.error(' [x] Error creating consumer JWT creadentials: ', err); - done('Failed to generate JWT Credentials for the user'); - } else { - content = JSON.parse(content); - - done(null, content); - } - }); - } - - generateJWT(info: any) { - - Logger.log('[-] Generating JWT'); - - const jwtBearerToken: any = jwt.sign( - { - id: info.sub, - firstname: info.given_name, - lastname: info.family_name, - identity_provider: info.identity_provider, - email: info.email, - iss: info.iss, - id_token: info.id_token, - exp: Math.floor(Date.now() / 1000) + (60 * 60), - }, - // { key: RSA_PRIVATE_KEY, passphrase: "metropoledelyonportaildata2018" }, - info.secret, - { - algorithm: 'HS256', - // algorithm: 'RS256', - }, - ); - - return jwtBearerToken; - } - - discoverIdentityProvider(identityProvider: string) { - request.get(this.conf.providers[identityProvider].discoveryUrl, (err: any, response: any, content: any) => { - Logger.log('[-] Discovering configuration for identity Provider:', identityProvider); - Logger.log(' [*] Response Status Code:', response.statusCode); - Logger.log(' [*] Response body:', content); - - if (err || !content || response.statusCode !== 200) { - Logger.error(' [x] Error discovering the configuration for oidc provider: ', err); - } else { - content = JSON.parse(content); - this.conf.providers[identityProvider].discoveryResult = content; - } - }); - } - - connectToRedis(done) { - Logger.log(`[-] Connecting to redis`); - - const client = redis.createClient({ host: this.conf.redis.host, port: this.conf.redis.port }); - - client.on('error', (err) => { - Logger.error(' [x] Error on redis client: ' + err); - }); - - done(client); - } - - setRedisKeyValue(key: string, value: string) { - Logger.log(`[-] setRedisKeyValue with params: ${key} ${value}`); - this.connectToRedis((client) => { - - Logger.log(' [*] Redis client connected.'); - - client.set(key, value, 'EX', this.conf.redis.ttl, (err, res) => { - Logger.log(` [*] Setting key/pair result => ${err} ${res}`); - client.quit(); - }); - }); - } - - getRedisValueByKey(key: string, done) { - Logger.log(`[-] getRedisValueByKey with key: ${key}`); - this.connectToRedis((client) => { - - Logger.log(' [*] Redis client connected.'); - - client.get(key, (err, res) => { - Logger.log(` [*] Get by key => ${err} ${res}`); - client.quit(); - done(res); - }); - }); - } } diff --git a/src/authentication/authentication.module.ts b/src/authentication/authentication.module.ts index 62e91beee410b5e205c5f34500214aee63fd92c2..afa9d1214836de20896a5c52621335d8516c81d0 100644 --- a/src/authentication/authentication.module.ts +++ b/src/authentication/authentication.module.ts @@ -1,7 +1,9 @@ import { Module } from '@nestjs/common'; import { AuthenticationController } from './authentication.controller'; +import { AuthenticationService } from './authentication.service'; @Module({ controllers: [AuthenticationController], + providers: [AuthenticationService], }) export class AuthenticationModule {} diff --git a/src/authentication/authentication.service.spec.ts b/src/authentication/authentication.service.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..d6cefa6e670e25c21caae43841fcbeb02517c7eb --- /dev/null +++ b/src/authentication/authentication.service.spec.ts @@ -0,0 +1,15 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AuthenticationService } from './authentication.service'; + +describe('AuthenticationService', () => { + let service: AuthenticationService; + beforeAll(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [AuthenticationService], + }).compile(); + service = module.get<AuthenticationService>(AuthenticationService); + }); + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/authentication/authentication.service.ts b/src/authentication/authentication.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..aac465cec9a7ca5879e43f85714152e197f1d4cf --- /dev/null +++ b/src/authentication/authentication.service.ts @@ -0,0 +1,345 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { ConfigService } from 'configuration/config.service'; +import * as request from 'request'; +import * as uuid4 from 'uuid/v4'; +import * as redis from 'redis'; +import * as jwt from 'jsonwebtoken'; + +@Injectable() +export class AuthenticationService { + conf: any = {}; + constructor( + private configService: ConfigService, + ) { + this.conf = this.configService.config; + for (const provider in this.conf.providers) { + // Discover the conf for each providers + if (this.conf.providers.hasOwnProperty(provider)) { + this.discoverIdentityProvider(provider); + } + } + } + + private discoverIdentityProvider(identityProvider: string) { + // Call the discovery endpoint of the identity provider + request.get(this.conf.providers[identityProvider].discoveryUrl, (err: any, response: any, content: any) => { + Logger.log('[-] Discovering configuration for identity Provider:', identityProvider); + if (response) Logger.log(' [*] Response Status Code:', response.statusCode); + if (content) Logger.log(' [*] Response body:', content); + + if (err || !content || response.statusCode !== 200) { + Logger.error(` [x] Error discovering the configuration for provider: ${identityProvider}. Error was:`, JSON.stringify(err)); + } else { + content = JSON.parse(content); + // Set the discovered conf in the controller conf object + this.conf.providers[identityProvider].discoveryResult = content; + } + }); + } + + login(idp: string, done) { + if (this.conf && this.conf.providers[idp] && this.conf.providers[idp].discoveryResult) { + const idpConf = this.conf.providers[idp]; + Logger.log('[-] Login'); + + // Generate a random uuid that will be the state in the connexion echange (see OIDC spec ) + const state = uuid4(); + // Push a state/provider key pair in redis + this.setRedisKeyValue(state, idp); + + // Generate the url base on the provider conf + let url = `${idpConf.discoveryResult.authorization_endpoint}?scope=${idpConf.scopes}`; + url += `&response_type=${idpConf.response_type}&client_id=${idpConf.client_id}`; + url += `&redirect_uri=${this.conf.redirect_uri}&state=${state}`; + + const encodedUrl = encodeURI(url); + + Logger.log(' [*] Encoded url:', encodedUrl); + + done(null, encodedUrl); + } else { + Logger.error(' [x] Error: Failed to get the configuration of the identity provider: ', idp); + done({status: 500, message: 'Failed to get the configuration of the identity provider.'}); + } + } + + getToken(code: string, state: string, done) { + Logger.log('[-] GetTokens Method'); + Logger.log(' [*] code: ', code); + Logger.log(' [*] state: ', state); + + // Get the state/provider key pair from redis + this.getRedisValueByKey(state, (err, idp) => { + // It can be null if the state has been modified (not generated by the login endpoint) or if it has expired + if (err !== null) { + done({status: 500, message: 'One of the required services wasn\'t available, please retry later.'}); + } else { + if (idp !== null) { + Logger.log(' [*] The state received in parameter is associated to the following identity provider: ', idp); + if (this.conf && this.conf.providers[idp]) { + // Get the conf of the provider associated with the state + const idpConf = this.conf.providers[idp]; + + const payload = { + grant_type: idpConf.grant_type, + code, + redirect_uri: this.conf.redirect_uri, + }; + + Logger.log(' [*] payload sent: ', JSON.stringify(payload)); + Logger.log('[-] Token Request'); + + // Exchange the code against an id_token and an access_token + request.post(idpConf.discoveryResult.token_endpoint, { form: payload }, (error: any, response: any, body: any) => { + + Logger.log(' [*] Response Status Code:', response.statusCode); + Logger.log(' [*] Response body:', body); + + if (error || !body || response.statusCode !== 200) { + Logger.error(' [x] error:', error); + done({status: 400, message: 'Failed to echange the code against tokens.'}); + } else { + if (body) { + body = JSON.parse(body); + const userInfoOptions = { + idp, + idp_conf: idpConf, + access_token: body.access_token, + id_token: body.id_token, + }; + // Retrieve the user info with the tokens received + this.getUserInfo(userInfoOptions, (getUserInfoErr: string, userInfo: any) => { + if (getUserInfoErr) { + done({status: 400, message: getUserInfoErr}); + } else { + // Create or update the kong user based on the user info received + this.createOrUpdateKongUser(userInfo.email, (createOrUpdateErr: string, email: string) => { + if (createOrUpdateErr) { + done({status: 400, message: createOrUpdateErr}); + } else { + // Get user jwt credentials from kong in order to sign our own Json Web Token + this.getUserJWTCredential(email, (getUserJWTCredErr: string, cred: any) => { + if (getUserJWTCredErr) { + done({status: 400, message: getUserJWTCredErr}); + } else { + userInfo.iss = cred.key; + userInfo.secret = cred.secret; + const jwtToken = this.generateJWT(userInfo); + done(null, jwtToken); + } + }); + } + }); + } + }); + } + } + }).auth(idpConf.client_id, idpConf.client_secret, true); + } else { + Logger.error(' [x] Error: Failed to get the configuration of the identity provider: ', idp); + done({status: 400, message: 'Failed to get the configuration of the identity provider.'}); + } + } else { + Logger.error(' [x] Error: The state received in parameter is not associated to any identity provider. State:', state); + done({status: 400, message: 'The state received in parameter is not associated to any identity provider.'}); + } + } + }); + } + + logout(id_token: string, identity_provider, done) { + Logger.log(`[x] logout from: ${identity_provider}`); + + if (this.conf && this.conf.providers[identity_provider]) { + // Get the identy provider conf + const idpConf = this.conf.providers[identity_provider]; + + // Generate the url with the identity provider conf + let url = `${idpConf.discoveryResult.end_session_endpoint}?post_logout_redirect_uri=${this.conf.post_logout_redirect_uri}`; + url += `&id_token_hint=${id_token}`; + const encodedUrl = encodeURI(url); + + Logger.log(`Logout url: ${encodedUrl}`); + + done(null, encodedUrl); + } else { + Logger.error(' [x] Error: Failed to get the configuration of the identity provider: ', identity_provider); + done({status: 500, message: 'Failed to get the configuration of the identity provider.'}); + } + } + + private setRedisKeyValue(key: string, value: string) { + Logger.log(`[-] setRedisKeyValue with params: ${key} ${value}`); + this.connectToRedis((client) => { + if (client !== null) { + Logger.log(' [*] Redis client connected.'); + + // Set key value with expiration time in seconds + client.set(key, value, 'EX', this.conf.redis.ttl, (err, res) => { + Logger.log(` [*] Setting key/pair result => ${err} ${res}`); + client.quit(); + }); + } else { + Logger.error(' [x] Couldn\'t set redis key/value'); + } + }); + } + + private getRedisValueByKey(key: string, done) { + Logger.log(`[-] getRedisValueByKey with key: ${key}`); + this.connectToRedis((client) => { + if (client !== null) { + Logger.log(' [*] Redis client connected.'); + + client.get(key, (err, res) => { + Logger.log(` [*] Get by key => ${err} ${res}`); + client.quit(); + done(null, res); + }); + } else { + Logger.error(' [x] Couldn\'t get redis value with the key provided.'); + done('Failed to connect to redis server.'); + } + }); + } + + private connectToRedis(done) { + Logger.log(`[-] Connecting to redis`); + + const client = redis.createClient({ host: this.conf.redis.host, port: this.conf.redis.port }); + + client.on('error', (err) => { + Logger.error(' [x] Error on redis client: ' + err); + client.quit(); + done(null); + }); + + client.on('ready', (ready) => { + Logger.log(' [*] Client connected: ' + ready); + done(client); + }); + } + + private getUserInfo(opts: { idp: string, idp_conf: any, access_token: string, id_token: string }, done: any) { + const userInfoOpts = { + url: opts.idp_conf.discoveryResult.userinfo_endpoint, + headers: { + Authorization: `Bearer ${opts.access_token}`, + }, + }; + + Logger.log('[-] UserInfo Request'); + + request.get(userInfoOpts, (err: any, response: any, content: any) => { + + Logger.log(' [*] Response Status Code:', response.statusCode); + Logger.log(' [*] Response body:', content); + + if (err || !content || response.statusCode !== 200) { + Logger.error(' [x] Error:', err); + done('User info request failed.'); + } else { + content = JSON.parse(content); + + content.identity_provider = opts.idp; + content.id_token = opts.id_token; + + done(null, content); + } + }); + } + + private createOrUpdateKongUser(email: string, done: any) { + Logger.log('[-] Generating Kong User with user name: ', email); + + request.put(`${this.conf.kongConsumers}/${email}`, { form: { username: email } }, (err: any, response: any, content: any) => { + Logger.log(' [*] Response Status Code:', response.statusCode); + Logger.log(' [*] Response body:', content); + + if (err || !content || response.statusCode !== 200) { + Logger.error(' [x] Error creating consumer in kong: ', err); + done('Failed to generate Kong User.'); + } else { + done(null, email); + } + }); + } + + private getUserJWTCredential(email: string, done: any) { + + Logger.log('[-] Getting JWT credentials for user: ', email); + + request.get(`${this.conf.kongConsumers}/${email}/jwt`, (err: any, response: any, content: any) => { + + Logger.log(' [*] Response Status Code:', response.statusCode); + Logger.log(' [*] Response body:', content); + + let res = null; + if (err || !content || response.statusCode !== 200) { + Logger.error(' [x] Error getting consumer JWT creadentials: ', err); + done('Failed to get JWT credentials.'); + } else { + content = JSON.parse(content); + // If at least ine creadential exist, use the first one + if (content.total > 0) { + res = content.data[0]; + } + + // If no credentials exist for the user generate one + if (res === null) { + this.generateUserJWTCredential(email, (generateUserJWTCredentialErr: string, cred: any) => { + done(generateUserJWTCredentialErr, cred); + }); + } else { + done(null, res); + } + } + }); + } + + private generateUserJWTCredential(email: string, done: any) { + + Logger.log('[-] Generating JWT credentials for user: ', email); + + request.post(`${this.conf.kongConsumers}/${email}/jwt`, (err: any, response: any, content: any) => { + + Logger.log(' [*] Response Status Code:', response.statusCode); + Logger.log(' [*] Response body:', content); + + if (err || !content || response.statusCode !== 200) { + Logger.error(' [x] Error creating consumer JWT creadentials: ', err); + done('Failed to generate JWT Credentials for the user'); + } else { + content = JSON.parse(content); + + done(null, content); + } + }); + } + + private generateJWT(info: any) { + + Logger.log('[-] Generating JWT'); + + const jwtBearerToken: any = jwt.sign( + { + id: info.sub, + firstname: info.given_name, + lastname: info.family_name, + identity_provider: info.identity_provider, + email: info.email, + iss: info.iss, + id_token: info.id_token, + exp: Math.floor(Date.now() / 1000) + (60 * 60), + }, + // { key: RSA_PRIVATE_KEY, passphrase: "metropoledelyonportaildata2018" }, + info.secret, + { + algorithm: 'HS256', + // algorithm: 'RS256', + }, + ); + + return jwtBearerToken; + } +} diff --git a/src/main.ts b/src/main.ts index 2d76242d97680e95b669f31e4b91a1c2226df245..50fa433b91044bcae2a940f6ac0d651d570b094d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,6 +11,7 @@ async function bootstrap() { .setTitle('Authentication service API') .setDescription('This service expose the endpoints needed in order to Login/Logout with the OIDC/Grand Lyon Connect') .setVersion('0.1') + .addTag('authentication') .build(); const document = SwaggerModule.createDocument(app, options);