1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-11 19:44:35 +00:00

feat: make access token duration configurable when creating client/secret

This commit is contained in:
2022-11-10 19:43:06 +05:00
parent 4c874c2c39
commit 2413c05fea
6 changed files with 44 additions and 13 deletions

View File

@@ -57,6 +57,11 @@ components:
type: string type: string
description: 'Client Secret' description: 'Client Secret'
example: someRandomCryptoString example: someRandomCryptoString
accessTokenExpiryDays:
type: number
format: double
description: 'Number of days in which access token will expire'
example: 1
required: required:
- clientId - clientId
- clientSecret - clientSecret
@@ -679,8 +684,8 @@ paths:
$ref: '#/components/schemas/ClientPayload' $ref: '#/components/schemas/ClientPayload'
examples: examples:
'Example 1': 'Example 1':
value: {clientId: someFormattedClientID1234, clientSecret: someRandomCryptoString} value: {clientId: someFormattedClientID1234, clientSecret: someRandomCryptoString, accessTokenExpiryDays: 1}
summary: 'Create client with the following attributes: ClientId, ClientSecret. Admin only task.' summary: 'Create client with the following attributes: ClientId, ClientSecret, accessTokenExpires (optional) . Admin only task.'
tags: tags:
- Client - Client
security: security:

View File

@@ -8,6 +8,7 @@ import {
removeTokensInDB, removeTokensInDB,
saveTokensInDB saveTokensInDB
} from '../utils' } from '../utils'
import Client from '../model/Client'
@Route('SASjsApi/auth') @Route('SASjsApi/auth')
@Tags('Auth') @Tags('Auth')
@@ -83,7 +84,13 @@ const token = async (data: any): Promise<TokenResponse> => {
} }
} }
const accessToken = generateAccessToken(userInfo) const client = await Client.findOne({ clientId })
if (!client) throw new Error('Invalid clientId.')
const accessToken = generateAccessToken(
userInfo,
client.accessTokenExpiryDays
)
const refreshToken = generateRefreshToken(userInfo) const refreshToken = generateRefreshToken(userInfo)
await saveTokensInDB(userInfo.userId, clientId, accessToken, refreshToken) await saveTokensInDB(userInfo.userId, clientId, accessToken, refreshToken)
@@ -92,7 +99,13 @@ const token = async (data: any): Promise<TokenResponse> => {
} }
const refresh = async (userInfo: InfoJWT): Promise<TokenResponse> => { const refresh = async (userInfo: InfoJWT): Promise<TokenResponse> => {
const accessToken = generateAccessToken(userInfo) const client = await Client.findOne({ clientId: userInfo.clientId })
if (!client) throw new Error('Invalid clientId.')
const accessToken = generateAccessToken(
userInfo,
client.accessTokenExpiryDays
)
const refreshToken = generateRefreshToken(userInfo) const refreshToken = generateRefreshToken(userInfo)
await saveTokensInDB( await saveTokensInDB(

View File

@@ -7,12 +7,13 @@ import Client, { ClientPayload } from '../model/Client'
@Tags('Client') @Tags('Client')
export class ClientController { export class ClientController {
/** /**
* @summary Create client with the following attributes: ClientId, ClientSecret. Admin only task. * @summary Create client with the following attributes: ClientId, ClientSecret, accessTokenExpires (optional) . Admin only task.
* *
*/ */
@Example<ClientPayload>({ @Example<ClientPayload>({
clientId: 'someFormattedClientID1234', clientId: 'someFormattedClientID1234',
clientSecret: 'someRandomCryptoString' clientSecret: 'someRandomCryptoString',
accessTokenExpiryDays: 1
}) })
@Post('/') @Post('/')
public async createClient( public async createClient(
@@ -22,8 +23,8 @@ export class ClientController {
} }
} }
const createClient = async (data: any): Promise<ClientPayload> => { const createClient = async (data: ClientPayload): Promise<ClientPayload> => {
const { clientId, clientSecret } = data const { clientId, clientSecret, accessTokenExpiryDays } = data
// Checking if client is already in the database // Checking if client is already in the database
const clientExist = await Client.findOne({ clientId }) const clientExist = await Client.findOne({ clientId })
@@ -32,13 +33,15 @@ const createClient = async (data: any): Promise<ClientPayload> => {
// Create a new client // Create a new client
const client = new Client({ const client = new Client({
clientId, clientId,
clientSecret clientSecret,
accessTokenExpiryDays
}) })
const savedClient = await client.save() const savedClient = await client.save()
return { return {
clientId: savedClient.clientId, clientId: savedClient.clientId,
clientSecret: savedClient.clientSecret clientSecret: savedClient.clientSecret,
accessTokenExpiryDays: savedClient.accessTokenExpiryDays
} }
} }

View File

@@ -11,6 +11,11 @@ export interface ClientPayload {
* @example "someRandomCryptoString" * @example "someRandomCryptoString"
*/ */
clientSecret: string clientSecret: string
/**
* Number of days in which access token will expire
* @example 1
*/
accessTokenExpiryDays?: number
} }
const ClientSchema = new Schema<ClientPayload>({ const ClientSchema = new Schema<ClientPayload>({
@@ -21,6 +26,10 @@ const ClientSchema = new Schema<ClientPayload>({
clientSecret: { clientSecret: {
type: String, type: String,
required: true required: true
},
accessTokenExpiryDays: {
type: Number,
default: 1
} }
}) })

View File

@@ -1,7 +1,7 @@
import jwt from 'jsonwebtoken' import jwt from 'jsonwebtoken'
import { InfoJWT } from '../types' import { InfoJWT } from '../types'
export const generateAccessToken = (data: InfoJWT) => export const generateAccessToken = (data: InfoJWT, expiry?: number) =>
jwt.sign(data, process.secrets.ACCESS_TOKEN_SECRET, { jwt.sign(data, process.secrets.ACCESS_TOKEN_SECRET, {
expiresIn: '1day' expiresIn: expiry ? `${expiry}d` : '1d'
}) })

View File

@@ -88,7 +88,8 @@ export const updateUserValidation = (
export const registerClientValidation = (data: any): Joi.ValidationResult => export const registerClientValidation = (data: any): Joi.ValidationResult =>
Joi.object({ Joi.object({
clientId: Joi.string().required(), clientId: Joi.string().required(),
clientSecret: Joi.string().required() clientSecret: Joi.string().required(),
accessTokenExpiryDays: Joi.number()
}).validate(data) }).validate(data)
export const registerPermissionValidation = (data: any): Joi.ValidationResult => export const registerPermissionValidation = (data: any): Joi.ValidationResult =>