Coder Social home page Coder Social logo

cassiomolin / jersey-jwt Goto Github PK

View Code? Open in Web Editor NEW
159.0 14.0 37.0 53 KB

Example of REST API with JWT authentication using Jersey, Jackson, Undertow, Weld, Hibernate and Arquillian.

License: MIT License

Java 100.00%
jersey jwt jwt-authentication rest-api rest jackson java postman undertow weld cdi jax-rs hibernate jpa arquillian

jersey-jwt's Introduction

REST API with JWT authentication using Jersey and CDI

Build Status MIT Licensed

This example application demonstrates how to perform token-based authentication using:

  • Jersey: JAX-RS reference implementation for creating RESTful web services in Java.
  • Jackson: JSON parser for Java.
  • Undertow: Servlet container.
  • Weld: CDI reference implementation.
  • Hibernate ORM: Persistence framework for relational databases (JPA implementation).
  • Arquillian: Testing framework.
  • JJWT: Library for creating and parsing JSON Web Tokens (JWTs) in Java.
  • jBCrypt: Implementation for the bcrypt password hashing function in Java.
  • H2: In memory relational database.

This example is inspired in my Stack Overflow best answer about token-based authentication in Jersey.

Note: For an implementation using Spring Security, have a look at the jersey-jwt-springsecurity project.

How token-based authentication works?

In a token-based authentication, the client exchanges hard credentials (such as username and password) for a piece of data called token. Instead of sending the hard credentials in every request, the client will send the token to the server to perform authentication and authorisation.

In a few words, an authentication scheme based on tokens follow these steps:

  1. The client sends their credentials (username and password) to the server.
  2. The server authenticates the credentials and issues a token.
  3. The server can store the previously generated token in some storage along with the user identifier.
  4. The server sends the generated token in the response.
  5. In each request, the client sends the token to the server.
  6. The server, in each request, extracts the token from the incoming request. With the token, the server looks up the user details to perform authentication and authorisation.
    1. If the token is valid, the server accepts the request.
    2. If the token is invalid, the server refuses the request.
  7. The server can provide an endpoint to refresh tokens.

What tokens can be like?

A token can be opaque which reveals no details other than the value itself (like a random string) or can be self-contained (like JWT, which is used in this example).

JWT stands for JSON Web Token. It's a standard method for representing claims securely between two parties, defined in the RFC 7519. JWT is a self-contained token and enables you to store a user identifier, an expiration date and whatever you want (but don't store passwords) in a payload, which is a JSON encoded as Base64. The payload can be read by the client and the integrity of the token can be easily checked by verifying its signature on the server.

To find some great resources to work with JWT, have a look at http://jwt.io.

JWT allows you to perform stateless authentication, that is, you won't need to persist JWT tokens if you don't need to track them. Although, by persisting the tokens, you will have the possibility of invalidating and revoking the access of them. To keep the track of JWT tokens, instead of persisting the whole token, you could persist the token identifier (the jti claim) and some metadata (the user you issued the token for, the expiration date, etc) if you need.

Your application can provide some functionality to revoke the tokens, but always consider revoking the tokens when the users change their password. When persisting tokens, consider removing the old ones in order to prevent your database from growing indefinitely.

Building and running this application

To build and run this application, follow these steps:

  1. Open a command line window or terminal.
  2. Navigate to the root directory of the project, where the pom.xml resides.
  3. Compile the project: mvn clean compile.
  4. Package the application: mvn package.
  5. Change into the target directory: cd target
  6. You should see a file with the following or a similar name: jersey-jwt-1.0.jar.
  7. Execute the JAR: java -jar jersey-jwt-1.0.jar.
  8. The application should be available at http://localhost:8080/api.

When the application starts up, the database will be populated with the following users:

ID Username Password Active Roles
1 admin password true ADMIN, USER
2 user password true USER
3 disabled password false USER

Quick words on Undertow and uber-jars

This application is packed as an uber-jar, making it easy to run, so you don't need to be bothered by installing a servlet container such as Tomcat and then deploy the application on it. Just execute java -jar <jar-file> and the application will be up and running.

This application uses Undertow, a lighweight Servlet container designed to be fully embeddable. It's used as the default web server in the WildFly Application Server.

The uber-jar is created with the Apache Maven Shade Plugin, that provides the capability to create an executable jar including its dependencies.

Application overview

Find below a quick description of the most relevant classes of this application:

REST API overview

See the curl scripts below with the REST API supported operations:

Exchange hard credentials for an authentication token

Valid credentials must be sent in the request payload to be exchanged for a token.

curl -X POST \
  'http://localhost:8080/api/auth' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "username": "<username>",
  "password": "<password>"
}'

Get a public greeting

No authentication is required to perform this operation.

curl -X GET \
  'http://localhost:8080/api/greetings/public' \
  -H 'Accept: text/plain'

Get a greeting for the user

Authentication and USER role are required to perform this operation.

curl -X GET \
  'http://localhost:8080/api/greetings/protected' \
  -H 'Accept: text/plain' \
  -H 'Authorization: Bearer <authentication-token>'

Get all users

Authentication and ADMIN role are required to perform this operation.

curl -X GET \
  'http://localhost:8080/api/users' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <authentication-token>'

Get a user by id

Authentication and ADMIN role are required to perform this operation.

curl -X GET \
  'http://localhost:8080/api/users/<user-id>' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <authentication-token>'

Get the current user

No authentication is required to perform this operation. However, if the request is performed with a valid token, the server will return details for the current user.

curl -X GET \
  'http://localhost:8080/api/users/me' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer <authentication-token>'

Targeting the REST API with Postman

Alternatively to curl, you can use Postman to target the REST API. The Postman collection files are available in the src/main/postman directory.

jersey-jwt's People

Contributors

cassiomolin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jersey-jwt's Issues

Question: Persistent login

Hi,
I wondered if there was a pattern for persisting login credentials on the client so that the user doesn't have to re-enter credentials.
I'm persisting the JWT Token, and then refreshing upon login, but that will obviously only work for validFor seconds, after which time the request request will be rejected.
Thanks

Error refreshing token

When I send a request POST to http://localhost:8080/api/auth/refresh, I got error in class AuthenticationResource, method refresh() in line 70:
AuthenticationTokenDetails tokenDetails = ((TokenBasedSecurityContext) securityContext).getAuthenticationTokenDetails();

javax.servlet.ServletException: java.lang.ClassCastException: org.glassfish.jersey.server.internal.process.SecurityContextInjectee cannot be cast to com.cassiomolin.example.security.api.TokenBasedSecurityContext
at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:489)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
...

Is @RolesAllowed annotation missing?

According to your explanations, secured resource should have @RolesAllowed annotation on method definition.

But when I look at getProtectedGreeting() method there is no annotation. How the system will know that it will have to perform both authorization and authentication on this method?

@GET
@Path("protected")
@Produces(MediaType.TEXT_PLAIN)
public Response getProtectedGreeting() {
    String username = securityContext.getUserPrincipal().getName();
    return Response.ok(greetingService.getGreetingForUser(username)).build();
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.