feat: resource restriction in presign token (#2150)

This commit is contained in:
Ted Liang
2025-12-08 12:55:54 +11:00
committed by GitHub
parent f70b76d8b8
commit dcaecf1fc5
11 changed files with 166 additions and 80 deletions
@@ -12,11 +12,13 @@ export type CreateEmbeddingPresignTokenOptions = {
* In development mode, can be set to 0 to create a token that expires immediately (for testing)
*/
expiresIn?: number;
scope?: string;
};
export const createEmbeddingPresignToken = async ({
apiToken,
expiresIn,
scope,
}: CreateEmbeddingPresignTokenOptions) => {
try {
// Validate the API token
@@ -40,6 +42,7 @@ export const createEmbeddingPresignToken = async ({
const token = await new SignJWT({
aud: String(validatedToken.teamId ?? validatedToken.userId),
sub: String(validatedToken.id),
scope,
})
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt(now.toJSDate())
@@ -7,10 +7,12 @@ import { AppError, AppErrorCode } from '../../errors/app-error';
export type VerifyEmbeddingPresignTokenOptions = {
token: string;
scope?: string;
};
export const verifyEmbeddingPresignToken = async ({
token,
scope,
}: VerifyEmbeddingPresignTokenOptions) => {
// First decode the JWT to get the claims without verification
let decodedToken: JWTPayload;
@@ -81,6 +83,12 @@ export const verifyEmbeddingPresignToken = async ({
});
}
if (decodedToken.scope && scope && decodedToken.scope !== scope) {
throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Presign token scope not matched',
});
}
// Now verify the token with the actual secret
const secret = new TextEncoder().encode(apiToken.token);