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/