Implementing JWT

Let's consider the identity app once again. We implemented IdentityStore and AuthMechanism to authenticate the user, and then provided access to the user to invoke the /organization endpoint.

We will modify this project to demonstrate the JWT. We will also add a new /login resource, which takes the user ID and password in the header, and validates it against IdentityStoreas explained earlier. Let's write this sequence to understand what we intend to do:

As shown in the preceding sequence diagram,  /login is the entry point that takes the user's credentials, which we then validate using the IdentityStore, before generating the JWT token and returning it as a response. The end user passes this JWT to invoke the /organization API.

Let's take a look at these steps in detail:

Once the user is authenticated against our custom identity store, we will invoke the createJWT() function, as follows:

public fun createJwt(id: String, issuer: String, subject: String, 
expiryTime: Long): String {
val signatureAlgorithm = SignatureAlgorithm.HS256
val currentTimeInMillis = System.currentTimeMillis()
val date = Date(currentTimeInMillis)
val apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET)
val signingKey = SecretKeySpec(apiKeySecretBytes,
signatureAlgorithm.getJcaName())

val builder = Jwts.builder()
.setId(id)
.setIssuedAt(date)
.setSubject(subject)
.setIssuer(issuer)
.setAudience(AUDIENCE)
.signWith(signatureAlgorithm, signingKey)

if (expiryTime >= 0) {
val expMillis = currentTimeInMillis + expiryTime
val exp = Date(expMillis)
builder.setExpiration(exp)
}
return builder.compact()
}

This function takes an ID, jwtId, an issuer, a subjectand expiryTime as input arguments. We use the HMACSHA256 algorithm and a defined secret to generate the JWT, and use the Jwts.builder() method from the jjwt library to create the token. We will return this token in response to the /login API.

Let's invoke a curl command for the /login API with valid credentials, as follows:

curl -X POST 
http://localhost:8080/login
-H 'Accept: application/json'
-H 'Content-Type: application/json'
-H 'UserId: testUser'
-H 'Password: testUserPass'

The output of the preceding REST API call is as follows:

The /login API returns a JWT token, valid for 15 minutes. We passed the expiry time of fifteen minutes when generating the token.

Now let's try to invoke the GET organization API with an invalid authorization header and see what happens:

curl -X GET 
http://localhost:8080/organization/4c118afd-eccb-4ac7-bcfc-15e47f10770a
-H 'Accept: application/json'
-H 'Authorization: Bearer 123'
-H 'Content-Type: application/json'

The output of the preceding REST invocation is as follows:

An invalid authorization header resulted in a 403 response.

Now, let's pass the valid JWT that we obtained in the authorization header, as follows:

curl -X GET 
http://localhost:8080/organization/4c118afd-eccb-4ac7-bcfc-15e47f10770a
-H 'Accept: application/json'
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjM0IiwiaWF0IjoxNTM1MDAwNzEzLCJzdWIiOiJzdWIxMjMiLCJpc3MiOiJsb2NhbGhvc3QiLCJhdWQiOiIvand0dG9rZW4iLCJleHAiOjE1MzUwMDE2MTN9.1ZWJlw4zj3xGTghq9Q36GYpy_7cxYCbCN-QJhJ1s_Lk'
-H 'Content-Type: application/json'

The output of the preceding REST call is as follows:

Now, the  GET organization API returns the organization details in response.

So, we have looked at how a REST API can be secured with JWT with a simple use case. In real-world applications, the complexity can be increased by using private and public keys while generating and verifying the JWT.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset