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

fix: DB names updates + refresh api is added

This commit is contained in:
Saad Jutt
2021-11-03 15:56:58 +05:00
parent 46c5a75ac4
commit 9f17b17e31
18 changed files with 274 additions and 209 deletions

View File

@@ -1,22 +1,22 @@
import Client from '../model/Client'
export const createClient = async (data: any) => {
const { client_id: clientid, client_secret: clientsecret } = data
const { clientId, clientSecret } = data
// Checking if client is already in the database
const clientExist = await Client.findOne({ clientid })
const clientExist = await Client.findOne({ clientId })
if (clientExist) throw new Error('Client ID already exists.')
// Create a new client
const client = new Client({
clientid,
clientsecret
clientId,
clientSecret
})
const savedClient = await client.save()
return {
client_id: savedClient.clientid,
client_secret: savedClient.clientsecret
clientId: savedClient.clientId,
clientSecret: savedClient.clientSecret
}
}

View File

@@ -2,7 +2,7 @@ import bcrypt from 'bcryptjs'
import User from '../model/User'
export const createUser = async (data: any) => {
const { displayname, username, password, isadmin, isactive } = data
const { displayName, username, password, isAdmin, isActive } = data
// Checking if user is already in the database
const usernameExist = await User.findOne({ username })
@@ -14,19 +14,19 @@ export const createUser = async (data: any) => {
// Create a new user
const user = new User({
displayname,
displayName,
username,
password: hashPassword,
isadmin,
isactive
isAdmin,
isActive
})
const savedUser = await user.save()
return {
displayname: savedUser.displayname,
displayName: savedUser.displayName,
username: savedUser.username,
isadmin: savedUser.isadmin,
isactive: savedUser.isactive
isAdmin: savedUser.isAdmin,
isActive: savedUser.isActive
}
}

View File

@@ -1,11 +1,11 @@
import mongoose from 'mongoose'
const clientSchema = new mongoose.Schema({
clientid: {
clientId: {
type: String,
required: true
},
clientsecret: {
clientSecret: {
type: String,
required: true
}

View File

@@ -1,8 +1,7 @@
import { string } from 'joi'
import mongoose, { Schema } from 'mongoose'
import mongoose from 'mongoose'
const userSchema = new mongoose.Schema({
displayname: {
displayName: {
type: String,
required: true
},
@@ -14,25 +13,25 @@ const userSchema = new mongoose.Schema({
type: String,
required: true
},
isadmin: {
isAdmin: {
type: Boolean,
default: false
},
isactive: {
isActive: {
type: Boolean,
default: true
},
tokens: [
{
clientid: {
clientId: {
type: String,
required: true
},
accesstoken: {
accessToken: {
type: String,
required: true
},
refreshtoken: {
refreshToken: {
type: String,
required: true
}

View File

@@ -6,7 +6,8 @@ import jwt from 'jsonwebtoken'
import Client from '../../model/Client'
import User from '../../model/User'
import {
authenticateToken,
authenticateAccessToken,
authenticateRefreshToken,
authorizeValidation,
removeTokensInDB,
saveTokensInDB,
@@ -16,7 +17,6 @@ import { InfoJWT } from '../../types'
const authRouter = express.Router()
const clients: { [key: string]: string } = {}
const clientIDs = new Set()
const authCodes: { [key: string]: { [key: string]: string } } = {}
@@ -24,8 +24,7 @@ export const populateClients = async () => {
const result = await Client.find()
clientIDs.clear()
result.forEach((r) => {
clients[r.clientid] = r.clientsecret
clientIDs.add(r.clientid)
clientIDs.add(r.clientId)
})
}
@@ -43,24 +42,24 @@ export const connectDB = () => {
}
}
export const saveCode = (username: string, client_id: string, code: string) => {
if (authCodes[username]) return (authCodes[username][client_id] = code)
export const saveCode = (username: string, clientId: string, code: string) => {
if (authCodes[username]) return (authCodes[username][clientId] = code)
authCodes[username] = { [client_id]: code }
return authCodes[username][client_id]
authCodes[username] = { [clientId]: code }
return authCodes[username][clientId]
}
export const deleteCode = (username: string, client_id: string) =>
delete authCodes[username][client_id]
export const deleteCode = (username: string, clientId: string) =>
delete authCodes[username][clientId]
authRouter.post('/authorize', async (req, res) => {
const { error, value } = authorizeValidation(req.body)
if (error) return res.status(400).send(error.details[0].message)
const { username, password, client_id } = value
const { username, password, clientId } = value
// Verify client ID
if (!clientIDs.has(client_id)) {
return res.status(403).send('Invalid client_id.')
if (!clientIDs.has(clientId)) {
return res.status(403).send('Invalid clientId.')
}
// Authenticate User
@@ -70,13 +69,13 @@ authRouter.post('/authorize', async (req, res) => {
const validPass = await bcrypt.compare(password, user.password)
if (!validPass) return res.status(403).send('Invalid password.')
// generate authorization code against client_id
// generate authorization code against clientId
const userInfo: InfoJWT = {
client_id,
clientId,
username
}
const code = saveCode(username, client_id, generateAuthCode(userInfo))
const code = saveCode(username, clientId, generateAuthCode(userInfo))
res.json({ code })
})
@@ -85,15 +84,15 @@ authRouter.post('/token', async (req, res) => {
const { error, value } = tokenValidation(req.body)
if (error) return res.status(400).send(error.details[0].message)
const { client_id, code } = value
const { clientId, code } = value
const userInfo = await verifyAuthCode(client_id, code)
const userInfo = await verifyAuthCode(clientId, code)
if (!userInfo) return res.sendStatus(403)
if (authCodes[userInfo.username][client_id] !== code)
if (authCodes[userInfo.username][clientId] !== code)
return res.sendStatus(403)
deleteCode(userInfo.username, client_id)
deleteCode(userInfo.username, clientId)
const accessToken = generateAccessToken(userInfo)
const refreshToken = jwt.sign(
@@ -101,36 +100,44 @@ authRouter.post('/token', async (req, res) => {
process.env.REFRESH_TOKEN_SECRET as string
)
await saveTokensInDB(userInfo.username, client_id, accessToken, refreshToken)
await saveTokensInDB(userInfo.username, clientId, accessToken, refreshToken)
res.json({ accessToken: accessToken, refreshToken: refreshToken })
})
// authRouter.post('/refresh', (req, res) => {
// const refreshToken = req.body.token
// if (refreshToken == null) return res.sendStatus(401)
// if (!refreshTokens.includes(refreshToken)) return res.sendStatus(403)
// jwt.verify(
// refreshToken,
// process.env.REFRESH_TOKEN_SECRET as string,
// (err: any, user: any) => {
// if (err) return res.sendStatus(403)
// const accessToken = generateAccessToken({ name: user.name })
// res.json({ accessToken: accessToken })
// }
// )
// })
authRouter.post('/refresh', authenticateRefreshToken, async (req: any, res) => {
const { username, clientId } = req.user
const userInfo = {
username,
clientId
}
authRouter.delete('/logout', authenticateToken, async (req: any, res) => {
const accessToken = generateAccessToken(userInfo)
const refreshToken = jwt.sign(
userInfo,
process.env.REFRESH_TOKEN_SECRET as string
)
await saveTokensInDB(userInfo.username, clientId, accessToken, refreshToken)
res.json({ accessToken: accessToken, refreshToken: refreshToken })
})
authRouter.delete('/logout', authenticateAccessToken, async (req: any, res) => {
const { user } = req
await removeTokensInDB(user.username, user.client_id)
await removeTokensInDB(user.username, user.clientId)
res.sendStatus(204)
})
export const generateAccessToken = (data: InfoJWT) =>
jwt.sign(data, process.env.ACCESS_TOKEN_SECRET as string, {
expiresIn: '1h'
})
export const generateRefreshToken = (data: InfoJWT) =>
jwt.sign(data, process.env.REFRESH_TOKEN_SECRET as string, {
expiresIn: '1day'
})
@@ -140,7 +147,7 @@ export const generateAuthCode = (data: InfoJWT) =>
})
const verifyAuthCode = async (
client_id: string,
clientId: string,
code: string
): Promise<InfoJWT | undefined> => {
return new Promise((resolve, reject) => {
@@ -148,10 +155,10 @@ const verifyAuthCode = async (
if (err) return resolve(undefined)
const clientInfo: InfoJWT = {
client_id: data?.client_id,
clientId: data?.clientId,
username: data?.username
}
if (clientInfo.client_id === client_id) {
if (clientInfo.clientId === clientId) {
return resolve(clientInfo)
}
return resolve(undefined)

View File

@@ -11,8 +11,8 @@ clientRouter.post('/', async (req, res) => {
try {
const savedClient = await createClient(data)
res.send({
client_id: savedClient.client_id,
client_secret: savedClient.client_secret
clientId: savedClient.clientId,
clientSecret: savedClient.clientSecret
})
} catch (err: any) {
res.status(403).send(err.toString())

View File

@@ -6,22 +6,22 @@ import stpRouter from './stp'
import userRouter from './user'
import clientRouter from './client'
import authRouter, { connectDB } from './auth'
import { authenticateToken } from '../../utils'
import { authenticateAccessToken } from '../../utils'
dotenv.config()
connectDB()
const router = express.Router()
router.use('/drive', authenticateToken, driveRouter)
router.use('/stp', authenticateToken, stpRouter)
router.use('/user', authenticateToken, verifyAdmin, userRouter)
router.use('/client', authenticateToken, verifyAdmin, clientRouter)
router.use('/drive', authenticateAccessToken, driveRouter)
router.use('/stp', authenticateAccessToken, stpRouter)
router.use('/user', authenticateAccessToken, verifyAdmin, userRouter)
router.use('/client', authenticateAccessToken, verifyAdmin, clientRouter)
router.use('/auth', authRouter)
function verifyAdmin(req: any, res: any, next: any) {
const { user } = req
if (!user?.isadmin) return res.status(403).send('Admin account required')
if (!user?.isAdmin) return res.status(403).send('Admin account required')
next()
}

View File

@@ -7,20 +7,21 @@ import { createClient } from '../../../controllers/createClient'
import {
generateAccessToken,
generateAuthCode,
generateRefreshToken,
populateClients,
saveCode
} from '../auth'
import { InfoJWT } from '../../../types'
import { saveTokensInDB, verifyTokenInDB } from '../../../utils'
const client_id = 'someclientID'
const client_secret = 'someclientSecret'
const clientId = 'someclientID'
const clientSecret = 'someclientSecret'
const user = {
displayname: 'Test User',
displayName: 'Test User',
username: 'testUsername',
password: '87654321',
isadmin: false,
isactive: true
isAdmin: false,
isActive: true
}
describe('auth', () => {
@@ -30,7 +31,7 @@ describe('auth', () => {
beforeAll(async () => {
mongoServer = await MongoMemoryServer.create()
con = await mongoose.connect(mongoServer.getUri())
await createClient({ client_id, client_secret })
await createClient({ clientId, clientSecret })
await populateClients()
})
@@ -55,7 +56,7 @@ describe('auth', () => {
.send({
username: user.username,
password: user.password,
client_id
clientId
})
.expect(200)
@@ -67,7 +68,7 @@ describe('auth', () => {
.post('/SASjsApi/auth/authorize')
.send({
password: user.password,
client_id
clientId
})
.expect(400)
@@ -80,7 +81,7 @@ describe('auth', () => {
.post('/SASjsApi/auth/authorize')
.send({
username: user.username,
client_id
clientId
})
.expect(400)
@@ -88,7 +89,7 @@ describe('auth', () => {
expect(res.body).toEqual({})
})
it('should respond with Bad Request if client_id is missing', async () => {
it('should respond with Bad Request if clientId is missing', async () => {
const res = await request(app)
.post('/SASjsApi/auth/authorize')
.send({
@@ -97,7 +98,7 @@ describe('auth', () => {
})
.expect(400)
expect(res.text).toEqual(`"client_id" is required`)
expect(res.text).toEqual(`"clientId" is required`)
expect(res.body).toEqual({})
})
@@ -107,7 +108,7 @@ describe('auth', () => {
.send({
username: user.username,
password: user.password,
client_id
clientId
})
.expect(403)
@@ -123,7 +124,7 @@ describe('auth', () => {
.send({
username: user.username,
password: 'WrongPassword',
client_id
clientId
})
.expect(403)
@@ -131,7 +132,7 @@ describe('auth', () => {
expect(res.body).toEqual({})
})
it('should respond with Forbidden if client_id is incorrect', async () => {
it('should respond with Forbidden if clientId is incorrect', async () => {
await createUser(user)
const res = await request(app)
@@ -139,18 +140,18 @@ describe('auth', () => {
.send({
username: user.username,
password: user.password,
client_id: 'WrongClientID'
clientId: 'WrongClientID'
})
.expect(403)
expect(res.text).toEqual('Invalid client_id.')
expect(res.text).toEqual('Invalid clientId.')
expect(res.body).toEqual({})
})
})
describe('token', () => {
const userInfo: InfoJWT = {
client_id,
clientId,
username: user.username
}
beforeAll(async () => {
@@ -165,14 +166,14 @@ describe('auth', () => {
it('should respond with access and refresh tokens', async () => {
const code = saveCode(
userInfo.username,
userInfo.client_id,
userInfo.clientId,
generateAuthCode(userInfo)
)
const res = await request(app)
.post('/SASjsApi/auth/token')
.send({
client_id,
clientId,
code
})
.expect(200)
@@ -185,7 +186,7 @@ describe('auth', () => {
const res = await request(app)
.post('/SASjsApi/auth/token')
.send({
client_id
clientId
})
.expect(400)
@@ -193,10 +194,10 @@ describe('auth', () => {
expect(res.body).toEqual({})
})
it('should respond with Bad Request if client_id is missing', async () => {
it('should respond with Bad Request if clientId is missing', async () => {
const code = saveCode(
userInfo.username,
userInfo.client_id,
userInfo.clientId,
generateAuthCode(userInfo)
)
@@ -207,7 +208,7 @@ describe('auth', () => {
})
.expect(400)
expect(res.text).toEqual(`"client_id" is required`)
expect(res.text).toEqual(`"clientId" is required`)
expect(res.body).toEqual({})
})
@@ -215,7 +216,7 @@ describe('auth', () => {
const res = await request(app)
.post('/SASjsApi/auth/token')
.send({
client_id,
clientId,
code: 'InvalidCode'
})
.expect(403)
@@ -223,17 +224,17 @@ describe('auth', () => {
expect(res.body).toEqual({})
})
it('should respond with Forbidden if client_id is invalid', async () => {
it('should respond with Forbidden if clientId is invalid', async () => {
const code = saveCode(
userInfo.username,
userInfo.client_id,
userInfo.clientId,
generateAuthCode(userInfo)
)
const res = await request(app)
.post('/SASjsApi/auth/token')
.send({
client_id: 'WrongClientID',
clientId: 'WrongClientID',
code
})
.expect(403)
@@ -242,20 +243,59 @@ describe('auth', () => {
})
})
describe('logout', () => {
const accessToken = generateAccessToken({
client_id,
describe('refresh', () => {
const refreshToken = generateRefreshToken({
clientId,
username: user.username
})
beforeEach(async () => {
await createUser(user)
await saveTokensInDB(
user.username,
client_id,
accessToken,
'refreshToken'
)
await saveTokensInDB(user.username, clientId, 'accessToken', refreshToken)
})
afterEach(async () => {
const collections = mongoose.connection.collections
const collection = collections['users']
await collection.deleteMany({})
})
afterAll(async () => {
const collections = mongoose.connection.collections
const collection = collections['users']
await collection.deleteMany({})
})
it('should respond with new access and refresh tokens', async () => {
const res = await request(app)
.post('/SASjsApi/auth/refresh')
.auth(refreshToken, { type: 'bearer' })
.send()
.expect(200)
expect(res.body).toHaveProperty('accessToken')
expect(res.body).toHaveProperty('refreshToken')
// cannot use same refresh again
const resWithError = await request(app)
.post('/SASjsApi/auth/refresh')
.auth(refreshToken, { type: 'bearer' })
.send()
.expect(401)
expect(resWithError.body).toEqual({})
})
})
describe('logout', () => {
const accessToken = generateAccessToken({
clientId,
username: user.username
})
beforeEach(async () => {
await createUser(user)
await saveTokensInDB(user.username, clientId, accessToken, 'refreshToken')
})
afterEach(async () => {
@@ -280,7 +320,12 @@ describe('auth', () => {
expect(res.body).toEqual({})
expect(
await verifyTokenInDB(user.username, client_id, accessToken)
await verifyTokenInDB(
user.username,
clientId,
accessToken,
'accessToken'
)
).toBeUndefined()
})
})

View File

@@ -8,19 +8,19 @@ import { createUser } from '../../../controllers/createUser'
import { saveTokensInDB } from '../../../utils'
const client = {
client_id: 'someclientID',
client_secret: 'someclientSecret'
clientId: 'someclientID',
clientSecret: 'someclientSecret'
}
const adminUser = {
displayname: 'Test Admin',
displayName: 'Test Admin',
username: 'testAdminUsername',
password: '12345678',
isadmin: true,
isactive: true
isAdmin: true,
isActive: true
}
const newClient = {
client_id: 'newClientID',
client_secret: 'newClientSecret'
clientId: 'newClientID',
clientSecret: 'newClientSecret'
}
describe('user', () => {
@@ -40,7 +40,7 @@ describe('user', () => {
describe('create', () => {
const adminAccessToken = generateAccessToken({
client_id: client.client_id,
clientId: client.clientId,
username: adminUser.username
})
@@ -48,7 +48,7 @@ describe('user', () => {
await createUser(adminUser)
await saveTokensInDB(
adminUser.username,
client.client_id,
client.clientId,
adminAccessToken,
'refreshToken'
)
@@ -67,8 +67,8 @@ describe('user', () => {
.send(newClient)
.expect(200)
expect(res.body.client_id).toEqual(newClient.client_id)
expect(res.body.client_secret).toEqual(newClient.client_secret)
expect(res.body.clientId).toEqual(newClient.clientId)
expect(res.body.clientSecret).toEqual(newClient.clientSecret)
})
it('should respond with Unauthorized if access token is not present', async () => {
@@ -83,20 +83,20 @@ describe('user', () => {
it('should respond with Forbideen if access token is not of an admin account', async () => {
const user = {
displayname: 'User 1',
displayName: 'User 1',
username: 'username1',
password: '12345678',
isadmin: false,
isactive: true
isAdmin: false,
isActive: true
}
const accessToken = generateAccessToken({
client_id: client.client_id,
clientId: client.clientId,
username: user.username
})
await createUser(user)
await saveTokensInDB(
user.username,
client.client_id,
client.clientId,
accessToken,
'refreshToken'
)
@@ -111,7 +111,7 @@ describe('user', () => {
expect(res.body).toEqual({})
})
it('should respond with Forbidden if client_id is already present', async () => {
it('should respond with Forbidden if clientId is already present', async () => {
await createClient(newClient)
const res = await request(app)
@@ -124,31 +124,31 @@ describe('user', () => {
expect(res.body).toEqual({})
})
it('should respond with Bad Request if client_id is missing', async () => {
it('should respond with Bad Request if clientId is missing', async () => {
const res = await request(app)
.post('/SASjsApi/client')
.auth(adminAccessToken, { type: 'bearer' })
.send({
...newClient,
client_id: undefined
clientId: undefined
})
.expect(400)
expect(res.text).toEqual(`"client_id" is required`)
expect(res.text).toEqual(`"clientId" is required`)
expect(res.body).toEqual({})
})
it('should respond with Bad Request if client_secret is missing', async () => {
it('should respond with Bad Request if clientSecret is missing', async () => {
const res = await request(app)
.post('/SASjsApi/client')
.auth(adminAccessToken, { type: 'bearer' })
.send({
...newClient,
client_secret: undefined
clientSecret: undefined
})
.expect(400)
expect(res.text).toEqual(`"client_secret" is required`)
expect(res.text).toEqual(`"clientSecret" is required`)
expect(res.body).toEqual({})
})
})

View File

@@ -10,16 +10,13 @@ import { generateAccessToken } from '../auth'
import { createUser } from '../../../controllers/createUser'
import { saveTokensInDB } from '../../../utils'
const client = {
clientid: 'someclientID',
clientsecret: 'someclientSecret'
}
const clientId = 'someclientID'
const user = {
displayname: 'Test User',
displayName: 'Test User',
username: 'testUsername',
password: '87654321',
isadmin: false,
isactive: true
isAdmin: false,
isActive: true
}
describe('files', () => {
@@ -38,18 +35,13 @@ describe('files', () => {
})
describe('deploy', () => {
const accessToken = generateAccessToken({
client_id: client.clientid,
clientId,
username: user.username
})
beforeAll(async () => {
await createUser(user)
await saveTokensInDB(
user.username,
client.clientid,
accessToken,
'refreshToken'
)
await saveTokensInDB(user.username, clientId, accessToken, 'refreshToken')
})
const shouldFailAssertion = async (payload: any) => {
const res = await request(app)

View File

@@ -6,23 +6,20 @@ import { createUser } from '../../../controllers/createUser'
import { generateAccessToken } from '../auth'
import { saveTokensInDB } from '../../../utils'
const client = {
clientid: 'someclientID',
clientsecret: 'someclientSecret'
}
const clientId = 'someclientID'
const adminUser = {
displayname: 'Test Admin',
displayName: 'Test Admin',
username: 'testAdminUsername',
password: '12345678',
isadmin: true,
isactive: true
isAdmin: true,
isActive: true
}
const user = {
displayname: 'Test User',
displayName: 'Test User',
username: 'testUsername',
password: '87654321',
isadmin: false,
isactive: true
isAdmin: false,
isActive: true
}
describe('user', () => {
@@ -42,7 +39,7 @@ describe('user', () => {
describe('create', () => {
const adminAccessToken = generateAccessToken({
client_id: client.clientid,
clientId,
username: adminUser.username
})
@@ -50,7 +47,7 @@ describe('user', () => {
await createUser(adminUser)
await saveTokensInDB(
adminUser.username,
client.clientid,
clientId,
adminAccessToken,
'refreshToken'
)
@@ -70,9 +67,9 @@ describe('user', () => {
.expect(200)
expect(res.body.username).toEqual(user.username)
expect(res.body.displayname).toEqual(user.displayname)
expect(res.body.isadmin).toEqual(user.isadmin)
expect(res.body.isactive).toEqual(user.isactive)
expect(res.body.displayName).toEqual(user.displayName)
expect(res.body.isAdmin).toEqual(user.isAdmin)
expect(res.body.isActive).toEqual(user.isActive)
})
it('should respond with Unauthorized if access token is not present', async () => {
@@ -87,16 +84,11 @@ describe('user', () => {
it('should respond with Forbideen if access token is not of an admin account', async () => {
const accessToken = generateAccessToken({
client_id: client.clientid,
clientId,
username: user.username
})
await createUser(user)
await saveTokensInDB(
user.username,
client.clientid,
accessToken,
'refreshToken'
)
await saveTokensInDB(user.username, clientId, accessToken, 'refreshToken')
const res = await request(app)
.post('/SASjsApi/user')
@@ -149,17 +141,17 @@ describe('user', () => {
expect(res.body).toEqual({})
})
it('should respond with Bad Request if displayname is missing', async () => {
it('should respond with Bad Request if displayName is missing', async () => {
const res = await request(app)
.post('/SASjsApi/user')
.auth(adminAccessToken, { type: 'bearer' })
.send({
...user,
displayname: undefined
displayName: undefined
})
.expect(400)
expect(res.text).toEqual(`"displayname" is required`)
expect(res.text).toEqual(`"displayName" is required`)
expect(res.body).toEqual({})
})
})

View File

@@ -11,10 +11,10 @@ userRouter.post('/', async (req, res) => {
try {
const savedUser = await createUser(data)
res.send({
displayname: savedUser.displayname,
displayName: savedUser.displayName,
username: savedUser.username,
isadmin: savedUser.isadmin,
isactive: savedUser.isactive,
isAdmin: savedUser.isAdmin,
isActive: savedUser.isActive,
tokens: []
})
} catch (err: any) {

View File

@@ -1,4 +1,4 @@
export interface InfoJWT {
client_id: string
clientId: string
username: string
}

View File

@@ -1,25 +1,54 @@
import jwt from 'jsonwebtoken'
import { verifyTokenInDB } from './verifyTokenInDB'
export const authenticateToken = (req: any, res: any, next: any) => {
export const authenticateAccessToken = (req: any, res: any, next: any) => {
authenticateToken(
req,
res,
next,
process.env.ACCESS_TOKEN_SECRET as string,
'accessToken'
)
}
export const authenticateRefreshToken = (req: any, res: any, next: any) => {
authenticateToken(
req,
res,
next,
process.env.REFRESH_TOKEN_SECRET as string,
'refreshToken'
)
}
const authenticateToken = (
req: any,
res: any,
next: any,
key: string,
tokenType: 'accessToken' | 'refreshToken' = 'accessToken'
) => {
const authHeader = req.headers['authorization']
const token = authHeader?.split(' ')[1]
if (!token) return res.sendStatus(401)
jwt.verify(
token,
process.env.ACCESS_TOKEN_SECRET as string,
async (err: any, data: any) => {
if (err) return res.sendStatus(403)
jwt.verify(token, key, async (err: any, data: any) => {
if (err) return res.sendStatus(401)
// verify this valid token's entry in DB
const user = await verifyTokenInDB(data?.username, data?.client_id, token)
// verify this valid token's entry in DB
const user = await verifyTokenInDB(
data?.username,
data?.clientId,
token,
tokenType
)
if (user) {
if (user) {
if (user.isActive) {
req.user = user
return next()
}
return res.sendStatus(403)
} else return res.sendStatus(401)
}
)
return res.sendStatus(401)
})
}

View File

@@ -1,10 +1,10 @@
import User from '../model/User'
export const removeTokensInDB = async (username: string, client_id: string) => {
export const removeTokensInDB = async (username: string, clientId: string) => {
const user = await User.findOne({ username })
const tokenObjIndex = user.tokens.findIndex(
(tokenObj: any) => tokenObj.clientid === client_id
(tokenObj: any) => tokenObj.clientId === clientId
)
if (tokenObjIndex > -1) {

View File

@@ -2,23 +2,23 @@ import User from '../model/User'
export const saveTokensInDB = async (
username: string,
client_id: string,
clientId: string,
accessToken: string,
refreshToken: string
) => {
const user = await User.findOne({ username })
const currentTokenObj = user.tokens.find(
(tokenObj: any) => tokenObj.clientid === client_id
(tokenObj: any) => tokenObj.clientId === clientId
)
if (currentTokenObj) {
currentTokenObj.accesstoken = accessToken
currentTokenObj.refreshtoken = refreshToken
currentTokenObj.accessToken = accessToken
currentTokenObj.refreshToken = refreshToken
} else {
user.tokens.push({
clientid: client_id,
accesstoken: accessToken,
refreshtoken: refreshToken
clientId: clientId,
accessToken: accessToken,
refreshToken: refreshToken
})
}
await user.save()

View File

@@ -7,26 +7,26 @@ export const authorizeValidation = (data: any): Joi.ValidationResult =>
Joi.object({
username: usernameSchema,
password: passwordSchema,
client_id: Joi.string().required()
clientId: Joi.string().required()
}).validate(data)
export const tokenValidation = (data: any): Joi.ValidationResult =>
Joi.object({
client_id: Joi.string().required(),
clientId: Joi.string().required(),
code: Joi.string().required()
}).validate(data)
export const registerUserValidation = (data: any): Joi.ValidationResult =>
Joi.object({
displayname: Joi.string().min(6).required(),
displayName: Joi.string().min(6).required(),
username: usernameSchema,
password: passwordSchema,
isadmin: Joi.boolean(),
isactive: Joi.boolean()
isAdmin: Joi.boolean(),
isActive: Joi.boolean()
}).validate(data)
export const registerClientValidation = (data: any): Joi.ValidationResult =>
Joi.object({
client_id: Joi.string().required(),
client_secret: Joi.string().required()
clientId: Joi.string().required(),
clientSecret: Joi.string().required()
}).validate(data)

View File

@@ -2,21 +2,22 @@ import User from '../model/User'
export const verifyTokenInDB = async (
username: string,
client_id: string,
token: string
clientId: string,
token: string,
tokenType: 'accessToken' | 'refreshToken'
) => {
const dbUser = await User.findOne({ username })
const currentTokenObj = dbUser.tokens.find(
(tokenObj: any) => tokenObj.clientid === client_id
(tokenObj: any) => tokenObj.clientId === clientId
)
return currentTokenObj?.accesstoken === token
return currentTokenObj?.[tokenType] === token
? {
client_id,
clientId,
username,
isadmin: dbUser.isadmin,
isactive: dbUser.isactive
isAdmin: dbUser.isAdmin,
isActive: dbUser.isActive
}
: undefined
}