sexta-feira, 27 de dezembro de 2019

Quarkus Application with Form Authentication using Database



Let's create a simple Quarkus application that uses databases table for authorization and authentication. This tutorial uses MariaDB and Quarkus 1.1.0.Final.

Database configuration


Remember to NEVER store plain text in the database. Elytron has the tools to use bcrypt for password encryption as described in the Quarkus JDBC security guide.


We need to configure the database tables where the user, password and roles will be stored. Let's create the tables in the database:

* User table keeps the username and password;
* Roles is where you can find all the system roles;
* User_role is user mapping to their roles

Which translated to the following SQL:

create table user(id int primary key, 
                            username varchar(100) unique, 
                            password varchar(1000));

create table role(id int primary key, name varchar(100));

create table user_role(user_id int references user(id), 
                                    role_id int references role(id), 
                                    primary key (user_id, role_id));


Create a database with the tables above and it will allow us to retrieve user information from the database.

Create Quarkus application

Generating an application

Go to code.quarkus.io, fill groupId, artifactId and version, then select the extension JDBC Driver - MariaDB* and Elytron Security JDBC Realm. Download the application, unzip it and import in the IDE you want. I will use VSCode with Quarkus extension and Java tooling.

* Change the JDBC driver according to the database you are using.


Application configuration


We need to configure at least 3 things:

* Datasource that connects to the database;
* Specific security JBDC configuration;
* Permissions

It translates to the following in application.properties:

### 1 - DATASOURCE CONFIGURATION ###
quarkus.datasource.url=jdbc:mysql://localhost:3306/quarkus_form_example
quarkus.datasource.driver=org.mariadb.jdbc.Driver
quarkus.datasource.username=root

### 2 - SECURITY CONFIGURATION ###
quarkus.http.auth.form.enabled=true
quarkus.security.jdbc.enabled=true
quarkus.security.jdbc.principal-query.sql=select... see below
quarkus.security.jdbc.principal-query.clear-password-mapper.enabled=true
quarkus.security.jdbc.principal-query.clear-password-mapper.password-index=1
quarkus.security.jdbc.principal-query.attribute-mappings.0.index=2
quarkus.security.jdbc.principal-query.attribute-mappings.0.to=groups

### 3 - SECURITY URIS MAPPING ###
quarkus.http.auth.permission.permit1.paths=/secured/*
quarkus.http.auth.permission.permit1.policy=authenticated


The value for property quarkus.security.jdbc.principal-query.sql is:

select u.password, r.name from user u, user_role ur,role r where u.id = ur.user_id AND r.id = ur.role_id and u.username = ? group by u.password;

In section one we configure how to connect to a database where all credentials are stored. In 2 the security specific properties for JDBC and we also make sure that it will use form authentication by telling how to retrieve the principal, password and roles from the database (notice the question mark, which is where quarkus will add the username) and finally we may map security policies to URIs. In the example above we just say that content under /secured will only be accessible by logged users. We will add more authorization in the application HTTP endpoints.

Authorization


Let's create a resource specific for manager and user and another one only for manager. In the index page some content will only show  if you are logged as admin or user.

Finally we can focus on the user interface. Let's create very simple pages to show the authorization and authentication in action.

Create pages


See the most import parts of the pages used in our application:

error.html: User is redirected to this page when login fails
login.html: The login page should send the credentials to the authentication endpoint passing the username and the password
secured/index.html: very simple page to show access to a secured static resource
index.html: This is where we show content according to the logged user which makes it a little more complex

Notice the content_public, content_user and content_manager headers in index.html, they are filled by Javascript and for this we use JQuery, see the script tags at the end of index.html.
An interesting method is logout. What we do is simply cancel the session cookie! The other logic in script is to try to retrieve content from the server and change the DOM accordingly.

Finally we are done! Now our index page content changes according to the logged user, see the result:


The source code can be found on my github.

Nenhum comentário:

Postar um comentário