Skip to content

hendisantika/spring-boot-rest-api-jwt-authentication-sample1

Repository files navigation

Spring Boot JWT Authentication using Spring Security

In this article, I’ll explain how we can implement a JWT (JSON Web Token) based authentication layer on Spring Boot CRUD API using Spring Security. Basically this JWT authentication layer will secure the API to avoid unauthorized API access.

Technologies Going to Use,

  • Java 1.8
  • Spring Boot: 2.3.4.RELEASE
  • Spring Security
  • JPA
  • MySQL
  • Lombok
  • Gradle
  • Intellij Idea for IDE

Main topics I’m going to discuss here,

  • What is JWT ?
  • How Does JWT Based Authentication work with Spring Boot?
  • Adding Required Dependencies
  • Developing API
    • Defining API Endpoints
    • Spring Security Related Implementation
      • API User Specific API Development
      • Authentication Filter with UsernamePasswordAuthenticationFilter
        • What is the use of Authentication Filter ?
      • JWT Authorization Filter with BasicAuthenticationFilter
        • What is the use of JWT authorization Filter ?
      • Authentication User Detail Service to Read User From Database
      • Security Configuration With WebSecurityConfigurerAdapter
    • Testing API with JWT Authentication
    • More Configurations inside JWT based Authentication Layer
      • Send JWT Authentication Token in Response Body After Successful Login
      • Role Based Authentication with JWT
    • Conclusion

What is JWT ?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. – Definition from JWT.io

Basically, JWT allows us to digitally signed a way of transmitting information between parties and when tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it. So no one can breach into the claims without the private key.

Follow official documentation for more details about JWT from here.

How Does JWT Based Authentication work with Spring Boot?

Here is the sequence diagram for how JWT in action inside Spring Boot application with Spring security.

JWT Work

Defining API Endpoints

This API is design to demonstrate a simple API that covers CRUD Operations in a library scenario where books and author data are stored and members can burrow any book if it is available.

Additionally, Here we need two additional APIs to accomplish our authentication layer interagration.

Those are API endpoints to Register new API consume user and endpoint to Login and retrieve JWT for successful authentication.

So our main API endpoints will be as follows:

Endpoint HTTP Method Description
/api/user POST Create user to consume API.
/login POST Request JWT token with Login request using auth credentials.
/api/library/author POST Register New Author.
/api/library/book GET Read all books from database.
/api/library/book?isbn=1919 GET Read book by ISBN
/api/library/book/:id GET Read book by ID
/api/library/book POST Register New Book
/api/library/book/:id DELETE Remove a book
/api/library/book/lend POST Lend a book to a member
/api/library/member POST Register member
/api/library/member GET List all members
/api/library/member/:id PATCH Update a member

and the base architecture will be like below:

Flow

Testing API with JWT Authentication

First let’s start with creating a API user with password who is allowed to generate JWT token to access other API endpoints.

curl --location --request POST 'http://localhost:8080/api/user' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username":"naruto",
    "password": "naruto"
}'

Now we have a user with the correct credentials in our database. Then we can generate an authentication token using those credentials as below.

curl -i --location --request POST 'http://localhost:8080/login' --header 'Content-Type: application/json' --data-raw '{
    "username": "naruto",
    "password": "naruto"
}'

Sending API request with authentication token we got from JWT authentication. Here we just needs to add authentication token with the token prefix which is Bearer here as an Authorization header and send the request.

curl --location --request POST 'http://localhost:8080/api/library/author' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJqdGRfYXBpX3VzZXIiLCJleHAiOjE2MDY1MDE4MjJ9.2TBlaqqmXcXUEIU97c1VuRwmJJphZTIAcOd9u6YLYSw8cBFTdJkyYGcwKOrre9TaG-0_E1kY_vqJasPCDiQTIg' \
--data-raw '{
    "firstName": "Uzumaki",
    "lastName": "Naruto"
}'
curl --location --request POST 'http://localhost:8080/api/user' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username":"naruto",
    "password": "naruto",
    "role": "ADMIN"
}'

All cURL

Add New User

curl --location --request POST 'http://localhost:8080/api/user' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username":"sasuke",
    "password": "sauke",
    "role": "ADMIN"
}'

User Login

curl --location --request POST 'http://localhost:8080/login' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username": "naruto",
    "password": "naruto"
}'

Register New Author

curl --location --request POST 'http://localhost:8080/api/library/author' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName": "Hendi",
    "lastName": "Santika"
}'

Register New Book

curl --location --request POST 'http://localhost:8080/api/library/book' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Mudah belajar Spring Boot2",
    "isbn": "1234",
    "authorId": 1
}'

Read all books from database

curl --location --request GET 'http://localhost:8080/api/library/book' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \

Read book by ISBN

curl --location --request GET 'http://localhost:8080/api/library/book?isbn=1234567890' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \

Read book by ID

curl --location --request GET 'http://localhost:8080/api/library/book/1' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \

Remove a book

curl --location --request DELETE 'http://localhost:8080/api/library/book/3' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \

Lend a book to a member

curl --location --request POST 'http://localhost:8080/api/library/book/lend' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \
--header 'Content-Type: application/json' \
--data-raw '{
    "bookIds": [1],
    "memberId": 1
}'

List All members

curl --location --request GET 'http://localhost:8080/api/library/member' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \

Update a member

curl --location --request PATCH 'http://localhost:8080/api/library/member/3' \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJuYXJ1dG8iLCJyb2xlIjoiQURNSU4iLCJleHAiOjE2NTg2MjMyOTB9.XVUHB5kbzMPJdG6_jMnHgOP1-PzEquzuN3HoxqJ3xkaFvHgVmWzY57X_8uLKr9gsLEZo-b3nH2nrICs_2JGNQw' \
--header 'Content-Type: application/json' \
--data-raw '{
    "firstName": "Uchiha",
    "lastName": "Madara"
}'

About

Spring Boot JWT Authentication using Spring Security

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages