Oslo JWT (@oslojs/jwt)

repository·main·Indexed 41 days ago

https://github.com/oslo-project/jwt

A runtime-agnostic, dependency-free, and fully typed JavaScript library for parsing and encoding signed JSON Web Tokens (JWT). Version 0.3.0 provides tools for decomposing tokens via parseJWT(), creating tokens with encodeJWT(), and validating registered headers and claims using the JWSRegisteredHeaders and JWTRegisteredClaims classes.

Tokens
8.2K
Snippets
58
Records
64
Agent score
50%

What's inside Oslo JWT

  1. Verify JWT tokens manually using parseJWT()

    main

    To verify a JSON Web Token (JWT), use parseJWT() to decompose the token into its constituent parts: header, payload, signature, and signatureMessage.

    Follow these steps for a complete verification flow:

    1. Parse the components: Use parseJWT(jwt).
    2. Validate the Header: Use JWSRegisteredHeaders to inspect the header parameters (e.g., checking if the algorithm is supported).
    3. Verify the Signature: Use the Web Crypto API (crypto.subtle.verify) with the extracted signature and signatureMessage to ensure the token hasn't been tampered with.
    4. Validate Claims: Use JWTRegisteredClaims to parse the payload and check temporal constraints like expiration (verifyExpiration()) and the 'not before' (verifyNotBefore()) claim.
    import { parseJWT, JWSRegisteredHeaders, JWTRegisteredClaims } from "@oslojs/jwt";
    
    const [header, payload, signature, signatureMessage] = parseJWT(jwt);
    
    // 1. Validate Header
    const headerParameters = new JWSRegisteredHeaders(header);
    if (headerParameters.algorithm() !== joseAlgorithmHS256) {
    	throw new Error("Unsupported algorithm");
    }
    
    // 2. Verify Signature
    const validSignature = await crypto.subtle.verify("HMAC", key, signature, signatureMessage);
    if (!validSignature) {
    	throw new Error("Invalid signature");
    }
    
    // 3. Validate Claims
    const claims = new JWTRegisteredClaims(payload);
    if (claims.hasExpiration() && !claims.verifyExpiration()) {
    	throw new Error("Expired token");
    }
    if (claims.hasNotBefore() && !claims.verifyNotBefore()) {
    	throw new Error("Invalid token");
    }
  2. Create tokens with encodeJWT()

    main

    To create a JSON Web Token (JWT), use the encodeJWT() function. This function requires three arguments: a stringified header object, a stringified payload object, and a Uint8Array containing the signature.

    Before calling encodeJWT(), you must:

    1. Prepare a JSON header (e.g., specifying the algorithm using joseAlgorithmHS256).
    2. Prepare a JSON payload (e.g., setting an expiration exp or custom claims).
    3. Generate a signature using a cryptographic method (like crypto.subtle.sign) and the createJWTSignatureMessage() helper to combine the header and payload for signing.
    import { joseAlgorithmHS256, createJWTSignatureMessage, encodeJWT } from "@oslojs/jwt";
    
    const headerJSON = JSON.stringify({
    	alg: joseAlgorithmHS256,
    	typ: "JWT"
    });
    const payloadJSON = JSON.stringify({
    	exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30,
    	name: "John Doe"
    });
    const signatureBuffer = await crypto.subtle.sign("HMAC", key, createJWTSignatureMessage(headerJSON, payloadJSON));
    const jwt = encodeJWT(headerJSON, payloadJSON, new Uint8Array(signatureBuffer));
  3. Parse and verify a JWT

    main

    Use parseJWT to decompose a token into its header, payload, and signature. To validate the token, use JWSRegisteredHeaders to inspect the algorithm and JWTRegisteredClaims to verify claims like expiration (exp) and not-before (nbf).

    Note: This library only supports signed tokens.

    import { parseJWT, JWSRegisteredHeaders, JWTRegisteredClaims, joseAlgorithmHS256 } from "@oslojs/jwt";
    
    const [header, payload, signature] = parseJWT(jwt);
    const headerParameters = new JWSRegisteredHeaders(header);
    if (headerParameters.algorithm() !== joseAlgorithmHS256) {
    	throw new Error("Unsupported algorithm");
    }
    const claims = new JWTRegisteredClaims(payload);
    if (!claims.verifyExpiration()) {
    	throw new Error("Expired token");
    }
    if (claims.hasNotBefore() && !claims.verifyNotBefore()) {
    	throw new Error("Invalid token");
    }
  4. Check for the x5u parameter with JWSRegisteredHeaders.hasX509URL()

    main

    Use JWSRegisteredHeaders.hasX509URL() to determine if the x5u (X.509 Certificate URL) parameter is present in the JWT headers.

    Note: This method only checks for the existence of the parameter; it does not validate whether the value provided in the x5u field is a valid URL or a valid certificate.

    function hasX509URL(): boolean;
  5. Decode a JWT payload with decodeJWT()

    main

    Use decodeJWT() to parse a JSON Web Token (JWT) and return its payload as an object.

    Warning: This function is strictly for parsing. It does not verify the signature, check if the header is well-formed, or validate any claims (such as exp for expiration). Use this only when you need to inspect the contents of a token without performing security verification.

    function decodeJWT(jwt: string): object;
  6. Use JWTRegisteredClaims.notBefore() to retrieve the 'nbf' claim

    main

    The notBefore() method on a JWTRegisteredClaims object returns the value of the nbf (Not Before) parameter as a standard JavaScript Date object. This claim identifies the time before which the JWT must not be accepted for processing.

    Error Conditions:

    • Throws an Error if the nbf parameter is missing from the claims.
    • Throws an Error if the nbf value is not a positive integer.
    function notBefore(): Date;
  7. Use JWSRegisteredHeaders.x509CertificateSHA1Thumbprint() to get the x5t parameter

    main

    The x509CertificateSHA1Thumbprint() method returns the value of the x5t (X.509 Certificate SHA-1 Thumbprint) registered header parameter as a Uint8Array.

    Error Conditions:

    • Throws an Error if the x5t parameter is missing from the JWT header.
    • Throws an Error if the x5t parameter value is not a valid base64url encoded string.
    function x509CertificateSHA1Thumbprint(): Uint8Array;
  8. Use JWTRegisteredClaims.expiration() to get the expiration date

    main

    The expiration() method on a JWTRegisteredClaims object retrieves the value of the exp (expiration time) claim and converts it into a standard JavaScript Date object.

    Important constraints:

    • The method will throw an Error if the exp parameter is missing from the claims.
    • The method will throw an Error if the exp value is not a positive integer.
    function expiration(): Date;
  9. Check for the presence of the 'alg' parameter with JWSRegisteredHeaders.hasAlgorithm()

    main

    Use the hasAlgorithm() method on a JWSRegisteredHeaders instance to determine if the alg (algorithm) parameter is present in the JWT registered headers.

    Important: This method only checks for the existence of the key. It does not validate whether the value assigned to the alg parameter is a valid or supported algorithm.

    function hasAlgorithm(): boolean;
  10. Use JWSRegisteredHeaders.critical() to retrieve critical header parameters

    main

    The critical() method returns the value of the crit parameter from the JWT registered headers. This parameter is used to indicate that certain header parameters must be understood by the implementation, or the JWT must be rejected.

    Behavior:

    • Returns an array of strings (string[]).
    • Throws an Error if:
      • The crit parameter does not exist.
      • The value is not an array of strings.
      • The value is an empty array.
    function critical(): string[];