Last active
          August 6, 2025 13:25 
        
      - 
      
- 
        Save codebender828/7d506e70a7bd97d77d301c1b303da151 to your computer and use it in GitHub Desktop. 
    Donut Wallet Service Access Token Verification
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | bun run verify-access-token.ts | |
| // ============================ | |
| Token is valid: { | |
| aid: "cmberb48q023yjo0leuwu63tw", | |
| att: "pat", | |
| sid: "cmd4ibkcy000ljz0my8vpmm2d", | |
| iss: "privy.io", | |
| iat: 1753864509, | |
| aud: "https://auth.privy.io", | |
| sub: "did:privy:cmc7kmnba00palf0lmakg3lge", | |
| exp: 1753868109, | |
| } | |
| results { | |
| verifyPrivyTokenResult: { | |
| aid: "cmberb48q023yjo0leuwu63tw", | |
| att: "pat", | |
| sid: "cmd4ibkcy000ljz0my8vpmm2d", | |
| iss: "privy.io", | |
| iat: 1753864509, | |
| aud: "https://auth.privy.io", | |
| sub: "did:privy:cmc7kmnba00palf0lmakg3lge", | |
| exp: 1753868109, | |
| }, | |
| verifyPrivyTokenWithValidationsResult: { | |
| aid: "cmberb48q023yjo0leuwu63tw", | |
| att: "pat", | |
| sid: "cmd4ibkcy000ljz0my8vpmm2d", | |
| iss: "privy.io", | |
| iat: 1753864509, | |
| aud: "https://auth.privy.io", | |
| sub: "did:privy:cmc7kmnba00palf0lmakg3lge", | |
| exp: 1753868109, | |
| }, | |
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | import jwt, { JwtPayload } from "jsonwebtoken"; | |
| const publicKey = `<REPLACE_WITH_PUBLIC_KEY_FROM_PRIVY_DASHBOARD>`; | |
| interface PrivyTokenPayload extends JwtPayload { | |
| sub?: string; // Subject (user ID) | |
| iss?: string; // Issuer | |
| aud?: string | string[]; // Audience | |
| exp?: number; // Expiration time | |
| iat?: number; // Issued at | |
| // You can add other Privy-specific claims as needed | |
| } | |
| function verifyPrivyToken(accessToken: string): PrivyTokenPayload | null { | |
| try { | |
| const decoded = jwt.verify(accessToken, publicKey, { | |
| // NOTe: This is important! Privy uses ES256 for signing | |
| algorithms: ["ES256"], | |
| }) as PrivyTokenPayload; | |
| console.log("Token is valid:", decoded); | |
| return decoded; | |
| } catch (error) { | |
| if (error instanceof Error) { | |
| console.error("Token verification failed:", error.message); | |
| } | |
| return null; | |
| } | |
| } | |
| // With additional validations | |
| function verifyPrivyTokenWithValidations( | |
| accessToken: string, | |
| options?: { | |
| audience?: string; | |
| issuer?: string; | |
| } | |
| ): PrivyTokenPayload | null { | |
| try { | |
| const verifyOptions: jwt.VerifyOptions = { | |
| algorithms: ["ES256"], | |
| ...(options?.audience && { audience: options.audience }), | |
| ...(options?.issuer && { issuer: options.issuer }), | |
| }; | |
| const decoded = jwt.verify( | |
| accessToken, | |
| publicKey, | |
| verifyOptions | |
| ) as PrivyTokenPayload; | |
| if (!decoded.sub) { | |
| throw new Error("Token missing subject (user ID)"); | |
| } | |
| return decoded; | |
| } catch (error) { | |
| if (error instanceof jwt.TokenExpiredError) { | |
| console.error("Token has expired"); | |
| } else if (error instanceof jwt.JsonWebTokenError) { | |
| console.error("Invalid token:", error.message); | |
| } else if (error instanceof Error) { | |
| console.error("Token verification failed:", error.message); | |
| } | |
| return null; | |
| } | |
| } | |
| // PLEASE REPLACE WUTH YOUR ACCESS TOKEN IN PRODUCTION | |
| const ACCESS_TOKEN = `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlZwVzdkYmtra1RpTWpWWV9xOFB6Sjd5ZkZ6blVGdWhjaWJLUEFhU3FoM1kifQ.eyJhaWQiOiJjbWJlcmI0OHEwMjN5am8wbGV1d3U2M3R3IiwiYXR0IjoicGF0Iiwic2lkIjoiY21kNGlia2N5MDAwbGp6MG15OHZwbW0yZCIsImlzcyI6InByaXZ5LmlvIiwiaWF0IjoxNzUzODY0NTA5LCJhdWQiOiJodHRwczovL2F1dGgucHJpdnkuaW8iLCJzdWIiOiJkaWQ6cHJpdnk6Y21jN2ttbmJhMDBwYWxmMGxtYWtnM2xnZSIsImV4cCI6MTc1Mzg2ODEwOX0.C68Apx09WrjBf4gwrXpz7P3rI3kRdSmIKsnSPY7yHr9Ekas7bhRMQoBTn00jp64hEfyE8NIZO3P1rIlenhWmhw`; | |
| const verifyPrivyTokenResult = verifyPrivyToken(ACCESS_TOKEN); | |
| const verifyPrivyTokenWithValidationsResult = | |
| verifyPrivyTokenWithValidations(ACCESS_TOKEN); | |
| console.log("results", { | |
| verifyPrivyTokenResult, | |
| verifyPrivyTokenWithValidationsResult, | |
| }); | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment