diff --git a/backend/src/controllers/v1/universalAuthController.ts b/backend/src/controllers/v1/universalAuthController.ts index e22c4e6860..750c356394 100644 --- a/backend/src/controllers/v1/universalAuthController.ts +++ b/backend/src/controllers/v1/universalAuthController.ts @@ -3,28 +3,28 @@ import { Types } from "mongoose"; import jwt from "jsonwebtoken"; import crypto from "crypto"; import bcrypt from "bcrypt"; -import { - IIdentity, - IIdentityTrustedIp, - IIdentityUniversalAuthClientSecret, - Identity, - IdentityAccessToken, - IdentityAuthMethod, - IdentityMembershipOrg, - IdentityUniversalAuth, - IdentityUniversalAuthClientSecret, +import { + IIdentity, + IIdentityTrustedIp, + IIdentityUniversalAuthClientSecret, + Identity, + IdentityAccessToken, + IdentityAuthMethod, + IdentityMembershipOrg, + IdentityUniversalAuth, + IdentityUniversalAuthClientSecret, } from "../../models"; import { createToken } from "../../helpers/auth"; import { AuthTokenType } from "../../variables"; -import { - BadRequestError, - ForbiddenRequestError, - ResourceNotFoundError, - UnauthorizedRequestError +import { + BadRequestError, + ForbiddenRequestError, + ResourceNotFoundError, + UnauthorizedRequestError } from "../../utils/errors"; import { - getAuthSecret, - getSaltRounds + getAuthSecret, + getSaltRounds } from "../../config"; import { ActorType, EventType, IRole } from "../../ee/models"; import { validateRequest } from "../../helpers/validation"; @@ -32,12 +32,12 @@ import * as reqValidator from "../../validation/auth"; import { checkIPAgainstBlocklist, extractIPDetails, isValidIpOrCidr } from "../../utils/ip"; import { getUserAgentType } from "../../utils/posthog"; import { EEAuditLogService, EELicenseService } from "../../ee/services"; -import { - OrgPermissionActions, - OrgPermissionSubjects, - getAuthDataOrgPermissions, - getOrgRolePermissions, - isAtLeastAsPrivilegedOrg +import { + OrgPermissionActions, + OrgPermissionSubjects, + getAuthDataOrgPermissions, + getOrgRolePermissions, + isAtLeastAsPrivilegedOrg } from "../../ee/services/RoleService"; import { ForbiddenError } from "@casl/ability"; @@ -53,7 +53,7 @@ const packageUniversalAuthClientSecretData = (identityUniversalAuthClientSecret: createdAt: identityUniversalAuthClientSecret.createdAt, updatedAt: identityUniversalAuthClientSecret.updatedAt }); - + /** * Renews an access token by its TTL * @param req @@ -86,9 +86,6 @@ export const renewAccessToken = async (req: Request, res: Response) => { createdAt: accessTokenCreatedAt } = identityAccessToken; - if (accessTokenTTL === accessTokenMaxTTL) throw UnauthorizedRequestError({ - message: "Failed to renew non-renewable access token" - }); // ttl check if (accessTokenTTL > 0) { @@ -141,6 +138,7 @@ export const renewAccessToken = async (req: Request, res: Response) => { return res.status(200).send({ accessToken, expiresIn: identityAccessToken.accessTokenTTL, + accessTokenMaxTTL: identityAccessToken.accessTokenMaxTTL, tokenType: "Bearer" }); } @@ -162,7 +160,7 @@ export const loginIdentityUniversalAuth = async (req: Request, res: Response) => const identityUniversalAuth = await IdentityUniversalAuth.findOne({ clientId }).populate<{ identity: IIdentity }>("identity"); - + if (!identityUniversalAuth) throw UnauthorizedRequestError(); checkIPAgainstBlocklist({ @@ -237,16 +235,16 @@ export const loginIdentityUniversalAuth = async (req: Request, res: Response) => // increment usage count by 1 await IdentityUniversalAuthClientSecret - .findByIdAndUpdate( - validatedClientSecretDatum._id, - { - clientSecretLastUsedAt: new Date(), - $inc: { clientSecretNumUses: 1 } - }, - { - new: true - } - ); + .findByIdAndUpdate( + validatedClientSecretDatum._id, + { + clientSecretLastUsedAt: new Date(), + $inc: { clientSecretNumUses: 1 } + }, + { + new: true + } + ); const identityAccessToken = await new IdentityAccessToken({ identity: identityUniversalAuth.identity, @@ -300,7 +298,8 @@ export const loginIdentityUniversalAuth = async (req: Request, res: Response) => return res.status(200).send({ accessToken, expiresIn: identityUniversalAuth.accessTokenTTL, - tokenType: "Bearer" + accessTokenMaxTTL: identityUniversalAuth.accessTokenMaxTTL, + tokenType: "Bearer", }); } @@ -328,7 +327,7 @@ export const addIdentityUniversalAuth = async (req: Request, res: Response) => { if (!identityMembershipOrg) throw ResourceNotFoundError({ message: `Failed to find identity with id ${identityId}` }); - + if (identityMembershipOrg.identity?.authMethod) throw BadRequestError({ message: "Failed to add universal auth to already-configured identity" }); @@ -377,7 +376,7 @@ export const addIdentityUniversalAuth = async (req: Request, res: Response) => { return extractIPDetails(accessTokenTrustedIp.ipAddress); }); - + const identityUniversalAuth = await new IdentityUniversalAuth({ identity: identityMembershipOrg.identity._id, clientId: crypto.randomUUID(), @@ -387,7 +386,7 @@ export const addIdentityUniversalAuth = async (req: Request, res: Response) => { accessTokenNumUsesLimit, accessTokenTrustedIps: reformattedAccessTokenTrustedIps, }).save(); - + await Identity.findByIdAndUpdate( identityMembershipOrg.identity._id, { @@ -439,7 +438,7 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) = if (!identityMembershipOrg) throw ResourceNotFoundError({ message: `Failed to find identity with id ${identityId}` }); - + if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.UNIVERSAL_AUTH) throw BadRequestError({ message: "Failed to add universal auth to already-configured identity" }); @@ -490,7 +489,7 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) = return extractIPDetails(accessTokenTrustedIp.ipAddress); }); } - + const identityUniversalAuth = await IdentityUniversalAuth.findOneAndUpdate( { identity: identityMembershipOrg.identity._id, @@ -531,7 +530,7 @@ export const getIdentityUniversalAuth = async (req: Request, res: Response) => { const { params: { identityId } } = await validateRequest(reqValidator.GetUniversalAuthForIdentityV1, req); - + const identityMembershipOrg = await IdentityMembershipOrg .findOne({ identity: new Types.ObjectId(identityId) @@ -558,7 +557,7 @@ export const getIdentityUniversalAuth = async (req: Request, res: Response) => { if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.UNIVERSAL_AUTH) throw BadRequestError({ message: "The identity does not have universal auth configured" }); - + const identityUniversalAuth = await IdentityUniversalAuth.findOne({ identity: identityMembershipOrg.identity._id, }); @@ -625,11 +624,11 @@ export const createUniversalAuthClientSecret = async (req: Request, res: Respons const clientSecret = crypto.randomBytes(32).toString("hex"); const clientSecretHash = await bcrypt.hash(clientSecret, await getSaltRounds()); - + const identityUniversalAuth = await IdentityUniversalAuth.findOne({ identity: identityMembershipOrg.identity._id }); - + if (!identityUniversalAuth) throw ResourceNotFoundError(); const identityUniversalAuthClientSecret = await new IdentityUniversalAuthClientSecret({ @@ -665,7 +664,7 @@ export const getUniversalAuthClientSecrets = async (req: Request, res: Response) const { params: { identityId } } = await validateRequest(reqValidator.GetUniversalAuthClientSecretsV1, req); - + const identityMembershipOrg = await IdentityMembershipOrg.findOne({ identity: new Types.ObjectId(identityId) }).populate<{ @@ -725,7 +724,7 @@ export const revokeUniversalAuthClientSecret = async (req: Request, res: Respons const { params: { identityId, clientSecretId } } = await validateRequest(reqValidator.RevokeUniversalAuthClientSecretV1, req); - + const identityMembershipOrg = await IdentityMembershipOrg .findOne({ identity: new Types.ObjectId(identityId) @@ -773,7 +772,7 @@ export const revokeUniversalAuthClientSecret = async (req: Request, res: Respons ); if (!clientSecretData) throw ResourceNotFoundError(); - + await EEAuditLogService.createAuditLog( req.authData, {