D.S

paulbakker.io

JWT authentication with Vert.x, Keycloak and Angular 2 – Paul about software development

JWT authentication with Vert.x, Keycloak and Angular 2 – Paul about software development Paul about software development About Posts Recordings Paul Bakker Software architect, author of Modular Cloud Apps with OSGi and Java 9 Modularity Email Twitter Google+ LinkedIn Github Stackoverflow JWT authentication with Vert.x, Keycloak and Angular 2 Almost every web app requires some kind of user management, authentication and authorization. This is often custom build. I can’t even count the number of times I created something like this as part of a project. It’s also non trivial to create something truly reusable for this. With new standards emerging like Openid Connect and JWT, things start to look more promising. For the development of Cloud RTI I started searching for something that would support the following: Authentication and authorization in the frontend (Angular 2) Secure REST endpoints User and role management Integration with social providers (Facebook, Google etc.) Single sign-on over several applications There are several available tools and hosted services available that satisfy these requirements. The tool that we ended up choosing is Keycloak , a project from Red Hat. Keycloak is open source and is very actively developed. It supports several standards such as Openid Connect, JWT and OAuth2. The example application is structured the same way as many real applications. It has an Angular 2 frontend, and users must login to use the applications. Users can login using an account they create for the application, or using a social account. The frontend uses a Vert.x REST backend. Calls to the backend can only be done by authenticated users, and the backend logs which user requests the API (for demo purposes). The demo application uses Keycloak to handle authentication, authorization and user managment. The example project is available on GitHub . Getting Keycloak to run Before we can run the demo project we need to start Keycloak and set it up. The easiest way to get started with Keycloak is by using the available Docker container. When taking Keycloak to production you should probably think about persistence a little better, but we don’t need that right now. Start Keycloak using the following command: docker run -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin -p 8080:8080 jboss/keycloak You can now open localhost:8080 and login to Keycloak user admin/admin. In Keycloak we can setup different reamls. A realm contains users and groups. By creating multiple realms we can use the same Keycloak installation for several applications. In this case we’ll just use the master realm however. Before we can integrate the demo application we need to configure Keycloak for this. This configuration is done in a client. Create a new client with Client ID demo and Client Protocol openid-connect. In the screen that follows we can setup the client for a specific authentication flow. We want a setup where the user is redirected to Keycloak for authentication when he or she opens the application. After successful authentication the user should be redirect back to the application. We can do so in Keycloak using the Standard flow. The only configuration left is setting the right urls for our application. In this example we’ll just run on localhost on port 8000. Valid Redirect Urls: http://localhost:8000/* Web Origins: http://localhost:8000 The Vert.x backend The Vert.x backend starts a HTTP server that does the following: Serve the frontend static files Return a list of books on /api/books Log the user requesting /api/books Only authenticated users can access /api/books. public class Main { Vertx vertx = Vertx.vertx(); Router router = Router.router(vertx); Handlers handlers = new Handlers(); router.route("/api/*").handler(CorsHandler.create("http://localhost:4200/*") .allowedMethod(HttpMethod.GET) .allowedHeader("Authorization") .allowedHeader("Content-Type") .allowCredentials(true)); JsonObject config = new JsonObject() .put("public-key", "KEYCLOAK_PUBLIC_KEY") .put("permissionsClaimKey", "realm_access/roles"); JWTAuth authProvider = JWTAuth.create(vertx, config); router.route("/api/*").handler(JWTAuthHandler.create(authProvider)); router.route("/api/*").handler(handlers::userLogger); router.route("/api/books").handler(handlers::listBooks); StaticHandler keycloakStaticHandler = StaticHandler.create("webroot/keycloak"); router.route("/keycloak/*").handler(keycloakStaticHandler::handle); StaticHandler staticHandler = StaticHandler.create("webroot/dist"); router.route("/*").handler(staticHandler::handle); vertx.createHttpServer().requestHandler(router::accept).listen(8000); } Here we setup the handlers for the application. If you’re not familiar with Vert.x, you might want to learn about handlers first here . The most interesting part is the setup of the auth provider. We use JWT (JSON Web Token), which is supported out of the box by Vert.x. A token in JWT is self contained. This means we can validate the token using the publi