1
0
mirror of https://github.com/Infisical/infisical.git synced 2025-03-29 22:02:57 +00:00

Modify service token format

This commit is contained in:
Tuan Dang
2023-01-02 22:43:00 +07:00
parent b8a64714d2
commit e99ee94a7b
7 changed files with 41 additions and 38 deletions

@ -15,7 +15,7 @@ import {
* @param res
* @returns
*/
export const getServiceTokenData = async (req: Request, res: Response) => ({
export const getServiceTokenData = async (req: Request, res: Response) => res.status(200).send({
serviceTokenData: req.serviceTokenData
});
@ -38,35 +38,32 @@ export const createServiceTokenData = async (req: Request, res: Response) => {
tag,
expiresIn
} = req.body;
const secret = crypto.randomBytes(16).toString('hex');
const secretHash = await bcrypt.hash(secret, SALT_ROUNDS);
// create 41-char service token with first 9-char being the prefix
serviceToken = `st.${crypto.randomBytes(19).toString('hex')}`;
const serviceTokenHash = await bcrypt.hash(serviceToken, SALT_ROUNDS);
// compute access token expiration date
const expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
// create service token data
serviceTokenData = new ServiceTokenData({
serviceTokenData = await new ServiceTokenData({
name,
workspace: workspaceId,
environment,
user: req.user._id,
expiresAt,
prefix: serviceToken.substring(0, 9),
serviceTokenHash,
secretHash,
encryptedKey,
iv,
tag
})
}).save();
await serviceTokenData.save();
// return service token data without sensitive data
serviceTokenData = await ServiceTokenData.findById(serviceTokenData._id);
if (!serviceTokenData) throw new Error('Failed to find service token data');
serviceToken = `st.${serviceTokenData._id.toString()}.${secret}`;
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);

@ -15,7 +15,8 @@ import {
import {
AccountNotFoundError,
ServiceTokenDataNotFoundError,
UnauthorizedRequestError
UnauthorizedRequestError,
BadRequestError
} from '../utils/errors';
/**
@ -101,15 +102,30 @@ const getAuthSTDPayload = async ({
}) => {
let serviceTokenData;
try {
const serviceTokenHash = await bcrypt.hash(authTokenValue, SALT_ROUNDS);
const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3);
// TODO: optimize double query
serviceTokenData = await ServiceTokenData
.findById(TOKEN_IDENTIFIER, 'secretHash expiresAt');
if (serviceTokenData?.expiresAt && new Date(serviceTokenData.expiresAt) < new Date()) {
// case: service token expired
await ServiceTokenData.findByIdAndDelete(serviceTokenData._id);
throw UnauthorizedRequestError({
message: 'Failed to authenticate expired service token'
});
}
if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' });
const isMatch = await bcrypt.compare(TOKEN_SECRET, serviceTokenData.secretHash);
if (!isMatch) throw UnauthorizedRequestError({
message: 'Failed to authenticate service token'
});
serviceTokenData = await ServiceTokenData
.findOne({
serviceTokenHash
})
.findById(TOKEN_IDENTIFIER)
.select('+encryptedKey +iv +tag');
if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' });
} catch (err) {
throw UnauthorizedRequestError({

@ -6,8 +6,7 @@ import {
getAuthUserPayload,
getAuthSTDPayload
} from '../helpers/auth';
import { JWT_AUTH_SECRET } from '../config';
import { AccountNotFoundError, BadRequestError, UnauthorizedRequestError } from '../utils/errors';
import { BadRequestError } from '../utils/errors';
declare module 'jsonwebtoken' {
export interface UserIDJwtPayload extends jwt.JwtPayload {

@ -40,10 +40,10 @@ const requireWorkspaceAuth = ({
if (
req.serviceTokenData
&& req.serviceTokenData.workspace !== workspaceId
&& req.serviceTokenData.environment !== req.body.environment
)
// case: st auth
&& req.serviceTokenData.environment !== req.query.environment
) {
next(UnauthorizedRequestError({message: 'Unable to authenticate workspace'}))
}
return next();
} catch (err) {

@ -7,8 +7,7 @@ export interface IServiceTokenData {
environment: string; // TODO: adapt to upcoming environment id
user: Types.ObjectId;
expiresAt: Date;
prefix: string;
serviceTokenHash: string;
secretHash: string;
encryptedKey: string;
iv: string;
tag: string;
@ -37,11 +36,7 @@ const serviceTokenDataSchema = new Schema<IServiceTokenData>(
expiresAt: {
type: Date
},
prefix: {
type: String,
required: true
},
serviceTokenHash: {
secretHash: {
type: String,
unique: true,
required: true,

@ -1,4 +1,4 @@
import express, { Request, Response } from 'express';
import express from 'express';
const router = express.Router();
import {
requireAuth,
@ -20,8 +20,6 @@ router.get(
requireAuth({
acceptedAuthModes: ['serviceToken']
}),
param('serviceTokenDataId').exists().trim(),
validateRequest,
serviceTokenDataController.getServiceTokenData
);

@ -4,11 +4,9 @@ import { body, param, query } from 'express-validator';
import {
requireAuth,
requireWorkspaceAuth,
requireServiceTokenAuth,
validateRequest
} from '../../middleware';
import { ADMIN, MEMBER, COMPLETED, GRANTED } from '../../variables';
import { membershipController } from '../../controllers/v1';
import { workspaceController } from '../../controllers/v2';
router.post(