JWT vs JWS vs JWE: What's the Difference?
A JWS (signed JWT) has 3 parts; a JWE (encrypted JWT) has 5. Learn what each JOSE acronym means, when a token is signed vs encrypted, and which you need.
Spend enough time around tokens and the acronyms start blurring together: JWT, JWS, JWE, plus JOSE and JWK for good measure, all tossed around as if they're interchangeable. They're related, but they are not the same thing. Confusing them leads to genuine security mistakes. The most common one is assuming a token is encrypted when it's only signed. Here is how the whole family fits together.
The big picture: JOSE
All of these acronyms live under one umbrella spec called JOSE, short for JavaScript Object Signing and Encryption. JOSE defines how to represent claims securely, and its main members are:
- JWT — JSON Web Token, the container, defined in RFC 7519
- JWS — JSON Web Signature, a signed token, defined in RFC 7515
- JWE — JSON Web Encryption, an encrypted token, defined in RFC 7516
- JWK — JSON Web Key, a key format, defined in RFC 7517
- JWA — JSON Web Algorithms, the algorithms used
Here is the one idea that organizes everything else. JWT is the format, while JWS and JWE describe what you do to it. In practice a JWT is almost always either a JWS (signed) or a JWE (encrypted). RFC 7519 puts it plainly: if the header is for a JWS, "the JWT is represented as a JWS," and if it is for a JWE, "the JWT is represented as a JWE."
JWT: the container
A JWT is a compact way to represent claims — facts about a user or session, like "this user is alice" or "this token expires at 3pm." On its own, the word "JWT" just describes the structure: a set of JSON claims encoded for transport.
A raw, unprotected JWT would be useless for security, because anyone could forge one. So in the real world every JWT gets secured with either JWS or JWE.
And when people say "JWT," they almost always mean a JWS, a signed JWT, because that's by far the most common form. The JWT Decoder handles the signed form you'll see in the overwhelming majority of applications.
JWS: signed (the common case)
JWS stands for JSON Web Signature, and this is the token you see everywhere: three Base64URL parts joined by dots. RFC 7515 spells out the exact layout as BASE64URL(Header) || '.' || BASE64URL(Payload) || '.' || BASE64URL(Signature).
header.payload.signature
A JWS is signed but not encrypted, and that one distinction is what trips everyone up:
- ✅ Tamper-proof — the signature proves the token wasn't modified
- ✅ Authentic — it proves who issued the token
- ❌ Not private — anyone can read the payload by Base64URL-decoding it
That last point is the one developers miss, so it's worth saying plainly: a signed JWT is readable by anyone. The payload, meaning the user ID, email, roles, and expiration, sits in plain sight. The signature only guarantees nobody changed it. It does nothing to hide it.
Decode any JWS payload yourself with the JWT Decoder and you'll see the claims as plain JSON, no key required. (For the decoding mechanics in detail, see how to decode JWT in JavaScript.)
When should you reach for JWS? Authentication and authorization where the claims aren't secret. The user's ID and roles being visible is fine, since they already know who they are. That covers the overwhelming majority of API auth. If you want a breakdown of what those visible fields actually mean, see JWT claims explained.
JWE: encrypted (the rare case)
JWE stands for JSON Web Encryption, and a JWE has five Base64URL parts instead of three. RFC 7516 defines the five segments as protected header, encrypted key, initialization vector, ciphertext, and authentication tag:
header.encrypted_key.iv.ciphertext.authentication_tag
A JWE is genuinely encrypted, so the payload is actually hidden. You can't read it without the decryption key. That buys you:
- ✅ Confidentiality — nobody reads the claims without the key
- ✅ Integrity — tampering is detectable
- ✅ Authenticity — depending on the algorithm
Use JWE when the claims themselves are sensitive: medical data, internal identifiers you don't want exposed, anything that shouldn't be visible even to the person holding the token. This is much rarer than JWS.
Sometimes a JWE wraps a JWS. You sign the claims (JWS), then encrypt the result (JWE), getting authenticity and confidentiality together. RFC 7519 calls this a "Nested JWT," where one JWT becomes the payload of an enclosing JWS or JWE.
How to tell them apart at a glance
| Type | Dots / parts | Readable payload? | Use case |
|---|---|---|---|
| JWS (signed) | 2 dots / 3 parts | Yes (plain text) | Auth (common) |
| JWE (encrypted) | 4 dots / 5 parts | No (encrypted) | Sensitive claims (rare) |
The shortcut is just counting dots. Three parts means signed (JWS). Five parts means encrypted (JWE).
The security mistake everyone makes
"We use JWTs, so the data is secure."
If "JWT" here means JWS, and it almost always does, the data is not hidden. It's only tamper-proof. Putting a secret in a JWS payload is like writing it on a postcard and adding a tamper-evident seal: anyone can read it, they just can't alter it without you noticing.
The real-world consequences follow directly:
- Don't put passwords, full credit card numbers, or secrets in a JWS payload.
- Don't assume a JWS hides the user's roles or permissions from them.
- If you genuinely need the claims hidden, use JWE, or just don't put them in the token at all.
The signature gives you integrity and authenticity, never confidentiality. For confidentiality you need JWE, transport encryption (HTTPS), or both.
Where JWK fits in
JWK, defined in RFC 7517, is a JSON format for representing cryptographic keys. These are the public keys used to verify JWS signatures, or the keys used to encrypt and decrypt a JWE.
You'll run into JWKs at a "JWKS endpoint" (/.well-known/jwks.json), where identity providers publish the public keys their clients use to verify tokens. When your backend verifies a JWT from Auth0 or Google, it fetches their JWK to check the signature.
Putting it together: a real flow
Here's a typical OAuth/OIDC login, start to finish:
- You log in to an identity provider, whether Google, Auth0, or another.
- The provider issues a JWT, specifically a JWS (signed).
- Your app receives it, often as an
id_tokenoraccess_token. - Your backend fetches the provider's JWK to get the public key.
- It uses that key to verify the JWS signature.
- If the signature checks out, it trusts the claims, such as user ID and email.
No JWE anywhere in that flow, because the claims (your email, name, ID) aren't secret. JWE only enters the picture when claims actually need hiding. If you want to wire up the verification step yourself, how to decode a JWT in JavaScript walks through it.
The bottom line
JOSE is the umbrella spec, and JWT is the token format that lives inside it. A JWS is a signed JWT: three parts, tamper-proof but fully readable, and it's the common case. A JWE is an encrypted JWT: five parts, genuinely hidden, and it's the rare one. JWK is the key format used to verify or decrypt. The one rule to carry with you is that a signed JWT hides nothing, so never put secrets in a JWS payload. To inspect a signed token's contents, use the JWT Decoder.
Frequently asked questions
Do I need JWE or is JWS enough?
Most applications never need anything beyond JWS. Reach for JWE only when the token's contents must stay hidden from the holder or from intermediaries — medical data, internal identifiers, secrets. For ordinary authentication where user IDs and roles aren't confidential, a signed JWS is the standard choice.
Is a JWS secure when sent over plain HTTP?
No. The JWS signature protects the token from tampering, but it does nothing to protect it in transit. HTTPS is what stops the token from being intercepted. Always use HTTPS, because a stolen JWS is a fully working credential until it expires.
Can I tell if a token is JWS or JWE without decoding it?
Yes, count the dots. Two dots (three parts) is a JWS; four dots (five parts) is a JWE, per RFC 7515 and RFC 7516. The header also gives it away — a JWE carries an "enc" field for the content-encryption algorithm that a JWS never has.
Is the payload of a signed JWT (JWS) encrypted?
No. A JWS payload is only Base64URL-encoded, not encrypted, so anyone can decode and read it without a key. Signing proves the claims weren't altered and proves who issued them, but it provides zero confidentiality. For hidden claims you need JWE.