• Stars
    star
    533
  • Rank 83,238 (Top 2 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created about 6 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

Jwt-Spring-Security-JPA

Travis (.org) 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": "[email protected]",
    "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": "[email protected]",
    "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": "[email protected]",
    "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": "[email protected]",
    "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": "[email protected]"
}'

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": "[email protected]",
    "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/[email protected]'

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.

More Repositories

1

Competitive-Programming

Collection of all competitive code snippets
C++
22
star
2

NIT-J-Code-Compiler

Web based Compiler NIT J CSE 2013-17 Final Year Project
JavaScript
21
star
3

Websockets-Vertx-Flink-Kafka

A simple request response cycle using Websockets, Eclipse Vert-x server, Apache Kafka, Apache Flink.
Java
16
star
4

SpringBatch-KafkaDB

A small demo that leverages Spring batch's capabilities to do job processing and Apache Kafka's stream processing. A simple CSV file gets used up in a batch job which then writes it to a Kafka queue (and H2 database) for further processing.
Java
13
star
5

Production-Log-Management

Shell scripts to monitor production server logs and store the result in a file.
Shell
10
star
6

flink-couchbase-data-sink

A Flink job that reads a Json file (either one-time or continous poll) as its source and dumps it to couchbase as a sink using the asynchronous Couchbase SDK.
Java
9
star
7

Hungarian-Assignment-GUI

Python program to solve the assignment problem using Hungarian method
Tcl
8
star
8

InterviewBit-DP

My solutions for the DP section at www.interviewbit.com
Java
7
star
9

dropwizard-jdbi-unitofwork

Provides Unit of Work Support for a JDBI based Dropwizard backend
Java
6
star
10

Lesson-AspectJ-Demo

A short project for teaching the new batch of students, AspectJ as part of the training university
Java
5
star
11

CSE-UG-Lab-Practicals

[C++/Py] Collection of useful practicals plus extra stuff encountered during a four year CS undergraduate course
Python
5
star
12

Mess-App-Manager-Version

Contains source code for the Mess App (Munshi) for NIT Jalandhar
Java
4
star
13

RIP-POSIX-threads

An attempt to implement the routing information protocol using POSIX Threads (C Language).
C
4
star
14

Lesson-SpringJDBC-Demo

A short project for teaching the new batch of students, SpringJDBC as part of the training university
Java
4
star
15

Redis-Leaderboard

A primitive interactive leaderboard designed in Python leveraging Redis
Python
4
star
16

go-patterns

Various patterns to dabble with, in Golang
Go
3
star
17

Interaction-Graph

Creating and analyzing interaction graphs based on boolean functions
Java
2
star
18

Mess-App-Student-Version

Mess App (Student) Source for NIT Jalandhar.
Java
2
star
19

Google-Search-History-Parser

View the relevant google searches along with the timestamp from the google search archive
Python
1
star
20

Fuzzy-Classifier

Fuzzy Maximum Likelihood Classifier for single class extraction from an image with multiple classes
Java
1
star
21

async-metrics-codahale

Leverage Codahale metrics (or any Metric Registry for that matter) to provide metrics on methods that complete asynchronously.
Java
1
star
22

Guava-Angular-Spring-Demo

An app that is built to persuade my fellow developer mates at Accolite to use the Guava Framework (Google).
Java
1
star
23

jersey-log-utils

A set of useful utilities for the Jersey Server and Client log filters
Java
1
star