Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Backend MVP showcasing JWT (Json Web Token) authentication with multiple login, timeout / refresh / logout (with in memory invalidation) using Spring Security & MySQL JPA.

License

Notifications You must be signed in to change notification settings

isopropylcyanide/Jwt-Spring-Security-JPA

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

169 Commits

Repository files navigation

Jwt-Spring-Security-JPA

GitHub

A demo project explaining the backend authentication using JWT (Json Web Token) authentication using Spring Security & MySQL JPA.

There's support for the following features:

  • Conventional email/username based registration with admin support.
  • Conventional Login using Spring Security and generation of JWT token.
  • Multiple device login and logout support.
  • In memory store for blacklisting JWT tokens upon user logout.
  • Expiration bases email verification. Mail is sent upon registration.
  • Resend the email confirmation email if old one expires.
  • Forgot-password functionality with password reset token validations.
  • Admin protected urls leveraging Spring security.
  • Refresh JWT tokens once the temporary JWT expires.
  • Check availability of username/email during registration.


JWT

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.


Swagger Docs

The project has been configured with a Swagger docket that exposes the APIs with the schema

Accessible at http://localhost:9004/swagger-ui once the app is running.

image


Exception Handling

  • The app throws custom exceptions wherever necessary which are captured through a controller advice. It then returns the appropriate error response to the caller
  • Moreover, entities are validated using JSR-303 Validation constraints.

Getting Started

Clone the application

$ git clone https://github.com/isopropylcyanide/Jwt-Spring-Security-JPA.git
$ cd Jwt-Spring-Security-JPA

Create a MySQL database

$ create database login_db

Change MySQL username and password as per your MySQL installation

  • Edit spring.datasource.username and spring.datasource.password properties as per your mysql installation in src/main/resources/application.properties
  • Edit spring.mail.username and spring.mail.password properties as per your mail server src/main/resources/mail.properties

Run the app

./mvnw spring-boot:run # For UNIX/Linux based operating systems
mvnw.cmd spring-boot:run # For Windows based operating systems
  • The server will start on server.port:9004 and will create the tables for you.
  • Every run of the app will reset your state. To not do that, modify spring.jpa.hibernate.ddl-auto: update

API

Registering a User
curl --location --request POST 'localhost:9004/api/auth/register' \
--header 'Content-Type: application/json' \
--data-raw '{
 "email": "amangarg1995sep@gmail.com",
 "password": "amangarg",
 "registerAsAdmin": true
}'

image

⚠️ If you re-register an email twice, you'll get the "email in use" error


Logging in an unverified user
curl --location --request POST 'localhost:9004/api/auth/login' \
--header 'Content-Type: application/json' \
--data-raw '{
 "email": "amangarg1995sep@gmail.com",
 "password": "amangarg",
 "deviceInfo": {
 "deviceId": "D1",
 "deviceType": "DEVICE_TYPE_ANDROID",
 "notificationToken": "N1"
 }
}'

image


Confirming the user email verification token
curl --location --request GET 'localhost:9004/api/auth/registrationConfirmation?token=bcbf8764-dbf2-4676-9ebd-2c74436293b9' \
--header 'Content-Type: application/json' \
--data-raw '{
 "email": "a@b.com",
 "password": "HI12",
 "deviceInfo": {
 "deviceId": "D1",
 "deviceType": "DEVICE_TYPE_ANDROID",
 "notificationToken": "N1"
 }
}'

image

⚠️ If you pass the incorrect token you will get a "Token Mismatch error"

Don't know the token?: Check your email in mail.properties

Still didn't get it?: Look inside the database email_verification_token#token


Logging in the user with valid credentials
curl --location --request POST 'localhost:9004/api/auth/login' \
--header 'Content-Type: application/json' \
--data-raw '{
 "email": "amangarg1995sep@gmail.com",
 "password": "amangarg",
 "deviceInfo": {
 "deviceId": "D1",
 "deviceType": "DEVICE_TYPE_ANDROID",
 "notificationToken": "N1"
 }
}'

image

⚠️ If you do not enter correct credentials you will get a "Bad credentials error"

⚠️ If your email is not verified (refer the above API) you will get an "Unauthorized" error

❔ Device information is required to enable a multi device login and logout functionality.


Using the JWT token to access a user resource
curl --location --request GET 'localhost:9004/api/user/me' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNjM1NjE0NTY4LCJleHAiOjE2MzU2MTU0Njh9.d8CJYduoC44njutphODoezheSt_so3Doc9g1RSiMaDU_qJwY0_3Ym4092hFkHsh-jbyB_9i66LbwSEE-szAgEw'

image

⚠️ If you enter an invalid token (obtained post login), you will get an "Incorrect JWT Signature" error.

⚠️ If you enter a malformed JWT token, you will get a "Malformed JWT Signature" error.

⚠️ If you enter an expired JWT token (default: app.jwt.expiration, you will get an "Expired JWT Signature" error and clients should refresh the JWT token.

image


Using the JWT token to access an admin resource
curl --location --request GET 'localhost:9004/api/user/admins' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNjM1NjE0NTY4LCJleHAiOjE2MzU2MTU0Njh9.d8CJYduoC44njutphODoezheSt_so3Doc9g1RSiMaDU_qJwY0_3Ym4092hFkHsh-jbyB_9i66LbwSEE-szAgEw'

image

⚠️ If you registered a user with registerAsAdmin: false, then you will get a "Forbidden" error. image

⚠️ JWT has to be valid (same constraints as the above user resource API)


Logout user
curl --location --request POST 'localhost:9004/api/user/logout' \
--header 'Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNjM1NjE0NTY4LCJleHAiOjE2MzU2MTU0Njh9.d8CJYduoC44njutphODoezheSt_so3Doc9g1RSiMaDU_qJwY0_3Ym4092hFkHsh-jbyB_9i66LbwSEE-szAgEw' \
--header 'Content-Type: application/json' \
--data-raw '{
 "deviceInfo": {
 "deviceId": "D1",
 "deviceType": "DEVICE_TYPE_ANDROID",
 "notificationToken": "N1"
 }
}'

image

❔ Logging out also deletes the refresh token associated with the device. In real production, this token should be specifically invalidated.

⚠️ If the JWT isn't passed then you will get an "Unauthorized" error.

image

⚠️ If you try to log out same user twice (without an app restart), you will get a "Token Expired" error. This works because on logout we invalidate the JWT

image

⚠️ If you try to log out a logged-in user against an invalid device (say D2), you will get an "Invalid Device" error.

image


Request a reset password link for a registered user
curl --location --request POST 'localhost:9004/api/auth/password/resetlink' \
--header 'Content-Type: application/json' \
--data-raw '{
 "email": "amangarg1995sep@gmail.com"
}'

image

❔ You can request a password reset multiple times. The reset token would be generated multiple times with an app.token.password.reset.duration

❔ You can request a password reset for a user even when they have not verified their email once. This is okay for our demo case.

⚠️ If you try to request a password reset for an unregistered user, you will get a "No matching user" error


Reset password for a registered user
curl --location --request POST 'localhost:9004/api/auth/password/reset' \
--header 'Content-Type: application/json' \
--data-raw '{
 "email": "amangarg1995sep@gmail.com",
 "password": "P1",
 "confirmPassword": "P1",
 "token": "880ab6f1-4b4b-4d04-92bd-8995b4063205"
}'

image

⚠️ If your new passwords do not match, there will be an error

⚠️ If your password reset token is not valid or is for some other user, you'll get a "Password Reset Token Not Found" error.

image

⚠️ If you try to use a password reset token twice, you will get a "Token Inactive" error image


Refreshing the JWT token for longer login sessions
curl --location --request POST 'localhost:9004/api/auth/refresh' \
--header 'Content-Type: application/json' \
--data-raw '{
 "refreshToken": "d029e0fa-80f5-4768-837c-7e85a0f94960"
}'

image

❔ You can refresh a JWT multiple times against the refresh token. That is the purpose of refresh. Refresh token expiry can be controlled with app.token.refresh.duration

⚠️ If you pass an invalid refresh token (obtained through login), you will get a "No token found" error

image


Check email in use
curl --location --request GET 'localhost:9004/api/auth/checkEmailInUse?email=amangarg1995sep@gmail.com'

image

❔ The API can be accessed insecurely and hence should be rate limited in production to prevent a DDOS attack.

❔ You can request a password reset for a user even when they have not verified their email once. This is okay for our demo case.

⚠️ If you try to request a password reset for an unregistered user, you will get a "No matching user" error


Roles

  • The spring boot app uses role based authorization powered by spring security
  • Tables and role data should have been created by default upon the first startup.
  • Any new user who signs up to the app is assigned the ROLE_USER by default.
  • In case the role entries aren't created, please execute the following sql queries in the database to insert the USER and ADMIN roles.
INSERT INTO `login_db.role` (ROLE_NAME)
VALUES ('ROLE_USER');
INSERT INTO `login_db.role` (ROLE_NAME)
VALUES ('ROLE_ADMIN');

Contribution

  • Remember, the project is a demo and should not be used into production directly.
  • Please fork the project and adapt it to your use case.
  • Submit a pull request with proper motivation and test plan.
  • Postman collection dump available here)
  • Not everything is in scope for this demo project. Feel free to fork the project and extend the functionality.
  • Project is equipped with a JUnit but lacks tests in most places. Would really appreciate your contributions here.

About

Backend MVP showcasing JWT (Json Web Token) authentication with multiple login, timeout / refresh / logout (with in memory invalidation) using Spring Security & MySQL JPA.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 11

AltStyle によって変換されたページ (->オリジナル) /