feat(auth): split api-key boundary for frontend auth flow
This commit is contained in:
@@ -21,6 +21,10 @@ function signAccessToken(userId: string, email: string): string {
|
||||
return jwt.sign({ sub: userId, email }, secret, { expiresIn });
|
||||
}
|
||||
|
||||
function getAccessTokenExpiresInSeconds(): number {
|
||||
return parseDurationToSeconds(process.env.FABRIC_BACKEND_CENTER_JWT_ACCESS_EXPIRES_IN ?? '15m', 900);
|
||||
}
|
||||
|
||||
function signRefreshToken(userId: string, email: string): string {
|
||||
const secret = process.env.FABRIC_BACKEND_CENTER_JWT_REFRESH_SECRET as string;
|
||||
const expiresIn = parseDurationToSeconds(process.env.FABRIC_BACKEND_CENTER_JWT_REFRESH_EXPIRES_IN ?? '30d', 2592000);
|
||||
@@ -29,7 +33,7 @@ function signRefreshToken(userId: string, email: string): string {
|
||||
|
||||
function signGuildAccessToken(userId: string, email: string, guildNodeId: string): string {
|
||||
const secret = process.env.FABRIC_BACKEND_CENTER_JWT_ACCESS_SECRET as string;
|
||||
const expiresIn = parseDurationToSeconds(process.env.FABRIC_BACKEND_CENTER_JWT_ACCESS_EXPIRES_IN ?? '15m', 900);
|
||||
const expiresIn = getAccessTokenExpiresInSeconds();
|
||||
return jwt.sign({ sub: userId, email, gid: guildNodeId, typ: 'guild_access' }, secret, { expiresIn });
|
||||
}
|
||||
|
||||
@@ -88,6 +92,7 @@ export class AuthService {
|
||||
guildNodeId: g.nodeId,
|
||||
token: signGuildAccessToken(userId, email, g.nodeId),
|
||||
tokenType: 'Bearer',
|
||||
expiresIn: getAccessTokenExpiresInSeconds(),
|
||||
}));
|
||||
|
||||
return { guilds, guildAccessTokens };
|
||||
@@ -148,6 +153,7 @@ export class AuthService {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
tokenType: 'Bearer',
|
||||
expiresIn: getAccessTokenExpiresInSeconds(),
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
@@ -237,6 +243,7 @@ export class AuthService {
|
||||
accessToken: newAccessToken,
|
||||
refreshToken: newRefreshToken,
|
||||
tokenType: 'Bearer',
|
||||
expiresIn: getAccessTokenExpiresInSeconds(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,18 @@ export class CenterApiKeyGuard implements CanActivate {
|
||||
const path = req.path ?? '';
|
||||
const method = (req.method ?? 'GET').toUpperCase();
|
||||
|
||||
const noApiKeyRequired =
|
||||
path === '/healthz' ||
|
||||
path.endsWith('/healthz') ||
|
||||
(method === 'POST' && (path === '/auth/login' || path.endsWith('/auth/login'))) ||
|
||||
(method === 'POST' && (path === '/auth/refresh' || path.endsWith('/auth/refresh'))) ||
|
||||
(method === 'POST' && (path === '/auth/logout' || path.endsWith('/auth/logout'))) ||
|
||||
(method === 'GET' && (path === '/auth/me/guilds' || path.endsWith('/auth/me/guilds')));
|
||||
|
||||
if (noApiKeyRequired) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// only guild registration is exempt from API key; it is protected by HMAC secret
|
||||
if (method === 'POST' && (path === '/nodes/register' || path.endsWith('/nodes/register'))) {
|
||||
return true;
|
||||
@@ -40,4 +52,3 @@ export class CenterApiKeyGuard implements CanActivate {
|
||||
throw new UnauthorizedException('invalid api key');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user