Monday, April 22, 2024
HomeJavaCreating, Signing, and Verifying JWT in Java - Java Code Geeks

Creating, Signing, and Verifying JWT in Java – Java Code Geeks


Summary

You utilize JWTs don’t you? Everybody does, proper? However have you learnt generate, signal, and confirm them? The aim of this publish is to show code all these operations.

Disclaimer

This publish is solely informative. Critically suppose earlier than utilizing any data introduced. Be taught from it however finally make your individual selections at your individual threat.

Necessities

I did the entire work for this publish utilizing the next main applied sciences. You could possibly do the identical factor with completely different applied sciences or variations, however no ensures.

  • Java 11
  • Maven 3.8.6 (Bundled with NetBeans)

Obtain

Go to my GitHub web page https://github.com/mjremijan to see all of my open supply initiatives. The code for this publish is situated at: https://github.com/mjremijan/thoth-jwt

A JWT is an easy three-part string of encoded characters – header, payload, signature – separated by 2 “.” characters.

xxxxx.yyyyy.zzzzz

JWT know-how has been round for years. Learn all concerning the JWT specification on the Introduction to JSON Internet Tokens at https://jwt.io/introduction. This weblog focuses on the Java code to create and confirm JWT values. There are 2 examples:

  1. JWT with Symmetric HMAC SHA256 Signature
  2. JWT with Uneven RSA SHA256 Signature

Let’s check out them.

JWT with Symmetric HMAC SHA256 Signature

Itemizing 1 reveals the code and Itemizing 2 reveals instance output.

Itemizing 1 – JWT with Symmetric HMAC SHA256 Signature

package deal org.thoth.jwt.most important;
 
 import java.util.Base64;
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
 
 /**
  *
  * @writer Michael Remijan mjremijan@yahoo.com @mjremijan
.  */
 public class SignatureWithSymmetricalHmacSha256Main 
 {
     public static void most important(String[] args) throws Exception 
     {
         // JWT HEADER
         //
         // That is the xxxxx of a JWT xxxxx.yyyyy.zzzzz
         //
         // Given the next JSON doc, encode it
         // utilizing Java as outlined within the JWT specs
         String header = "{"alg":"HS256","typ": "JWT"}";
         String headerEncoded 
             = Base64.getUrlEncoder()
                     .withoutPadding()
                     .encodeToString(
                         header.getBytes()
                    );
         String headerDecoded
                = new String(
                     Base64.getUrlDecoder().decode(headerEncoded)
                 );
         
         System.out.printf("Header Plain   : %spercentn", header);
         System.out.printf("Header Encoded : %spercentn", headerEncoded);
         System.out.printf("Header Decoded : %spercentn", headerDecoded);
         
         
         // JWT PAYLOAD
         //
         // That is the yyyyy of a JWT xxxxx.yyyyy.zzzzz
         //
         // Given the next JSON doc, encode it
         // utilizing Java as outlined within the JWT specs
         String payload = "{"sub":"TMJR00001","title":"Michael J. Remijan","exp":61475608800,"iss":"data@wstutorial.com","teams":["user","admin"]}";
         String payloadEncoded 
             = Base64.getUrlEncoder()
                     .withoutPadding()
                     .encodeToString(
                         payload.getBytes()
                     );
         
         String payloadDecoded
                 = new String(
                     Base64.getUrlDecoder().decode(payloadEncoded)
                 );
         
         System.out.printf("%n");
         System.out.printf("Payload Plain   : %spercentn", payload);
         System.out.printf("Payload Encoded : %spercentn", payloadEncoded);
         System.out.printf("Payload Decoded : %spercentn", payloadDecoded);
         
     
         // SIGNATURE / VERIFY
         // That is the zzzzz of a JWT xxxxx.yyyyy.zzzzz
         //
         // Hash-based message authentication code(HMAC)
         // is a selected kind of message authentication code 
         // (MAC) involving a cryptographic hash perform and 
         // a secret cryptographic key. As with all MAC, it 
         // could also be used to concurrently confirm each the info
         // integrity and authenticity of a message.
         // 
         // A cryptographic hash perform (CHF) is any perform 
         // that can be utilized to map information of arbitrary measurement to 
         // a fixed-size variety of n bits that has particular 
         // properties fascinating for a cryptographic utility.
         //
         // For this instance, the method will use the SHA256
         // cryptographic hash perform and a secret key
         // to generate a signatureCreatedFromThisData (hash) of the JWT information.
         // This signatureCreatedFromThisData can then be used to confirm the
         // JWT information has not been tampered.
         //
         // Usually the key secret is solely obtainable on the 
         // Authentication Server. The secret's used to create the 
         // signatureCreatedFromThisData for the JWT. Purchasers will sometimes make 
         // an authentication request (HTTPS) to the Authentication
         // server to confirm a JWT. Purchasers can not confirm a JWT 
         // themselves as a result of they don't have entry to the
         // secret key. Nevertheless, if a Consumer is 100% trusted,
         // The key key could be shared with the Consumer so
         // that the Consumer can do its personal verification. 
         // WARNING: This implies the Consumer may also have the ability 
         // to make new JWTs, which could be harmful.
         String algorithm  = "HmacSHA256";
         String secret = "thisismysupersecretkeywhichshouldonlybeontheauthenticationserver";
         SecretKeySpec key = new SecretKeySpec(secret.getBytes(), algorithm);
         Mac mac = Mac.getInstance(algorithm);
         mac.init(key);
         String signatureCreatedFromThisData 
             = headerEncoded + "." + payloadEncoded;
         String signatureEncoded 
             = Base64.getUrlEncoder()
                     .withoutPadding()
                     .encodeToString(mac.doFinal(
                             signatureCreatedFromThisData.getBytes()
                         )
                     );
         
         System.out.printf("%n");
         System.out.printf("Signature Algorithm : %spercentn", algorithm);
         System.out.printf("Signature Secret    : %spercentn", secret);
         System.out.printf("Signaure Encoded    :%spercentn", signatureEncoded);
     }
 }
 

Itemizing 2 – HMAC Instance Output

Header Plain   : {"alg":"HS256","typ": "JWT"}
Header Encoded : eyJhbGciOiJIUzI1NiIsInR5cCI6ICJKV1QifQ
Header Decoded : {"alg":"HS256","typ": "JWT"}

Payload Plain   : {"sub":"TMJR00001","title":"Michael J. Remijan","exp":61475608800,"iss":"data@wstutorial.com","teams":["user","admin"]}
Payload Encoded : eyJzdWIiOiJUTUpSMDAwMDEiLCJuYW1lIjoiTWljaGFlbCBKLiBSZW1pamFuIiwiZXhwIjo2MTQ3NTYwODgwMCwiaXNzIjoiaW5mb0B3c3R1dG9yaWFsLmNvbSIsImdyb3VwcyI6WyJ1c2VyIiwiYWRtaW4iXX0
Payload Decoded : {"sub":"TMJR00001","title":"Michael J. Remijan","exp":61475608800,"iss":"data@wstutorial.com","teams":["user","admin"]}

Signature Algorithm : HmacSHA256
Signature Secret    : thisismysupersecretkeywhichshouldonlybeontheauthenticationserver
Signaure Encoded    :Xi6kVafrGX18FQIkNZuVJVBbmGbmEzI8cM-5G02S32A

Line #21 of Itemizing 1 begins the creation of the JWT header. That is the xxxxx a part of a xxxxx.yyyyy.zzzzz JWT. As you’ll be able to see, the code is straightforward. Use Base64.getUrlEncoder().withoutPadding() for encoding and Base64.getUrlDecoder() for decoding.

NOTE:Make certain to make use of the **.withoutPadding()** encoder. If not, trailing “=” characters might be added by the encoder to make the encoded string the required size. These trailing “=” aren’t allowed by the JWT specification so you probably have them, different JWT decoders received’t be capable to decode your JWT correctly.

Line #44 of Itemizing 1 begins the creation of the JWT payload, sometimes consumer data, however in principle could be something. That is the yyyyy a part of a xxxxx.yyyyy.zzzzz JWT. As you’ll be able to see, the code is straightforward. Use Base64.getUrlEncoder().withoutPadding() for encoding and Base64.getUrlDecoder() for decoding. See NOTE above about utilizing the .withoutPadding() encoder.

Line #95 of Itemizing 1 begins the creation of the JWT signature. That is the zzzzz a part of a xxxxx.yyyyy.zzzzz JWT. Itemizing 1 is an instance of utilizing the "alg":"HS256" aka HmacSHA256 algorithm. This can be a single-key, symmetric algorithm which depends on a user-generated secret worth as seen on line #96. This secret sometimes is saved exterior the applying in some sort of configuration system (file, git, database, and many others.). Staring with line #102, you see how the MAC is used to complete the hash and the Base64.getUrlEncoder().withoutPadding() is used to encode the hash.

You’ll discover that after signing, there isn’t a extra code in Itemizing 1. The place’s the code exhibiting confirm a JWT? Properly with a single-key, symmetric algorithm like HmacSHA256, the signing and verifying steps are precisely the identical. To confirm, the signature must be generated once more and in contrast with the zzzzz a part of a xxxxx.yyyyy.zzzzz JWT.

That’s it for JWT with Symmetric HMAC SHA256 Signature.

JWT with Uneven RSA SHA256 Signature

Itemizing 3 reveals the code and Itemizing 4 reveals instance output.

Itemizing 3 – JWT with Uneven RSA SHA256 Signature

package deal org.thoth.jwt.most important;
 
 import java.safety.KeyPair;
 import java.safety.KeyPairGenerator;
 import java.safety.PrivateKey;
 import java.safety.PublicKey;
 import java.safety.Signature;
 import java.util.Base64;
 
 /**
  *
  * @writer Michael Remijan mjremijan@yahoo.com @mjremijan
  */
 public class SignatureWithAsymmetricalRsaSha256Main 
 {
     public static void most important(String[] args) throws Exception 
     {
         // JWT HEADER
         //
         // That is the xxxxx of a JWT xxxxx.yyyyy.zzzzz
         //
         // Given the next JSON doc, encode it
         // utilizing Java as outlined within the JWT specs
         String header = "{"alg":"RS256","typ": "JWT"}";
         String headerEncoded 
             = Base64.getUrlEncoder()
                     .withoutPadding()
                     .encodeToString(
                         header.getBytes()
                     );
         String headerDecoded
                 = new String(
                     Base64.getUrlDecoder().decode(headerEncoded)
                 );
        
         System.out.printf("Header Plain   : %spercentn", header);
         System.out.printf("Header Encoded : %spercentn", headerEncoded);
         System.out.printf("Header Decoded : %spercentn", headerDecoded);
         
         
         // JWT PAYLOAD
         //
         // That is the yyyyy of a JWT xxxxx.yyyyy.zzzzz
         //
         // Given the next JSON doc, encode it
         // utilizing Java as outlined within the JWT specs
         String payload = "{"sub":"TMJR00001","title":"Michael J. Remijan","exp":61475608800,"iss":"data@wstutorial.com","teams":["user","admin"]}";
         String payloadEncoded 
             = Base64.getUrlEncoder()
                     .withoutPadding()
                     .encodeToString(
                         payload.getBytes()
                     );
         
         String payloadDecoded
                 = new String(
                     Base64.getUrlDecoder().decode(payloadEncoded)
                 );
         
         System.out.printf("%n");
         System.out.printf("Payload Plain   : %spercentn", payload);
         System.out.printf("Payload Encoded : %spercentn", payloadEncoded);
         System.out.printf("Payload Decoded : %spercentn", payloadDecoded);
         
     
         // SIGNATURE
         //
         // That is the zzzzz of a JWT xxxxx.yyyyy.zzzzz
         //
         // RSA (Rivest--Shamir--Adleman) is a public-key cryptosystem 
         // that's extensively used for safe information transmission.
         // In a public-key cryptosystem, the general public secret is used for
         // encryption and the personal secret is used for decryption. The
         // personal key can be used for creating digital signatures
         // of knowledge and the general public secret is used for verifying the
         // digital signature.
         //
         // A cryptographic hash perform (CHF) is any perform 
         // that can be utilized to map information of arbitrary measurement to 
         // a fixed-size variety of n bits that has particular 
         // properties fascinating for a cryptographic utility.
         //
         // For this instance, the method will use the SHA256
         // cryptographic hash perform together with a public/personal
         // keypair and the RSA encryption algorithm to generate
         // a signature for the JWT.
         //
         // The personal secret is used for creating the signature.
         //
         KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA");
         keyGenerator.initialize(1024);
         KeyPair kp = keyGenerator.genKeyPair();
         PublicKey publicKey = (PublicKey) kp.getPublic();
         PrivateKey privateKey = (PrivateKey) kp.getPrivate();
         String algorithm = "SHA256withRSA";
         String signatureCreatedFromThisData 
             = headerEncoded + "." + headerDecoded;
         
         Signature privateSignature 
             = Signature.getInstance(algorithm);
         privateSignature.initSign(privateKey);
         
         System.out.printf("%n");
         System.out.printf("Algorithm    : %spercentn", algorithm);
         System.out.printf("Public Key   : %spercentn", Base64.getEncoder().encodeToString(publicKey.getEncoded()));
         System.out.printf("Personal Key  : %spercentn", Base64.getEncoder().encodeToString(privateKey.getEncoded()));
         
         privateSignature.replace(signatureCreatedFromThisData.getBytes());
         String signatureEncoded 
                 = Base64.getUrlEncoder()
                         .withoutPadding()
                         .encodeToString(
                            privateSignature.signal()
                         );
         System.out.printf("%n");
         System.out.printf("Signaure Encoded         : %spercentn", signatureEncoded);
         
         // VERIFY
         // That is the zzzzz of a JWT xxxxx.yyyyy.zzzzz
         //
         // The general public secret is used for verifying the signature.
         //
         // Becuase the general public secret is used for making a signature,
         // it protected to distribute the general public key to Purchasers so 
         // that Purchasers can confirm the JWT signature with out
         // having to ask the Authentication Server for verification
         //
         
         Signature publicSignature = Signature.getInstance(algorithm);
         publicSignature.initVerify(publicKey);
         publicSignature.replace(signatureCreatedFromThisData.getBytes());
         boolean verified = publicSignature.confirm(
             Base64.getUrlDecoder().decode(signatureEncoded)
         );
         System.out.printf("Signature Verified (t/f) : %bpercentn", verified);
     }
 }

Itemizing 4 – RSA Instance Output

Header Plain   : {"alg":"RS256","typ": "JWT"}
Header Encoded : eyJhbGciOiJSUzI1NiIsInR5cCI6ICJKV1QifQ
Header Decoded : {"alg":"RS256","typ": "JWT"}

Payload Plain   : {"sub":"TMJR00001","title":"Michael J. Remijan","exp":61475608800,"iss":"data@wstutorial.com","teams":["user","admin"]}
Payload Encoded : eyJzdWIiOiJUTUpSMDAwMDEiLCJuYW1lIjoiTWljaGFlbCBKLiBSZW1pamFuIiwiZXhwIjo2MTQ3NTYwODgwMCwiaXNzIjoiaW5mb0B3c3R1dG9yaWFsLmNvbSIsImdyb3VwcyI6WyJ1c2VyIiwiYWRtaW4iXX0
Payload Decoded : {"sub":"TMJR00001","title":"Michael J. Remijan","exp":61475608800,"iss":"data@wstutorial.com","teams":["user","admin"]}

Algorithm    : SHA256withRSA
Public Key   : MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRxw6Ncvsx0/kDYKwA6pLwn3hSbRdYFBOv1aiBomF7lPfOPfqaTgN2yPN6hErlLAP2d+94ig4uXv7MROXlsn8n7jdr2g5yo/kC92RJwALpffzBlWh29hEadiznWp2u0b0h++Cn4HJejfJpZOek6wurBL/7K2Y2TELOg8eg1uipEwIDAQAB
Personal Key  : MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANHHDo1y+zHT+QNgrADqkvCfeFJtF1gUE6/VqIGiYXuU9849+ppOA3bI83qESuUsA/Z373iKDi5e/sxE5eWyfyfuN2vaDnKj+QL3ZEnAAul9/MGVaHb2ERp2LOdana7RvSH74Kfgcl6N8mlk56TrC6sEv/srZjZMQs6Dx6DW6KkTAgMBAAECgYBqVyPzZGQeADxtD+ZhmIfgXpaaAh8hURwhuIdxH6WXBg8Qh66v5fgvkPKMGt/0iHmByY6lZiaGLzWuywZXiEKYSl6tpK8WtiY+gyYxOVgFckAKzjBJ4GYb6YvPI5p5/qDFqN/9Ca4vDn9URFEIRSBIc1it8TWzze8x2Ljd4vu54QJBAOmlSJ/m4dHJMzLnyM6Y1x/e2fqm48DbfV3m+jDjyR7YrTwcVoZSC17B1z4J7W+/Ea7N61UWRRvelvC4c8OKkEkCQQDl2StC7vbKCsnDAFyDjUADq7p2aE+vVH7v7ZUjHhsTXMF8TFMgfkxl5cH58nDNq1Yo82SKGvMeRnmBYHeHlqZ7AkBP1Ur4YBJ+9QmKdkpV1UGEQUgn7ghaKGUwxbBtLhfVc2HV7TTfVn9OFFuwdgHsMdQf73peq2pXuHnIrK3ZfaoJAkEAh0nXg/NCAdRtw8C/s5L9feujujRVyt6SRMj0ApKi3ze2j2Ihf7u3XjbpgSRprzVNZpc0s3F/bm+O708HrCBJZwJBANPeVhBizgqPZOiQxLRxpNN2+EvEfs8js7YFRwB45orM/+9yVelNojEKxcHT7zS6j59dTlwvbGp6LVrKCrwtwLw=

Signaure Encoded         : HO4FLrLDt4ObECVWRiUGIGUimU1M70Y9aILT5op0UkV-kbEx8AqjCsLTh-Y1zOAisvFmuH5LYRw1wQyncQ5uEUWJYcoeldr-1_uFlpD2LqUy-QZfng8e6pxXOopL8Of_OcNEOqRijmI_dob8Gf0UnT7GQWpGTl32cIuuIFDeRHo
Signature Verified (t/f) : true

Line #24 of Itemizing 3 begins the creation of the JWT header. That is the xxxxx a part of a xxxxx.yyyyy.zzzzz JWT. As you’ll be able to see, the code is straightforward. Use Base64.getUrlEncoder().withoutPadding() for encoding and Base64.getUrlDecoder() for decoding.

NOTEMake certain to make use of the **.withoutPadding()** encoder. If not, trailing “=” characters might be added by the encoder to make the encoded string the required size. These trailing “=” aren’t allowed by the JWT specification so you probably have them, different JWT decoders received’t be capable to decode your JWT correctly.

Line #47 of Itemizing 3 begins the creation of the JWT payload, sometimes consumer data, however in principle could be something. That is the yyyyy a part of a xxxxx.yyyyy.zzzzz JWT. As you’ll be able to see, the code is straightforward. Use Base64.getUrlEncoder().withoutPadding() for encoding and Base64.getUrlDecoder() for decoding. See NOTE above about utilizing the .withoutPadding() encoder.

Line #90 of Itemizing 3 begins the creation of the JWT signature. That is the zzzzz a part of a xxxxx.yyyyy.zzzzz JWT. Itemizing 3 is an instance of utilizing the "alg":"RS256" aka SHA256withRSA algorithm. This can be a two-key, uneven algorithm which depends on a public/personal keypair created on Line #92. A Signature object is created on line #99 and it’s initialized with the personal key. Staring with line #108, see how the Signature is used to create a signature and the Base64.getUrlEncoder().withoutPadding() is used to encode the signature.

NOTEThe general public/personal keypair will have to be generated exterior the applying and stored in some sort of configuration retailer (file, git, database, and many others.). That is an train left as much as you.

Line #129 of Itemizing 3 begins the confirm course of. A Consumer might confirm a JWT it receives from an Authentication server to protect in opposition to tampering whereas in transit. To confirm a JWT created utilizing an uneven RSA SHA256 signature, the Consumer will want the public key. This sometimes is just not an issue since public keys are designed to be giving freely. Line #132 demonstrates the decision to .confirm().

That’s it for JWT with Uneven RSA SHA256 Signature.

Abstract

Most of this weblog is the code. Evaluation the code, prime to backside, it isn’t overly sophisticated. However now you understand how to create and confirm JWT values utilizing each a Symmetric HMAC SHA256 Signature and an Uneven RSA SHA256 Signature.

Take pleasure in!

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments