Merge pull request #3666 from Infisical/feat/add-token-period-support

feat: add token period support for ua
This commit is contained in:
Maidul Islam
2025-05-28 17:38:59 -04:00
committed by GitHub
26 changed files with 384 additions and 91 deletions
@@ -96,10 +96,15 @@ export const identityAccessTokenServiceFactory = ({
}
await validateAccessTokenExp({ ...identityAccessToken, accessTokenNumUses });
const { accessTokenMaxTTL, createdAt: accessTokenCreatedAt, accessTokenTTL } = identityAccessToken;
const {
accessTokenMaxTTL,
createdAt: accessTokenCreatedAt,
accessTokenTTL,
accessTokenPeriod
} = identityAccessToken;
// max ttl checks - will it go above max ttl
if (Number(accessTokenMaxTTL) > 0) {
// Only enforce Max TTL for non-periodic tokens
if (Number(accessTokenMaxTTL) > 0 && Number(accessTokenPeriod) === 0) {
const accessTokenCreated = new Date(accessTokenCreatedAt);
const ttlInMilliseconds = Number(accessTokenMaxTTL) * 1000;
const currentDate = new Date();
@@ -125,6 +130,18 @@ export const identityAccessTokenServiceFactory = ({
accessTokenLastRenewedAt: new Date()
});
const ttl = Number(accessTokenTTL);
const period = Number(accessTokenPeriod);
let expiresIn: number | undefined;
if (period > 0) {
expiresIn = period;
} else if (ttl > 0) {
expiresIn = ttl;
} else {
expiresIn = undefined;
}
const renewedToken = jwt.sign(
{
identityId: decodedToken.identityId,
@@ -133,12 +150,7 @@ export const identityAccessTokenServiceFactory = ({
authTokenType: AuthTokenType.IDENTITY_ACCESS_TOKEN
} as TIdentityAccessTokenJwtPayload,
appCfg.AUTH_SECRET,
// akhilmhdh: for non-expiry tokens you should not even set the value, including undefined. Even for undefined jsonwebtoken throws error
Number(identityAccessToken.accessTokenTTL) === 0
? undefined
: {
expiresIn: Number(identityAccessToken.accessTokenTTL)
}
expiresIn !== undefined ? { expiresIn } : undefined
);
return { accessToken: renewedToken, identityAccessToken: updatedIdentityAccessToken };
@@ -114,21 +114,36 @@ export const identityUaServiceFactory = ({
});
}
const accessTokenTTLParams =
Number(identityUa.accessTokenPeriod) === 0
? {
accessTokenTTL: identityUa.accessTokenTTL,
accessTokenMaxTTL: identityUa.accessTokenMaxTTL
}
: {
accessTokenTTL: identityUa.accessTokenPeriod,
// Setting Max TTL to 2 × period ensures that clients can always renew their token
// at least once, and matches client logic that checks if renewing would exceed Max TTL.
accessTokenMaxTTL: 2 * identityUa.accessTokenPeriod
};
const identityAccessToken = await identityUaDAL.transaction(async (tx) => {
const uaClientSecretDoc = await identityUaClientSecretDAL.incrementUsage(validClientSecretInfo!.id, tx);
const newToken = await identityAccessTokenDAL.create(
{
identityId: identityUa.identityId,
isAccessTokenRevoked: false,
identityUAClientSecretId: uaClientSecretDoc.id,
accessTokenTTL: identityUa.accessTokenTTL,
accessTokenMaxTTL: identityUa.accessTokenMaxTTL,
accessTokenNumUses: 0,
accessTokenNumUsesLimit: identityUa.accessTokenNumUsesLimit,
authMethod: IdentityAuthMethod.UNIVERSAL_AUTH
accessTokenPeriod: identityUa.accessTokenPeriod,
authMethod: IdentityAuthMethod.UNIVERSAL_AUTH,
...accessTokenTTLParams
},
tx
);
return newToken;
});
@@ -149,7 +164,14 @@ export const identityUaServiceFactory = ({
}
);
return { accessToken, identityUa, validClientSecretInfo, identityAccessToken, identityMembershipOrg };
return {
accessToken,
identityUa,
validClientSecretInfo,
identityAccessToken,
identityMembershipOrg,
...accessTokenTTLParams
};
};
const attachUniversalAuth = async ({
@@ -163,7 +185,8 @@ export const identityUaServiceFactory = ({
actorAuthMethod,
actor,
actorOrgId,
isActorSuperAdmin
isActorSuperAdmin,
accessTokenPeriod
}: TAttachUaDTO) => {
await validateIdentityUpdateForSuperAdminPrivileges(identityId, isActorSuperAdmin);
@@ -232,7 +255,8 @@ export const identityUaServiceFactory = ({
accessTokenMaxTTL,
accessTokenTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps: JSON.stringify(reformattedAccessTokenTrustedIps)
accessTokenTrustedIps: JSON.stringify(reformattedAccessTokenTrustedIps),
accessTokenPeriod
},
tx
);
@@ -248,6 +272,7 @@ export const identityUaServiceFactory = ({
accessTokenTTL,
accessTokenTrustedIps,
clientSecretTrustedIps,
accessTokenPeriod,
actorId,
actorAuthMethod,
actor,
@@ -324,6 +349,7 @@ export const identityUaServiceFactory = ({
accessTokenMaxTTL,
accessTokenTTL,
accessTokenNumUsesLimit,
accessTokenPeriod,
accessTokenTrustedIps: reformattedAccessTokenTrustedIps
? JSON.stringify(reformattedAccessTokenTrustedIps)
: undefined
@@ -5,6 +5,7 @@ export type TAttachUaDTO = {
accessTokenTTL: number;
accessTokenMaxTTL: number;
accessTokenNumUsesLimit: number;
accessTokenPeriod: number;
clientSecretTrustedIps: { ipAddress: string }[];
accessTokenTrustedIps: { ipAddress: string }[];
isActorSuperAdmin?: boolean;
@@ -15,6 +16,7 @@ export type TUpdateUaDTO = {
accessTokenTTL?: number;
accessTokenMaxTTL?: number;
accessTokenNumUsesLimit?: number;
accessTokenPeriod?: number;
clientSecretTrustedIps?: { ipAddress: string }[];
accessTokenTrustedIps?: { ipAddress: string }[];
} & Omit<TProjectPermission, "projectId">;