JWT code examples
Creating, verifying and decoding an HS256 token with the most popular library for each language. Paste any token they print into the decoder with the secret a-string-secret-at-least-256-bits-long to verify it.
JWT in Node.js / JavaScript
Install: npm install jose
jose works in Node.js, browsers, Deno, Bun and edge runtimes.
import { SignJWT, jwtVerify, decodeJwt } from "jose";
const secret = new TextEncoder().encode("a-string-secret-at-least-256-bits-long");
// Create and sign
const token = await new SignJWT({ name: "Ada Lovelace", admin: true })
.setProtectedHeader({ alg: "HS256" })
.setSubject("1234567890")
.setIssuedAt()
.setExpirationTime("1h")
.sign(secret);
console.log(token);
// Verify (checks the signature and exp/nbf)
const { payload } = await jwtVerify(token, secret, { algorithms: ["HS256"] });
console.log(payload.name); // "Ada Lovelace"
// Decode WITHOUT verifying — never trust these claims
console.log(decodeJwt(token));JWT in Python
Install: pip install pyjwt
import datetime as dt
import jwt
secret = "a-string-secret-at-least-256-bits-long"
now = dt.datetime.now(dt.timezone.utc)
# Create and sign
token = jwt.encode(
{"sub": "1234567890", "name": "Ada Lovelace", "iat": now, "exp": now + dt.timedelta(hours=1)},
secret,
algorithm="HS256",
)
print(token)
# Verify (raises jwt.ExpiredSignatureError, jwt.InvalidSignatureError, ...)
claims = jwt.decode(token, secret, algorithms=["HS256"])
print(claims["name"])
# Decode WITHOUT verifying
print(jwt.decode(token, options={"verify_signature": False}))JWT in Java
Install: io.jsonwebtoken:jjwt-api, jjwt-impl and jjwt-jackson (0.12.x)
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
public class JwtExample {
public static void main(String[] args) {
SecretKey key = Keys.hmacShaKeyFor(
"a-string-secret-at-least-256-bits-long".getBytes(StandardCharsets.UTF_8));
// Create and sign (HS256 is picked from the key size)
String token = Jwts.builder()
.subject("1234567890")
.claim("name", "Ada Lovelace")
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + 3_600_000))
.signWith(key)
.compact();
System.out.println(token);
// Verify and read the claims
Claims claims = Jwts.parser()
.verifyWith(key)
.build()
.parseSignedClaims(token)
.getPayload();
System.out.println(claims.get("name", String.class));
}
}JWT in C# / .NET
Install: dotnet add package Microsoft.IdentityModel.JsonWebTokens
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes("a-string-secret-at-least-256-bits-long"));
var handler = new JsonWebTokenHandler();
// Create and sign
string token = handler.CreateToken(new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim("sub", "1234567890"),
new Claim("name", "Ada Lovelace"),
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256),
});
Console.WriteLine(token);
// Verify
var result = await handler.ValidateTokenAsync(token, new TokenValidationParameters
{
ValidateIssuer = false, // set ValidIssuer / ValidAudience in real apps
ValidateAudience = false,
IssuerSigningKey = key,
});
Console.WriteLine(result.IsValid ? result.Claims["name"] : result.Exception.Message);JWT in Go
Install: go get github.com/golang-jwt/jwt/v5
package main
import (
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
)
func main() {
secret := []byte("a-string-secret-at-least-256-bits-long")
// Create and sign
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"sub": "1234567890",
"name": "Ada Lovelace",
"iat": time.Now().Unix(),
"exp": time.Now().Add(time.Hour).Unix(),
})
signed, err := token.SignedString(secret)
if err != nil {
panic(err)
}
fmt.Println(signed)
// Verify — always pin the expected algorithm
parsed, err := jwt.Parse(signed, func(t *jwt.Token) (any, error) {
return secret, nil
}, jwt.WithValidMethods([]string{"HS256"}))
if err != nil {
panic(err)
}
claims := parsed.Claims.(jwt.MapClaims)
fmt.Println(claims["name"])
}JWT in PHP
Install: composer require firebase/php-jwt
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$secret = 'a-string-secret-at-least-256-bits-long';
// Create and sign
$token = JWT::encode([
'sub' => '1234567890',
'name' => 'Ada Lovelace',
'iat' => time(),
'exp' => time() + 3600,
], $secret, 'HS256');
echo $token, "\n";
// Verify (throws on a bad signature or expired token)
$decoded = JWT::decode($token, new Key($secret, 'HS256'));
echo $decoded->name, "\n";JWT in Rust
Install: cargo add jsonwebtoken@9 serde --features serde/derive
use jsonwebtoken::{decode, encode, get_current_timestamp, Algorithm, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
name: String,
exp: u64,
}
fn main() -> Result<(), jsonwebtoken::errors::Error> {
let secret = b"a-string-secret-at-least-256-bits-long";
let claims = Claims {
sub: "1234567890".into(),
name: "Ada Lovelace".into(),
exp: get_current_timestamp() + 3600,
};
// Create and sign
let token = encode(&Header::new(Algorithm::HS256), &claims, &EncodingKey::from_secret(secret))?;
println!("{token}");
// Verify
let data = decode::<Claims>(&token, &DecodingKey::from_secret(secret), &Validation::new(Algorithm::HS256))?;
println!("{}", data.claims.name);
Ok(())
}JWT in Bash
Decodes only — it does not verify the signature. Needs jq for pretty output.
# Decode part N of a JWT (1 = header, 2 = payload)
jwt_part() {
local part
part=$(cut -d. -f"$2" <<< "$1" | tr '_-' '/+')
while (( ${#part} % 4 )); do part+="="; done
base64 -d <<< "$part"
}
TOKEN='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.signature'
jwt_part "$TOKEN" 1 | jq . # header
jwt_part "$TOKEN" 2 | jq . # payloadVerification checklist
- Always pass an explicit list of allowed algorithms. Never let the token's own
algdecide. - Reject
alg: nonetokens. - Check
exp,nbf, and the expectedissandaud. - Use secrets of at least 256 bits for HS256 and keep them out of source control.