Category: Expert Guide

How does a JWT decoder verify a token?

Absolutely! Here's a comprehensive guide on JWT token verification using `jwt-decoder`, designed to be authoritative and SEO-friendly. --- Ultimate Authoritative Guide: JWT Token Verification with jwt-decoder

The Ultimate Authoritative Guide: How a JWT Decoder Verifies a Token

Focus Tool: jwt-decoder

Audience: Cloud Solutions Architects, Security Engineers, Backend Developers

Date: October 26, 2023

Executive Summary

In the modern, distributed, and API-driven landscape of cloud computing, secure and efficient authentication and authorization mechanisms are paramount. JSON Web Tokens (JWTs) have emerged as a de facto standard for securely transmitting information between parties as a JSON object. This guide provides an in-depth exploration of how a JWT decoder verifies a token, with a specific focus on the practical application and capabilities of the jwt-decoder tool. We will dissect the intricate process of signature validation, the critical role of cryptographic keys, and the various algorithms employed. Furthermore, we will contextualize this understanding through practical scenarios, global industry standards, a multi-language code vault, and a forward-looking perspective on future trends in JWT security. For Cloud Solutions Architects, a thorough grasp of JWT verification is indispensable for designing robust, scalable, and secure cloud-native applications.

Deep Technical Analysis: The Mechanics of JWT Verification

A JWT is composed of three parts, separated by dots (.): a Header, a Payload, and a Signature. Each part is a Base64Url encoded JSON object. The magic of JWT security lies not in encrypting the token's content (though encryption is possible with JWE), but in its verifiable signature. The verification process is a multi-step cryptographic operation designed to ensure the token's integrity and authenticity.

1. Token Structure and Decoding

Before verification can even begin, the JWT needs to be parsed. The structure is typically:

[Base64UrlEncodedHeader].[Base64UrlEncodedPayload].[Base64UrlEncodedSignature]

A JWT decoder will first split the token at the dots. Each segment is then Base64Url decoded to reveal the underlying JSON objects for the header and payload.

  • Header: Contains metadata about the token, most importantly the signing algorithm used (alg) and the token type (typ, usually "JWT").
  • Payload: Contains the "claims," which are statements about an entity (typically the user) and additional data. Standard claims include iss (issuer), exp (expiration time), sub (subject), aud (audience), etc. Custom claims can also be included.
  • Signature: This is the crucial component for verification. It's generated by taking the encoded header, the encoded payload, a secret or private key, and applying the algorithm specified in the header.

2. The Role of the Signature

The signature serves two primary purposes:

  • Integrity: It ensures that the token has not been tampered with since it was issued. If any part of the header or payload is altered, the generated signature will not match the received signature.
  • Authenticity: It verifies that the token was issued by a trusted party (the issuer). This is achieved through cryptographic signing using a key that only the issuer possesses.

3. The Verification Process: A Step-by-Step Breakdown

When a server (or a dedicated JWT decoder service) receives a JWT, it performs the following verification steps:

3.1. Header Parsing and Algorithm Identification

The decoder first Base64Url decodes the header. It then inspects the alg parameter to determine which cryptographic algorithm was used to sign the token. This is a critical step as it dictates the subsequent verification procedure. Common algorithms include:

  • HMAC (e.g., HS256, HS384, HS512): Symmetric algorithms that use a single secret key for both signing and verification. The same key is shared between the issuer and the verifier.
  • RSA (e.g., RS256, RS384, RS512): Asymmetric algorithms that use a pair of keys: a private key for signing and a public key for verification. The issuer keeps the private key secret, and the verifier uses the publicly available key.
  • ECDSA (e.g., ES256, ES384, ES512): Elliptic Curve Digital Signature Algorithm, another asymmetric approach that offers smaller key sizes for equivalent security compared to RSA.

The jwt-decoder tool, when used, will often infer the algorithm from the header or allow you to specify it.

3.2. Reconstructing the Signed Data

The decoder then reconstructs the data that was originally signed. This is precisely the Base64Url encoded header concatenated with a dot (.) and the Base64Url encoded payload.

signed_data = encoded_header + "." + encoded_payload

3.3. Signature Validation using the Appropriate Key

This is the core of the verification process. The decoder uses the algorithm identified in the header and a corresponding key to validate the token's signature.

3.3.1. Symmetric Key Verification (HMAC)

If the algorithm is HMAC (e.g., HS256), the decoder needs the shared secret key. The verification process is as follows:

  1. The decoder takes the signed_data (encoded header + "." + encoded payload).
  2. It applies the same HMAC algorithm (e.g., SHA-256 for HS256) to the signed_data using the shared secret key.
  3. This generates a new signature.
  4. The decoder then compares this newly generated signature with the signature part of the received JWT (the third Base64Url encoded segment).
  5. If they match, the signature is valid, proving integrity and authenticity.

Security Note: For HMAC to be secure, the shared secret key must be kept highly confidential. Compromise of this key allows an attacker to forge any JWT.

3.3.2. Asymmetric Key Verification (RSA/ECDSA)

If the algorithm is asymmetric (e.g., RS256 or ES256), the decoder needs the issuer's public key.

  1. The decoder takes the signed_data (encoded header + "." + encoded payload).
  2. It applies the specified asymmetric verification algorithm (e.g., RSASSA-PKCS1-v1_5 with SHA-256 for RS256) to the signed_data using the issuer's public key.
  3. This process "verifies" the signature against the data and the public key.
  4. If the verification is successful, it means the signature was created using the corresponding private key.

Key Management: The public key used for verification is typically obtained from a trusted source, such as a JWKS (JSON Web Key Set) endpoint provided by the issuer. This ensures that the verifier is using the legitimate public key associated with the issuer.

3.4. Claim Validation

Once the signature is verified, the decoder proceeds to validate the claims within the payload. This involves several checks:

  • Expiration Time (exp): The decoder checks if the current time is before the expiration time specified in the exp claim. If the token has expired, it's considered invalid.
  • Not Before Time (nbf): If present, the decoder checks if the current time is after the "not before" time. If not, the token is not yet valid.
  • Audience (aud): The decoder checks if the token is intended for the audience (the recipient) of the token. The aud claim can be a string or an array of strings.
  • Issuer (iss): The decoder may verify that the issuer specified in the iss claim is a trusted entity.
  • Subject (sub): This identifies the principal that is the subject of the token.
  • Other Claims: Any custom claims relevant to the application's authorization logic are also inspected.

4. The jwt-decoder Tool in Action

The jwt-decoder tool (whether it's a command-line utility, a library function, or an online service) automates these steps. When you input a JWT into jwt-decoder, it performs the following:

  • Parses the token: Splits it into header, payload, and signature.
  • Decodes header and payload: Converts them from Base64Url to JSON.
  • Identifies the algorithm: Reads the alg from the header.
  • Requests or uses a key: You typically provide the necessary public key (for asymmetric) or secret key (for symmetric) to the jwt-decoder.
  • Performs cryptographic verification: Reconstructs the signed data and uses the provided key and algorithm to validate the signature.
  • Validates claims: Checks exp, nbf, aud, etc.
  • Reports the result: Indicates whether the token is valid and often displays the decoded header and payload.

For a Cloud Solutions Architect, understanding that jwt-decoder is not just a display tool but a robust verifier is crucial. It encapsulates the entire cryptographic and logical validation process.

5. Common Pitfalls and Security Considerations

  • Algorithm Confusion (alg: "none"): An attacker might try to remove the signature or set the algorithm to "none". The decoder must explicitly reject tokens with "none" unless specifically configured for a very niche, insecure scenario.
  • Key Management Issues:
    • Using weak or compromised secrets for HMAC.
    • Exposing private keys for asymmetric signing.
    • Using the wrong public key for verification.
    • Not rotating keys periodically.
  • Clock Skew: Differences in system clocks between the issuer and verifier can lead to valid tokens being rejected (if the verifier's clock is ahead) or expired tokens being accepted (if the verifier's clock is behind). Implement NTP synchronization.
  • Ignoring Expiration: Failing to check the exp claim leaves the system vulnerable to using stale tokens.
  • Trusting the Payload Unconditionally: The payload's data is only trusted *after* the signature has been verified.
  • Replay Attacks: While JWTs themselves don't inherently prevent replay attacks, mechanisms like the jti (JWT ID) claim, combined with a server-side blacklist or tracking of issued tokens, can mitigate this.

5+ Practical Scenarios for JWT Verification with jwt-decoder

Understanding the theoretical underpinnings is one thing; applying them in real-world cloud architectures is another. The jwt-decoder tool is invaluable for debugging, testing, and understanding these scenarios.

Scenario 1: API Gateway Authentication

Problem: A microservices architecture where an API Gateway needs to authenticate incoming requests before forwarding them to downstream services. Solution: The API Gateway receives a JWT in the Authorization: Bearer [token] header. It uses a jwt-decoder (integrated as middleware or a library) to verify the token. The key for verification (public key of the identity provider or signing service) is pre-configured or fetched from a JWKS endpoint. If the token is valid, the Gateway can extract user claims (e.g., `sub`, `roles`) and pass them along to the microservices, which may perform their own granular authorization based on these claims. jwt-decoder Role: Debugging invalid tokens, verifying the signature and claims of a valid token to ensure it's correctly processed.

Scenario 2: Single Sign-On (SSO) with OpenID Connect (OIDC)

Problem: Users authenticate with an Identity Provider (IdP) and should be able to access multiple relying party applications without re-authenticating. Solution: After successful authentication at the IdP, the IdP issues an ID Token (a JWT) and potentially an Access Token. The relying party application receives the ID Token. It uses its configured jwt-decoder with the IdP's public keys (from its JWKS endpoint) to verify the ID Token's signature and validate claims like iss (must match the IdP) and aud (must match the relying party). This confirms the user's identity and attributes. jwt-decoder Role: Verifying the authenticity and integrity of the ID Token, ensuring it originates from the correct IdP and hasn't been tampered with.

Scenario 3: Serverless Function Authorization

Problem: A serverless function (e.g., AWS Lambda, Azure Functions) needs to ensure that only authorized users or services can invoke it. Solution: An API Gateway or another service invokes the serverless function, passing a JWT. The serverless function's code includes a JWT verification library (effectively a jwt-decoder). The function retrieves the necessary public key (e.g., from AWS Secrets Manager, Azure Key Vault, or a public endpoint) and verifies the token. If valid, the function proceeds with its logic; otherwise, it returns an authorization error. jwt-decoder Role: Embedded within the function's runtime to perform on-the-fly verification, ensuring the function is only executed by legitimate requests.

Scenario 4: Client-Side Token Inspection (for Debugging)

Problem: A frontend developer needs to understand the contents of a JWT received from the backend for debugging purposes. Solution: The developer can copy the JWT and paste it into an online jwt-decoder tool or use a local command-line jwt-decoder. This allows them to see the decoded header and payload, inspect the claims, and understand what data is being transmitted. Note: This is for inspection, not for performing cryptographic verification on the client-side for security-critical operations, as the necessary private keys are never exposed to the client. jwt-decoder Role: Visualizing token contents, aiding in debugging front-end interactions with authentication systems.

Scenario 5: Microservice-to-Microservice Communication (Service-to-Service Auth)

Problem: Two microservices need to communicate securely, and the calling service needs to prove its identity or authorization to the called service. Solution: The calling service obtains a JWT (e.g., from an OAuth 2.0 token endpoint or an internal identity service). It includes this JWT in the request to the called service. The called service, acting as a verifier, uses a jwt-decoder with the appropriate public key (or shared secret) to validate the token. This confirms that the request originates from a trusted service. jwt-decoder Role: Enabling secure, authenticated communication between internal services in a distributed system.

Scenario 6: Offline Token Validation in a Federated Identity System

Problem: A system needs to validate tokens issued by a trusted external identity provider without direct real-time communication with the IdP for every validation. Solution: The system periodically fetches the public keys of the trusted IdP from its JWKS endpoint and caches them. When a JWT arrives, the system's jwt-decoder uses the cached public key corresponding to the kid (key ID) in the token's header to perform signature verification. This allows for fast, stateless verification. jwt-decoder Role: Facilitating efficient, offline verification of tokens issued by trusted third parties.

Global Industry Standards Governing JWTs

The security and interoperability of JWTs are underpinned by several key industry standards, primarily managed by the Internet Engineering Task Force (IETF). Understanding these ensures that implementations are robust and compliant.

1. RFC 7519: JSON Web Token (JWT)

This is the foundational specification for JWTs. It defines:

  • The compact serialization format (header.payload.signature).
  • The structure of the header and payload (JSON objects).
  • Registered claims names (iss, exp, sub, etc.).
  • The general concept of signing and verification.

2. RFC 7518: JSON Web Key (JWK)

This RFC specifies a JSON-based data structure (JWK) for representing cryptographic keys. JWKs are essential for:

  • Representing public keys used for asymmetric verification.
  • Allowing for key identification (e.g., using kid).
  • Facilitating the secure exchange of keys.

3. RFC 7517: JSON Web Key (JWK) Set

This RFC defines the JWK Set (jwks), which is a JSON structure that contains an array of JWKs. This is the standard format for exposing public keys at a discoverable URL, commonly used by OAuth 2.0 and OpenID Connect providers.

4. RFC 7515: JSON Web Signature (JWS)

This RFC specifies the JWS structure, which is the basis for JWT signatures. It defines how to represent a signed JSON object (including the header and payload) and its signature. JWTs use the compact serialization of JWS.

5. RFC 7516: JSON Web Encryption (JWE)

While JWTs are primarily about signed information, JWE defines how to encrypt JSON objects, allowing for confidentiality. A JWE can contain claims that are protected from unauthorized disclosure.

6. RFC 7516: JSON Web Algorithms (JWA)

This RFC specifies the cryptographic algorithms that can be used with JWS and JWE, such as HMAC SHA-256 (HS256), RSA SHA-256 (RS256), and ECDSA P-256 SHA-256 (ES256). The alg parameter in the JWT header references algorithms defined here.

7. OAuth 2.0 and OpenID Connect Specifications

While not directly defining JWT *verification*, these protocols heavily rely on JWTs for ID Tokens and Access Tokens. Their specifications dictate how JWTs are issued, exchanged, and what claims are expected for authentication and authorization purposes. For example, OpenID Connect defines standard claims for user identity.

The jwt-decoder tool, when properly implemented or configured, adheres to these standards, ensuring that it can correctly parse, verify, and validate JWTs generated according to these specifications.

Multi-language Code Vault: Implementing JWT Verification

As Cloud Solutions Architects, we often work with diverse technology stacks. The implementation of JWT verification, leveraging libraries that act as jwt-decoders, is common across many languages. Here are snippets demonstrating how to verify a JWT.

Example 1: Python (using PyJWT)

This example demonstrates verifying an HMAC-signed JWT.


import jwt
from datetime import datetime, timedelta, timezone

# --- Configuration ---
# In a real-world scenario, this secret would be securely stored and retrieved.
JWT_SECRET = "your-super-secret-key"
JWT_ALGORITHM = "HS256"

# --- Token to verify (example) ---
# This token would be received from a client or another service.
# For demonstration, we'll create one first.
payload = {
    "sub": "1234567890",
    "name": "John Doe",
    "iat": datetime.now(timezone.utc),
    "exp": datetime.now(timezone.utc) + timedelta(minutes=30)
}
encoded_jwt = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
print(f"Generated JWT: {encoded_jwt}\n")

# --- Verification ---
try:
    # The jwt.decode function acts as our jwt-decoder
    decoded_payload = jwt.decode(
        encoded_jwt,
        JWT_SECRET,
        algorithms=[JWT_ALGORITHM],
        options={"verify_signature": True, "verify_exp": True, "verify_iat": True}
    )
    print("JWT Verification Successful!")
    print("Decoded Payload:")
    print(decoded_payload)
except jwt.ExpiredSignatureError:
    print("JWT Verification Failed: Token has expired.")
except jwt.InvalidSignatureError:
    print("JWT Verification Failed: Invalid signature.")
except jwt.InvalidTokenError as e:
    print(f"JWT Verification Failed: {e}")
        

Example 2: Node.js (using `jsonwebtoken`)

This example verifies an RSA-signed JWT. We'll assume the public key is available.


const jwt = require('jsonwebtoken');
const fs = require('fs'); // For reading keys from files

// --- Configuration ---
// In a real-world scenario, these keys would be securely managed.
// For RSA, you need the public key for verification.
const PUBLIC_KEY = fs.readFileSync('path/to/your/public.pem'); // Load your public key
const JWT_ALGORITHM = "RS256";

// --- Token to verify (example) ---
// Let's simulate a signed token for demonstration.
// In a real app, you'd receive this token.
const originalPayload = {
    sub: "user123",
    name: "Jane Smith",
    iat: Math.floor(Date.now() / 1000), // Issued at
    exp: Math.floor(Date.now() / 1000) + (60 * 30) // Expiration in 30 minutes
};
// To generate a token for testing, you'd need the private key.
// For this example, we assume 'signedToken' is a valid JWT received.
// const signedToken = jwt.sign(originalPayload, PRIVATE_KEY, { algorithm: JWT_ALGORITHM });

const signedToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzg5MDIyfQ.SflKxwRJSMeKK984IL_q3i2Zg9-A0rLgq0G8a6u1h3i8o3j4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0g4g0