com.auth0.jwt.JWTSigner Maven / Gradle / Ivy
package com.auth0.jwt;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.naming.OperationNotSupportedException;
import org.apache.commons.codec.binary.Base64;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* JwtSigner implementation based on the Ruby implementation from http://jwt.io
* No support for RSA encryption at present
*/
public class JWTSigner {
private final byte[] secret;
public JWTSigner(String secret) {
this(secret.getBytes());
}
public JWTSigner(byte[] secret) {
this.secret = secret;
}
/**
* Generate a JSON Web Token.
* using the default algorithm HMAC SHA-256 ("HS256")
* and no claims automatically set.
*
* @param claims A map of the JWT claims that form the payload. Registered claims
* must be of appropriate Java datatype as following:
*
* - iss, sub: String
*
- exp, nbf, iat, jti: numeric, eg. Long
*
- aud: String, or Collection<String>
*
* All claims with a null value are left out the JWT.
* Any claims set automatically as specified in
* the "options" parameter override claims in this map.
*
*
* @param options Allow choosing the signing algorithm, and automatic setting of some registered claims.
*/
public String sign(Map claims, Options options) {
Algorithm algorithm = Algorithm.HS256;
if (options != null && options.algorithm != null)
algorithm = options.algorithm;
List segments = new ArrayList();
try {
segments.add(encodedHeader(algorithm));
segments.add(encodedPayload(claims, options));
segments.add(encodedSignature(join(segments, "."), algorithm));
} catch (Exception e) {
throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e);
}
return join(segments, ".");
}
/**
* Generate a JSON Web Token using the default algorithm HMAC SHA-256 ("HS256")
* and no claims automatically set.
*/
public String sign(Map claims) {
return sign(claims, null);
}
/**
* Generate the header part of a JSON web token.
*/
private String encodedHeader(Algorithm algorithm) throws UnsupportedEncodingException {
if (algorithm == null) { // default the algorithm if not specified
algorithm = Algorithm.HS256;
}
// create the header
ObjectNode header = JsonNodeFactory.instance.objectNode();
header.put("typ", "JWT");
header.put("alg", algorithm.name());
return base64UrlEncode(header.toString().getBytes("UTF-8"));
}
/**
* Generate the JSON web token payload string from the claims.
* @param options
*/
private String encodedPayload(Map _claims, Options options) throws Exception {
Map claims = new HashMap(_claims);
enforceStringOrURI(claims, "iss");
enforceStringOrURI(claims, "sub");
enforceStringOrURICollection(claims, "aud");
enforceIntDate(claims, "exp");
enforceIntDate(claims, "nbf");
enforceIntDate(claims, "iat");
enforceString(claims, "jti");
if (options != null)
processPayloadOptions(claims, options);
String payload = new ObjectMapper().writeValueAsString(claims);
return base64UrlEncode(payload.getBytes("UTF-8"));
}
private void processPayloadOptions(Map claims, Options options) {
long now = System.currentTimeMillis() / 1000l;
if (options.expirySeconds != null)
claims.put("exp", now + options.expirySeconds);
if (options.notValidBeforeLeeway != null)
claims.put("nbf", now - options.notValidBeforeLeeway);
if (options.isIssuedAt())
claims.put("iat", now);
if (options.isJwtId())
claims.put("jti", UUID.randomUUID().toString());
}
private void enforceIntDate(Map claims, String claimName) {
Object value = handleNullValue(claims, claimName);
if (value == null)
return;
if (!(value instanceof Number)) {
throw new RuntimeException(String.format("Claim '%s' is invalid: must be an instance of Number", claimName));
}
long longValue = ((Number) value).longValue();
if (longValue < 0)
throw new RuntimeException(String.format("Claim '%s' is invalid: must be non-negative", claimName));
claims.put(claimName, longValue);
}
private void enforceStringOrURICollection(Map claims, String claimName) {
Object values = handleNullValue(claims, claimName);
if (values == null)
return;
if (values instanceof Collection) {
@SuppressWarnings({ "unchecked" })
Iterator
© 2015 - 2025 Weber Informatics LLC | Privacy Policy