@@ -20,6 +20,8 @@ import { isPublicJWT, validatePublicJwtKey } from "./realtime/jwtAuth.server";
2020
2121const ClaimsSchema = z . object ( {
2222 scopes : z . array ( z . string ( ) ) . optional ( ) ,
23+ // One-time use token
24+ otu : z . boolean ( ) . optional ( ) ,
2325} ) ;
2426
2527type Optional < T , K extends keyof T > = Prettify < Omit < T , K > & Partial < Pick < T , K > > > ;
@@ -39,6 +41,7 @@ export type ApiAuthenticationResultSuccess = {
3941 type : "PUBLIC" | "PRIVATE" | "PUBLIC_JWT" ;
4042 environment : AuthenticatedEnvironment ;
4143 scopes ?: string [ ] ;
44+ oneTimeUse ?: boolean ;
4245} ;
4346
4447export type ApiAuthenticationResultFailure = {
@@ -146,6 +149,7 @@ export async function authenticateApiKey(
146149 ...result ,
147150 environment : validationResults . environment ,
148151 scopes : parsedClaims . success ? parsedClaims . data . scopes : [ ] ,
152+ oneTimeUse : parsedClaims . success ? parsedClaims . data . otu : false ,
149153 } ;
150154 }
151155 }
@@ -227,6 +231,7 @@ export async function authenticateApiKeyWithFailure(
227231 ...result ,
228232 environment : validationResults . environment ,
229233 scopes : parsedClaims . success ? parsedClaims . data . scopes : [ ] ,
234+ oneTimeUse : parsedClaims . success ? parsedClaims . data . otu : false ,
230235 } ;
231236 }
232237 }
@@ -531,3 +536,20 @@ function calculateJWTExpiration() {
531536
532537 return ( Date . now ( ) + DEFAULT_JWT_EXPIRATION_IN_MS ) / 1000 ;
533538}
539+
540+ export async function getOneTimeUseToken (
541+ auth : ApiAuthenticationResultSuccess
542+ ) : Promise < string | undefined > {
543+ if ( auth . type !== "PUBLIC_JWT" ) {
544+ return ;
545+ }
546+
547+ if ( ! auth . oneTimeUse ) {
548+ return ;
549+ }
550+
551+ // Hash the API key to make it unique
552+ const hash = await crypto . subtle . digest ( "SHA-256" , new TextEncoder ( ) . encode ( auth . apiKey ) ) ;
553+
554+ return Buffer . from ( hash ) . toString ( "hex" ) ;
555+ }
0 commit comments