mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-09 15:38:03 -05:00
Complete v1 API Key
This commit is contained in:
@@ -111,7 +111,7 @@ app.use('/api/v2/workspace', v2WorkspaceRouter); // TODO: turn into plural route
|
||||
app.use('/api/v2/secret', v2SecretRouter); // stop supporting, TODO: revise
|
||||
app.use('/api/v2/secrets', v2SecretsRouter);
|
||||
app.use('/api/v2/service-token', v2ServiceTokenDataRouter); // TODO: turn into plural route
|
||||
app.use('/api/v2/api-key-data', v2APIKeyDataRouter);
|
||||
app.use('/api/v2/api-key', v2APIKeyDataRouter);
|
||||
|
||||
// api docs
|
||||
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerFile))
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ADMIN, MEMBER } from '../../../variables';
|
||||
router.get(
|
||||
'/:secretId/secret-versions',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireSecretAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
@@ -27,7 +27,7 @@ router.get(
|
||||
router.post(
|
||||
'/:secretId/secret-versions/rollback',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireSecretAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
|
||||
@@ -12,7 +12,7 @@ import { workspaceController } from '../../controllers/v1';
|
||||
router.get(
|
||||
'/:workspaceId/secret-snapshots',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
@@ -40,7 +40,7 @@ router.get(
|
||||
router.post(
|
||||
'/:workspaceId/secret-snapshots/rollback',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
@@ -54,7 +54,7 @@ router.post(
|
||||
router.get(
|
||||
'/:workspaceId/logs',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
|
||||
@@ -16,49 +16,66 @@ import {
|
||||
AccountNotFoundError,
|
||||
ServiceTokenDataNotFoundError,
|
||||
APIKeyDataNotFoundError,
|
||||
UnauthorizedRequestError
|
||||
UnauthorizedRequestError,
|
||||
BadRequestError
|
||||
} from '../utils/errors';
|
||||
|
||||
// TODO 1: check if API key works
|
||||
// TODO 2: optimize middleware
|
||||
|
||||
/**
|
||||
* Validate that auth token value [authTokenValue] falls under one of
|
||||
* accepted auth modes [acceptedAuthModes].
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} obj.authTokenValue - auth token value (e.g. JWT or service token value)
|
||||
* @param {String[]} obj.acceptedAuthModes - accepted auth modes (e.g. jwt, serviceToken)
|
||||
* @returns {String} authMode - auth mode
|
||||
* @param {Object} obj.headers - HTTP request headers object
|
||||
*/
|
||||
const validateAuthMode = ({
|
||||
authTokenValue,
|
||||
headers,
|
||||
acceptedAuthModes
|
||||
}: {
|
||||
authTokenValue: string;
|
||||
acceptedAuthModes: string[];
|
||||
headers: { [key: string]: string | string[] | undefined },
|
||||
acceptedAuthModes: string[]
|
||||
}) => {
|
||||
let authMode;
|
||||
try {
|
||||
switch (authTokenValue.split('.', 1)[0]) {
|
||||
case 'st':
|
||||
authMode = 'serviceToken';
|
||||
break;
|
||||
case 'ak':
|
||||
authMode = 'apiKey';
|
||||
break;
|
||||
default:
|
||||
authMode = 'jwt';
|
||||
break;
|
||||
}
|
||||
|
||||
if (!acceptedAuthModes.includes(authMode))
|
||||
throw UnauthorizedRequestError({ message: 'Failed to authenticated auth mode' });
|
||||
// TODO: refactor middleware
|
||||
const apiKey = headers['x-api-key'];
|
||||
const authHeader = headers['authorization'];
|
||||
|
||||
} catch (err) {
|
||||
throw UnauthorizedRequestError({ message: 'Failed to authenticated auth mode' });
|
||||
let authTokenType, authTokenValue;
|
||||
if (apiKey === undefined && authHeader === undefined) {
|
||||
// case: no auth or X-API-KEY header present
|
||||
throw BadRequestError({ message: 'Missing Authorization or X-API-KEY in request header.' });
|
||||
}
|
||||
|
||||
return authMode;
|
||||
if (typeof apiKey === 'string') {
|
||||
// case: treat request authentication type as via X-API-KEY (i.e. API Key)
|
||||
authTokenType = 'apiKey';
|
||||
authTokenValue = apiKey;
|
||||
}
|
||||
|
||||
if (typeof authHeader === 'string') {
|
||||
// case: treat request authentication type as via Authorization header (i.e. either JWT or service token)
|
||||
const [tokenType, tokenValue] = <[string, string]>authHeader.split(' ', 2) ?? [null, null]
|
||||
if (tokenType === null)
|
||||
throw BadRequestError({ message: `Missing Authorization Header in the request header.` });
|
||||
if (tokenType.toLowerCase() !== 'bearer')
|
||||
throw BadRequestError({ message: `The provided authentication type '${tokenType}' is not supported.` });
|
||||
if (tokenValue === null)
|
||||
throw BadRequestError({ message: 'Missing Authorization Body in the request header.' });
|
||||
|
||||
switch (tokenValue.split('.', 1)[0]) {
|
||||
case 'st':
|
||||
authTokenType = 'serviceToken';
|
||||
break;
|
||||
default:
|
||||
authTokenType = 'jwt';
|
||||
}
|
||||
authTokenValue = tokenValue;
|
||||
}
|
||||
|
||||
if (!authTokenType || !authTokenValue) throw BadRequestError({ message: 'Missing valid Authorization or X-API-KEY in request header.' });
|
||||
|
||||
if (!acceptedAuthModes.includes(authTokenType)) throw BadRequestError({ message: 'The provided authentication type is not supported.' });
|
||||
|
||||
return ({
|
||||
authTokenType,
|
||||
authTokenValue
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
getAuthSTDPayload,
|
||||
getAuthAPIKeyPayload
|
||||
} from '../helpers/auth';
|
||||
import { BadRequestError } from '../utils/errors';
|
||||
|
||||
declare module 'jsonwebtoken' {
|
||||
export interface UserIDJwtPayload extends jwt.JwtPayload {
|
||||
@@ -31,37 +30,28 @@ const requireAuth = ({
|
||||
acceptedAuthModes: string[];
|
||||
}) => {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>req.headers['authorization']?.split(' ', 2) ?? [null, null]
|
||||
if (AUTH_TOKEN_TYPE === null)
|
||||
return next(BadRequestError({ message: `Missing Authorization Header in the request header.` }))
|
||||
if (AUTH_TOKEN_TYPE.toLowerCase() !== 'bearer')
|
||||
return next(BadRequestError({ message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.` }))
|
||||
if (AUTH_TOKEN_VALUE === null)
|
||||
return next(BadRequestError({ message: 'Missing Authorization Body in the request header' }))
|
||||
|
||||
// validate auth token against
|
||||
const authMode = validateAuthMode({
|
||||
authTokenValue: AUTH_TOKEN_VALUE,
|
||||
// validate auth token against accepted auth modes [acceptedAuthModes]
|
||||
// and return token type [authTokenType] and value [authTokenValue]
|
||||
const { authTokenType, authTokenValue } = validateAuthMode({
|
||||
headers: req.headers,
|
||||
acceptedAuthModes
|
||||
});
|
||||
|
||||
if (!acceptedAuthModes.includes(authMode)) throw new Error('Failed to validate auth mode');
|
||||
|
||||
// attach auth payloads
|
||||
switch (authMode) {
|
||||
switch (authTokenType) {
|
||||
case 'serviceToken':
|
||||
req.serviceTokenData = await getAuthSTDPayload({
|
||||
authTokenValue: AUTH_TOKEN_VALUE
|
||||
authTokenValue
|
||||
});
|
||||
break;
|
||||
case 'apiKey':
|
||||
req.user = await getAuthAPIKeyPayload({
|
||||
authTokenValue: AUTH_TOKEN_VALUE
|
||||
authTokenValue
|
||||
});
|
||||
break;
|
||||
default:
|
||||
req.user = await getAuthUserPayload({
|
||||
authTokenValue: AUTH_TOKEN_VALUE
|
||||
authTokenValue
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ router.post(
|
||||
}),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER],
|
||||
@@ -76,7 +76,7 @@ router.get(
|
||||
query('environment').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt', 'serviceToken']
|
||||
acceptedAuthModes: ['jwt', 'apiKey', 'serviceToken']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER],
|
||||
@@ -115,7 +115,7 @@ router.patch(
|
||||
}),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireSecretsAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
@@ -143,7 +143,7 @@ router.delete(
|
||||
.isEmpty(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireSecretsAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
|
||||
@@ -8,7 +8,7 @@ import { usersController } from '../../controllers/v2';
|
||||
router.get(
|
||||
'/me',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
usersController.getMe
|
||||
);
|
||||
|
||||
@@ -45,7 +45,7 @@ router.get(
|
||||
router.get(
|
||||
'/:workspaceId/encrypted-key',
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER]
|
||||
@@ -75,7 +75,7 @@ router.get( // new - TODO: rewire dashboard to this route
|
||||
param('workspaceId').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN, MEMBER],
|
||||
@@ -89,7 +89,7 @@ router.delete( // TODO - rewire dashboard to this route
|
||||
param('membershipId').exists().trim(),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN],
|
||||
@@ -107,7 +107,7 @@ router.patch( // TODO - rewire dashboard to this route
|
||||
body('role').exists().isString().trim().isIn([ADMIN, MEMBER]),
|
||||
validateRequest,
|
||||
requireAuth({
|
||||
acceptedAuthModes: ['jwt']
|
||||
acceptedAuthModes: ['jwt', 'apiKey']
|
||||
}),
|
||||
requireWorkspaceAuth({
|
||||
acceptedRoles: [ADMIN],
|
||||
|
||||
Reference in New Issue
Block a user