This blog post explains the JSON web token(JWT) authentication using Spring Security, Spring Boot, Spring Data and Angular. Source code uploaded to Github repository
Image by MasterTux from Pixabay
Introduction
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.
JWT Token structure
In its compact form, JSON Web Tokens consist of three parts separated by dots (.
), which are:
- Header
- Payload
- Signature
Therefore, a JWT typically looks like the following.
xxxxx.yyyyy.zzzzz
Header
The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA.
For example:
{
"alg": "HS256",
"typ": "JWT"
}
Then, this JSON is Base64Url encoded to form the first part of the JWT.
Payload
The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.
Signature
To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. Please read https://jwt.io/introduction/ for detailed workflow and description
Technologies
- Spring Boot 2.2.x
- Spring Security
- Spring Data JPA
- Java JWT library
- H2 embedded database
Implementation
There are many open-source JWT implementations available for all languages. In this blog post, we use Java jjwt library in this blog post.
pom.xml
- Create an empty spring boot project with spring boot, security dependencies and add dependencies as shown above
- Create UserController class that accepts username and password parameters and authenticates users through UsernamePasswordAuthenticationToken class
@PostMapping(value = {**"/authenticate"**,**"/login"**})
**public** Object loginUser(@RequestParam String username, @RequestParam String password)
{
Authentication authentication=**authenticationManager**.authenticate( **new** UsernamePasswordAuthenticationToken(username, password));
**return** mapUserAndReturnJwtToken(authentication,**true**);
}
4. Create SecurityConfig class(shown below) that defines standard Spring Security configuration for the project.
5. Method public void configure(HttpSecurity http)
allows all requests to login URLs since authentication is being done manually through in UserController class
SecurityConfig.java
6. JwtUtil class is responsible to issue and validate the tokens. In particular, createToken()
method creates token with 24 hours expiration and sign with custom key from properties file(make sure keep this long and hard to guess)
JwtUtil.java
7. validateToken()
method validates the supplied token by validating the expiration date
8. Create JwtRequestFilter filter that intercepts all requests from client and looks for Bearer token. If the token is present, extract the username and validate the expiration date.
9. If the token is valid, create new UsernamePasswordAuthenticationToken and set userDetails and userDetails authorities. Save this as Spring Security authentication object, which tells spring security that this user is authenticated and continue with security chain.
10. In order for this filter to work, in SecurityConfig add it before UsernamePasswordAuthenticationFilter
http.addFilterBefore(**jwtRequestFilter**,UsernamePasswordAuthenticationFilter.**class**);
11. To show case the demo, generated Angular project with 2 pages. Login and Home page
Testing
- This project uses in H2 memory database as database. And
schema.sql
file in src/main/resources directory creates the required tables anddata.sql
file inserts sample users and roles - Run the spring boot class JwtSpringSecurityApplication to start the application
- Now go to http://localhost:8080/h2-console to see the database and enter the credentials(shown below)
4. Check the existing users with the query SELECT * FROM CORE_USER.
If you do not see any results, copy SQL statements from data.sql
in src/main/resources and execute it
5. Now go to src/webapp directory and install all dependencies
$ npm install
6. Start the Angular application with the following command
$ npm run start --watch
7. Now go to http://localhost:4200 and you will be redirected to login page
8. Enter credentials admin/admin and you will be redirected to home page.
9. In home page, during initial load we use the token from previous page(stored as cookie) and get user information by presenting that token to spring boot application(just to make sure that token is valid)
9. See the network tab for JWT token with expiration date
Conclusion
Code is uploaded to Github for reference, Happy Coding :)
Top comments (0)