JSON web token (JWT) implementation in Java

In my previous article , I talked about JWT introduction and how it works. There are multiple libraries by which you can implement JWT in Java.

1. Java JWT: JSON Web Token for Java and Android

Installation

Use your favorite Maven-compatible build tool to pull the dependency (and its transitive dependencies) from Maven Central:

Maven:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.6.0</version>
</dependency>



Gradle:


dependencies {
    compile 'io.jsonwebtoken:jjwt:0.6.0'
}

Note: JJWT depends on Jackson 2.x. If you’re already using an older version of Jackson in your app, read this

Usage

Most complexity is hidden behind a convenient and readable builder-based fluent interface, great for relying on IDE auto-completion to write code quickly. Here’s an example:

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
import java.security.Key;

// We need a signing key, so we'll create one just for this example. Usually
// the key would be read from your application configuration instead.
Key key = MacProvider.generateKey();

String s = Jwts.builder().setSubject("Joe").signWith(SignatureAlgorithm.HS512, key).compact();
How easy was that!?

Now let's verify the JWT (you should always discard JWTs that don't match an expected signature):

assert Jwts.parser().setSigningKey(key).parseClaimsJws(s).getBody().getSubject().equals("Joe");
You have to love one-line code snippets!

But what if signature validation failed? You can catch SignatureException and react accordingly:

try {

    Jwts.parser().setSigningKey(key).parseClaimsJws(compactJwt);

    //OK, we can trust this JWT

} catch (SignatureException e) {

    //don't trust the JWT!
}

2. Using Nimbus Jose + JWT

The most popular and robust Java library for JSON Web Tokens (JWT)
Supports all standard signature (JWS) and encryption (JWE) algorithms
Open source Apache 2.0 licence

Features –

– Signed / encrypted tokens, such as bearer access tokens in OAuth 2.0 or OpenID Connect identity tokens;
– Self-contained API keys, with optional revocation;
– Protecting content and messages;
– Authenticating clients and web API requests.

Use in Java

// Create an HMAC-protected JWS object with some payload
JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256),
                                    new Payload("Hello world!"));

// We need a 256-bit key for HS256 which must be pre-shared
byte[] sharedKey = new byte[32];
new SecureRandom().nextBytes(sharedKey);

// Apply the HMAC to the JWS object
jwsObject.sign(new MACSigner(sharedKey));

// Output to URL-safe format
jwsObject.serialize(); 

Maven configuration

Maven
For Java 7+ :

<dependency>
    <groupId>com.nimbusds</groupId>
    <artifactId>nimbus-jose-jwt</artifactId>
    <version>4.11.2</version>
</dependency>

3. JSON token library – It depend on Google Guava.The library is in fact used by Google Wallet.

Here is how to create a jwt, and to verify it and deserialize it:

Maven –

<dependency>
    <groupId>com.googlecode.jsontoken</groupId>
    <artifactId>jsontoken</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>18.0</version>
</dependency>

and Java implementation –

import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.util.Calendar;
import java.util.List;

import net.oauth.jsontoken.JsonToken;
import net.oauth.jsontoken.JsonTokenParser;
import net.oauth.jsontoken.crypto.HmacSHA256Signer;
import net.oauth.jsontoken.crypto.HmacSHA256Verifier;
import net.oauth.jsontoken.crypto.SignatureAlgorithm;
import net.oauth.jsontoken.crypto.Verifier;
import net.oauth.jsontoken.discovery.VerifierProvider;
import net.oauth.jsontoken.discovery.VerifierProviders;

import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.joda.time.DateTime;

import com.google.common.collect.Lists;
import com.google.gson.JsonObject;


/**
 * Provides static methods for creating and verifying access tokens and such. 
 * @author davidm
 *
 */
public class AuthHelper {

    private static final String AUDIENCE = "NotReallyImportant";

    private static final String ISSUER = "YourCompanyOrAppNameHere";

    private static final String SIGNING_KEY = "[email protected]^($%*$%";

    /**
     * Creates a json web token which is a digitally signed token that contains a payload (e.g. userId to identify 
     * the user). The signing key is secret. That ensures that the token is authentic and has not been modified.
     * Using a jwt eliminates the need to store authentication session information in a database.
     * @param userId
     * @param durationDays
     * @return
     */
    public static String createJsonWebToken(String userId, Long durationDays)    {
        //Current time and signing algorithm
        Calendar cal = Calendar.getInstance();
        HmacSHA256Signer signer;
        try {
            signer = new HmacSHA256Signer(ISSUER, null, SIGNING_KEY.getBytes());
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        }

        //Configure JSON token
        JsonToken token = new net.oauth.jsontoken.JsonToken(signer);
        token.setAudience(AUDIENCE);
        token.setIssuedAt(new org.joda.time.Instant(cal.getTimeInMillis()));
        token.setExpiration(new org.joda.time.Instant(cal.getTimeInMillis() + 1000L * 60L * 60L * 24L * durationDays));

        //Configure request object, which provides information of the item
        JsonObject request = new JsonObject();
        request.addProperty("userId", userId);

        JsonObject payload = token.getPayloadAsJsonObject();
        payload.add("info", request);

        try {
            return token.serializeAndSign();
        } catch (SignatureException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Verifies a json web token's validity and extracts the user id and other information from it. 
     * @param token
     * @return
     * @throws SignatureException
     * @throws InvalidKeyException
     */
    public static TokenInfo verifyToken(String token)  
    {
        try {
            final Verifier hmacVerifier = new HmacSHA256Verifier(SIGNING_KEY.getBytes());

            VerifierProvider hmacLocator = new VerifierProvider() {

                @Override
                public List<Verifier> findVerifier(String id, String key){
                    return Lists.newArrayList(hmacVerifier);
                }
            };
            VerifierProviders locators = new VerifierProviders();
            locators.setVerifierProvider(SignatureAlgorithm.HS256, hmacLocator);
            net.oauth.jsontoken.Checker checker = new net.oauth.jsontoken.Checker(){

                @Override
                public void check(JsonObject payload) throws SignatureException {
                    // don't throw - allow anything
                }

            };
            //Ignore Audience does not mean that the Signature is ignored
            JsonTokenParser parser = new JsonTokenParser(locators,
                    checker);
            JsonToken jt;
            try {
                jt = parser.verifyAndDeserialize(token);
            } catch (SignatureException e) {
                throw new RuntimeException(e);
            }
            JsonObject payload = jt.getPayloadAsJsonObject();
            TokenInfo t = new TokenInfo();
            String issuer = payload.getAsJsonPrimitive("iss").getAsString();
            String userIdString =  payload.getAsJsonObject("info").getAsJsonPrimitive("userId").getAsString();
            if (issuer.equals(ISSUER) && !StringUtils.isBlank(userIdString))
            {
                t.setUserId(new ObjectId(userIdString));
                t.setIssued(new DateTime(payload.getAsJsonPrimitive("iat").getAsLong()));
                t.setExpires(new DateTime(payload.getAsJsonPrimitive("exp").getAsLong()));
                return t;
            }
            else
            {
                return null;
            }
        } catch (InvalidKeyException e1) {
            throw new RuntimeException(e1);
        }
    }


}

public class TokenInfo {
    private ObjectId userId;
    private DateTime issued;
    private DateTime expires;
    public ObjectId getUserId() {
        return userId;
    }
    public void setUserId(ObjectId userId) {
        this.userId = userId;
    }
    public DateTime getIssued() {
        return issued;
    }
    public void setIssued(DateTime issued) {
        this.issued = issued;
    }
    public DateTime getExpires() {
        return expires;
    }
    public void setExpires(DateTime expires) {
        this.expires = expires;
    }
}

Happy API secure using JWT with Vinay

Reference
– https://github.com/jwtk/jjwt
– http://connect2id.com/products/nimbus-jose-jwt
– https://code.google.com/archive/p/jsontoken/

Build Secure Application Using JSON Web Tokens (JWT)

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

Below picture will give more better explanation

The claims in a JWT are encoded as a JSON object that is base64url encoded and consists of zero or more name/value pairs (or members), where the names are strings and the values are arbitrary JSON values. Each member is a claim represented by the JWT.

What JWT contains – JWT consists of three main components: a header object, payload object, and a signature. These three properties are encoded using base64, then concatenated with periods as separators.

for example

xxxxxxxxxxxxxxxxxx.yyyy.zzzzzzzzzzzzzzzzzzzzzzzzz

xxxxxxxxxxxxxxxxxxxxx – header
yyyy – – claims/payload
zzzzzzzzzzzzzzzzzzzz – signature

Header: The header contains the metadata for the token and at a minimal contains the type of the signature and/or encryption algorithm
Claims: The claims contains any information that you want signed
JSON Web Signature (JWS): The headers and claims digitally signed using the algorithm in the specified in the headerStructure of a JWT

JSON Web Token example:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b3B0YWwuY29tI iwiZXhwIjoxNDI2NDIwODAwLCJodHRwOi8vdG9wdGFsLmNvbS9qd3RfY2xhaW1zL2lzX2FkbWluI jp0cnVlLCJjb21wYW55IjoiVG9wdGFsIiwiYXdlc29tZSI6dHJ1ZX0.yRQYnWzskCZUxPwaQupWk iUzKELZ49eM7oWxAQK_ZXw

Since there are 3 parts separated by a ., each section is created differently. We have the 3 parts which are:

header
payload
signature
..

Header

The JWT Header declares that the encoded object is a JSON Web Token (JWT) and the JWT is a JWS that is MACed using the HMAC SHA-256 algorithm. For example:

{
“alg”: “HS256”,
“typ”: “JWT”
}
“alg” is a string and specifies the algorithm used to sign the token.

“typ” is a string for the token, defaulted to “JWT”. Specifies that this is a JWT token.

Payload (Claims)

A claim or a payload can be defined as a statement about an entity that contians security information as well as additional meta data about the token itself.

Following are the claim attributes :

iss: The issuer of the token

sub: The subject of the token

aud: The audience of the token

qsh: query string hash

exp: Token expiration time defined in Unix time

nbf: “Not before” time that identifies the time before which the JWT must not be accepted for processing

iat: “Issued at” time, in Unix time, at which the token was issued

jti: JWT ID claim provides a unique identifier for the JWT

Signature

JSON Web Signatre specification are followed to generate the final signed token. JWT Header, the encoded claim are combined, and an encryption algorithm, such as HMAC SHA-256 is applied. The signatures’s secret key is held by the server so it will be able to verify existing tokens.

JWT-Real world

Advantages of Token Based Approach

JWT approach allows us to make AJAX calls to any server or domain. Since the HTTP header is used to transmit the user information.

Their is no need for having a separate session store on the server. JWT itself conveys the entire information.

Server Side reduces to just an API and static assets(HTML, CSS, JS) can be served via a CDN.

The authentication system is mobile ready, the token can be generated on any device.

Since we have eliminated the need for cookies, we no more need to protect against the cross site requesets.

API Keys provide either-or solution, whereas JWT provide much granular control, which can be inspected for any debugging purpose.

API Keys depend on a central storage and a service. JWT can be self-issued or an external service can issue it with allowed scopes and expiration.

You can use jwt in node.js, angular.js, ruby, Java, .net and other frameworks.
Following is example of JWT generator and verify jwt token

Generate Tokens

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import io.jsonwebtoken.*;
import java.util.Date;    

//Sample method to construct a JWT

private String createJWT(String id, String issuer, String subject, long ttlMillis) {

//The JWT signature algorithm we will be using to sign the token
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);

//We will sign our JWT with our ApiKey secret
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(apiKey.getSecret());
Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

  //Let's set the JWT Claims
JwtBuilder builder = Jwts.builder().setId(id)
                                .setIssuedAt(now)
                                .setSubject(subject)
                                .setIssuer(issuer)
                                .signWith(signatureAlgorithm, signingKey);

 //if it has been specified, let's add the expiration
if (ttlMillis >= 0) {
    long expMillis = nowMillis + ttlMillis;
    Date exp = new Date(expMillis);
    builder.setExpiration(exp);
}

 //Builds the JWT and serializes it to a compact, URL-safe string
return builder.compact();
}

Decode and Verify Tokens

import javax.xml.bind.DatatypeConverter;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;

//Sample method to validate and read the JWT
private void parseJWT(String jwt) {
//This line will throw an exception if it is not a signed JWS (as expected)
Claims claims = Jwts.parser()         
   .setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret()))
   .parseClaimsJws(jwt).getBody();
System.out.println("ID: " + claims.getId());
System.out.println("Subject: " + claims.getSubject());
System.out.println("Issuer: " + claims.getIssuer());
System.out.println("Expiration: " + claims.getExpiration());
}

Happy secure API call with Vinay in techartifact . 🙂

– See more at:
http://blog.apcelent.com/json-web-token-tutorial-example-python.html#sthash.GzZriR3U.dpuf
http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/

How to Create and verify JWTs in Java