Feat: Org Scoped JWT Tokens

This commit is contained in:
Daniel Hougaard
2024-03-17 18:48:10 +01:00
parent 8fc081973d
commit d287c3e152
8 changed files with 129 additions and 26 deletions
+2 -2
View File
@@ -15,10 +15,10 @@ export const validateProviderAuthToken = (providerToken: string, username?: stri
if (decodedToken.username !== username) throw new Error("Invalid auth credentials");
if (decodedToken.organizationId) {
return { orgId: decodedToken.organizationId };
return { orgId: decodedToken.organizationId, authMethod: decodedToken.authMethod };
}
return {};
return { authMethod: decodedToken.authMethod, orgId: null };
};
export const validateSignUpAuthorization = (token: string, userId: string, validate = true) => {
+25 -16
View File
@@ -17,7 +17,7 @@ import {
TOauthLoginDTO,
TVerifyMfaTokenDTO
} from "./auth-login-type";
import { AuthMethod, AuthTokenType } from "./auth-type";
import { AuthMethod, AuthModeMfaJwtTokenPayload, AuthTokenType } from "./auth-type";
type TAuthLoginServiceFactoryDep = {
userDAL: TUserDALFactory;
@@ -83,12 +83,14 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
user,
ip,
userAgent,
organizationId
organizationId,
authMethod
}: {
user: TUsers;
ip: string;
userAgent: string;
organizationId?: string;
authMethod: AuthMethod;
}) => {
const cfg = getConfig();
await updateUserDeviceSession(user, ip, userAgent);
@@ -98,8 +100,10 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
userId: user.id
});
if (!tokenSession) throw new Error("Failed to create token");
const accessToken = jwt.sign(
{
authMethod,
authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: user.id,
tokenVersionId: tokenSession.id,
@@ -112,6 +116,7 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
const refreshToken = jwt.sign(
{
authMethod,
authTokenType: AuthTokenType.REFRESH_TOKEN,
userId: user.id,
tokenVersionId: tokenSession.id,
@@ -158,9 +163,9 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
const loginExchangeClientProof = async ({
email,
clientProof,
providerAuthToken,
ip,
userAgent
userAgent,
providerAuthToken
}: TLoginClientProofDTO) => {
const userEnc = await userDAL.findUserEncKeyByUsername({
username: email
@@ -168,14 +173,14 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
if (!userEnc) throw new Error("Failed to find user");
const cfg = getConfig();
let organizationId;
if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) {
const { orgId } = validateProviderAuthToken(providerAuthToken as string, email);
organizationId = orgId;
} else if (providerAuthToken) {
// SAML SSO
const { orgId } = validateProviderAuthToken(providerAuthToken, email);
organizationId = orgId;
// let organizationId;
// let authMethod = (providerAuthToken as AuthMethod) || AuthMethod.EMAIL;
let authMethod = AuthMethod.EMAIL;
if (providerAuthToken) {
authMethod = validateProviderAuthToken(providerAuthToken, email).authMethod;
}
if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey) throw new Error("Failed to authenticate. Try again?");
@@ -196,9 +201,9 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
if (userEnc.isMfaEnabled && userEnc.email) {
const mfaToken = jwt.sign(
{
authMethod,
authTokenType: AuthTokenType.MFA_TOKEN,
userId: userEnc.userId,
organizationId
userId: userEnc.userId
},
cfg.AUTH_SECRET,
{
@@ -221,7 +226,7 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
},
ip,
userAgent,
organizationId
authMethod
});
return { token, isMfaEnabled: false, user: userEnc } as const;
@@ -250,6 +255,9 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
userId,
code: mfaToken
});
const decodedToken = jwt.verify(mfaToken, getConfig().AUTH_SECRET) as AuthModeMfaJwtTokenPayload;
const userEnc = await userDAL.findUserEncKeyByUserId(userId);
if (!userEnc) throw new Error("Failed to authenticate user");
@@ -260,7 +268,8 @@ export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }:
},
ip,
userAgent,
organizationId: orgId
organizationId: orgId,
authMethod: decodedToken.authMethod
});
return { token, user: userEnc };
@@ -174,6 +174,7 @@ export const authSignupServiceFactory = ({
const accessToken = jwt.sign(
{
authMethod: AuthMethod.EMAIL,
authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: updateduser.info.id,
tokenVersionId: tokenSession.id,
@@ -277,6 +278,7 @@ export const authSignupServiceFactory = ({
const accessToken = jwt.sign(
{
authMethod: AuthMethod.EMAIL,
authTokenType: AuthTokenType.ACCESS_TOKEN,
userId: updateduser.info.id,
tokenVersionId: tokenSession.id,
+6
View File
@@ -40,6 +40,7 @@ export enum ActorType { // would extend to AWS, Azure, ...
export type AuthModeJwtTokenPayload = {
authTokenType: AuthTokenType.ACCESS_TOKEN;
authMethod: AuthMethod;
userId: string;
tokenVersionId: string;
accessVersion: number;
@@ -48,12 +49,15 @@ export type AuthModeJwtTokenPayload = {
export type AuthModeMfaJwtTokenPayload = {
authTokenType: AuthTokenType.MFA_TOKEN;
authMethod: AuthMethod;
userId: string;
organizationId?: string;
};
export type AuthModeRefreshJwtTokenPayload = {
// authMode
authTokenType: AuthTokenType.REFRESH_TOKEN;
authMethod: AuthMethod;
userId: string;
tokenVersionId: string;
refreshVersion: number;
@@ -63,6 +67,8 @@ export type AuthModeRefreshJwtTokenPayload = {
export type AuthModeProviderJwtTokenPayload = {
authTokenType: AuthTokenType.PROVIDER_TOKEN;
username: string;
authMethod: AuthMethod;
email: string;
organizationId?: string;
};