Security

    JWT alg:none and algorithm-confusion attacks

    A 2026 view of JWT forgery via alg none and RS256-to-HS256 algorithm confusion, contrasted with a server that pins the expected algorithm and key and verifies claims

    A JSON Web Token carries a header that names the algorithm used to sign it, and that small detail is the root of two classic forgery attacks. If your backend trusts the algorithm the token declares, an attacker can set it to "none" and strip the signature, or switch an asymmetric algorithm to a symmetric one and sign with your public key. Both produce a token your server happily accepts as valid, letting the attacker impersonate any user. The fix is the same idea in both cases: never let the token tell you how to verify it. Here is how these JWT verification attacks work and how to validate tokens safely on your mobile app's backend.

    Short answer

    JWT forgery attacks exploit a backend that trusts the algorithm declared in the token's header. Per OWASP, the two classic cases are the alg: none attack, where an attacker sets the algorithm to none and removes the signature, and the server accepts the unsigned token; and algorithm confusion, where an attacker switches an asymmetric algorithm like RS256 to a symmetric one like HS256 and signs the token using your public key as the HMAC secret, which the server then verifies with that same public key. Both let an attacker forge tokens. The defense is to specify and enforce the expected algorithm and key on the server, never trusting the token's alg header, reject none, verify the signature, and validate the claims.

    What you should know

    • The JWT header declares the algorithm: trusting it is the root flaw.
    • alg: none forges unsigned tokens: if the server accepts no signature.
    • Algorithm confusion swaps RS256 for HS256: signing with the public key.
    • The fix is to pin the algorithm server-side: do not trust the header.
    • Verify the signature and validate claims: signature, expiry, issuer, audience.

    How is JWT verification attacked?

    By exploiting how the server decides to verify a token. The table lists the main attacks.

    AttackHow it works
    alg: noneSet algorithm to none, remove the signature; server accepts it
    Algorithm confusionSwitch RS256 to HS256, sign with the public key
    No signature verificationThe server decodes but never verifies
    Weak HMAC secretA short or guessable secret is brute-forced
    Missing claim checksExpiry, issuer, or audience not validated

    The unifying theme is that JWT attacks target verification, not the token format itself. The most direct is alg: none: the standard defines an option for an unsigned token, and if the server honors a token that declares none and has no signature, an attacker can craft any payload and have it accepted. Algorithm confusion is subtler, switching the declared algorithm from asymmetric to symmetric to abuse how the verification key is used. Beyond these, some backends decode a JWT without actually verifying its signature, which accepts anything, and others use an HMAC secret weak enough to brute-force, or fail to check claims like expiry, issuer, and audience, so an expired or misdirected token is accepted. Each is a server-side verification gap, which is where JWT security lives.

    How do alg:none and algorithm confusion work?

    Both come from the server trusting the token's declared algorithm. In the alg: none attack, the JWT header says the algorithm is none, meaning unsigned, and the token carries no signature; if the verification code accepts that, perhaps because it reads the algorithm from the header and dispatches accordingly, then a token with an attacker-chosen payload and no signature is treated as authentic, so the attacker forges whatever they want. Algorithm confusion exploits the difference between asymmetric and symmetric signing. With an asymmetric algorithm like RS256, the server signs with a private key and verifies with a public key, and that public key is, by design, public. If the server's verification picks the algorithm from the token header, an attacker can change the header to a symmetric algorithm like HS256, which verifies by recomputing an HMAC with a shared secret, and sign their forged token using the public key as that secret. Because the server then verifies HS256 using the public key it holds, the very key that is not supposed to be secret, the forged token validates. In both attacks, the flaw is that the token was allowed to dictate how it would be verified.

    How do you verify JWTs safely?

    Decide the algorithm and key on the server, and verify everything. The core rule is to never trust the alg header: configure your verification to expect a specific algorithm, or a fixed allowlist, and the corresponding key, and reject any token that does not match, rather than letting the token's header select the verification method. This single discipline closes both alg: none, since none is simply not an accepted algorithm, and algorithm confusion, since the server will only ever verify with the algorithm and key you pinned. Always verify the signature, never merely decode the token, and use a well-maintained JWT library configured to enforce the expected algorithm rather than one that infers it from the header. Use strong keys: a long, random HMAC secret for symmetric algorithms so it cannot be brute-forced, and proper key management for asymmetric keys. And validate the claims, not just the signature: check expiry, issuer, and audience, so an expired, foreign, or misdirected token is rejected. Keep all of this on the server, since the app is one client and an attacker submits tokens directly. The principle is that the server, not the token, decides the algorithm and key, and the server verifies the signature and the claims before trusting anything inside.

    What to watch out for

    The first trap is verification code that reads the algorithm from the token header and dispatches on it, which enables both alg: none and algorithm confusion; pin the algorithm and key server-side. The second is decoding a JWT without verifying its signature, or using a weak HMAC secret. The third is checking the signature but not the claims, accepting expired or misdirected tokens. JWT verification is server-side, so a pre-submission scan such as PTKD.com (https://ptkd.com), which reads the binary against OWASP MASVS, surfaces how your app handles authentication and tokens as the surface to protect, while the verification logic, pinning the algorithm and validating claims, is yours to implement on the backend.

    What to take away

    • JWT forgery attacks exploit a backend that trusts the algorithm in the token header: alg: none strips the signature, and algorithm confusion switches RS256 to HS256 and signs with the public key.
    • Both, plus skipped signature verification, weak secrets, and missing claim checks, are server-side verification gaps that let an attacker forge tokens and impersonate users.
    • Verify safely by pinning the expected algorithm and key server-side, never trusting the alg header, verifying the signature, using strong keys, and validating expiry, issuer, and audience.
    • JWT verification is server-side; use a pre-submission scan such as PTKD.com to surface your app's authentication and token handling, and enforce strict verification on the backend.
    • #jwt
    • #authentication
    • #algorithm-confusion
    • #api-security
    • #token-forgery
    • #owasp
    • #mobile

    Frequently asked questions

    What is the JWT alg:none attack?
    It exploits the JWT option for an unsigned token. A JWT header declares its signing algorithm, and the standard defines none, meaning unsigned. In the attack, an attacker sets the header algorithm to none and removes the signature, and if the server's verification honors that, treating a token that declares none and carries no signature as authentic, then a token with an attacker-chosen payload is accepted. The attacker can forge any claims they want. The fix is to never accept none as a valid algorithm: pin the expected algorithm server-side so an unsigned token is rejected.
    How does JWT algorithm confusion work?
    It abuses the difference between asymmetric and symmetric signing. With RS256, the server signs with a private key and verifies with a public key, which is public by design. If the server picks the algorithm from the token header, an attacker changes it to HS256, a symmetric algorithm that verifies by recomputing an HMAC with a shared secret, and signs their forged token using the public key as that secret. The server then verifies HS256 using the public key it holds, the key that is not meant to be secret, so the forged token validates. The flaw is letting the token dictate the algorithm.
    Why is trusting the alg header dangerous?
    Because it lets the token decide how it will be verified, which is exactly what an attacker controls. If verification reads the algorithm from the header and dispatches on it, an attacker can choose none to skip signature checking, or switch an asymmetric algorithm to a symmetric one to abuse the verification key. Both forge valid-looking tokens. The header is attacker-controlled input, so it must not drive verification. The server should decide the expected algorithm and key in advance and reject anything that does not match, regardless of what the token's header claims.
    How do I verify JWTs safely?
    Pin the algorithm and key on the server and verify everything. Configure verification to expect a specific algorithm or a fixed allowlist and the corresponding key, rejecting tokens that do not match, which closes both alg none and algorithm confusion. Always verify the signature rather than merely decoding, use a well-maintained library configured to enforce the expected algorithm, and use strong keys, a long random HMAC secret or properly managed asymmetric keys. Then validate the claims, expiry, issuer, and audience, so an expired or misdirected token is rejected, all enforced server-side.
    Can a scan detect JWT verification flaws?
    JWT verification happens on your backend, so the flaws, trusting the alg header, skipping signature verification, weak secrets, or missing claim checks, are fixed in server code. A pre-submission scan such as PTKD.com reads the binary against OWASP MASVS and surfaces how your app handles authentication and tokens, which identifies the authentication surface to protect. The verification logic itself, pinning the expected algorithm and key, verifying the signature, and validating claims, is implemented and enforced on the server, since an attacker can submit crafted tokens to your API directly.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free