A real header.payload.signature token, decoded into its claims. Edit role from patient to admin and the signature check fails; let it expire and it's rejected. See exactly why a JWT must be validated, not trusted.
Here's a real-shaped JWT. Edit the claims like an attacker would, then validate it — and watch the signature check catch the tampering.
▹A JWT is three base64 parts: header.payload.signature. The payload holds claims — who you are (sub), your role, the issuer, and an expiry. Anyone can read it; base64 is not encryption.
▹The signature is the security. The server signs header+payload with a secret key. To trust a token it recomputes the signature and checks it matches — and checks the token hasn't expired.
▹That's why tampering fails: an attacker can edit 'role: patient' to 'role: admin', but they can't produce a matching signature without the secret. A server that skips validation and just trusts the decoded claims is wide open.