# Basic-Authentication für Single-User-Applikation mit Quarkus

Wir haben eine simple Single-User-Applikation mit Quarkus geschrieben und möchten dieser nun für den Admin-Bereich einen Zugriffsschutz hinzufügen. Es reicht uns vollkommen aus Basic Authentication zu nutzen und die Benutzerdaten embedded (aber konfigurierbar) zu speichern.

Diese Aufgabe ist eigentlich schnell erledigt, aber leider etwas wirr bzw. umständlich  [dokumentiert](https://quarkus.io/guides/security#basic-and-form-authentication-mechanisms)  [[2]](https://quarkus.io/guides/security-properties).  

# Konfiguration 

Die komplette Arbeit können wir in unserer `application.properties` erledigen:

```properties
quarkus.http.auth.basic=true
quarkus.http.auth.policy.admin-policy.roles-allowed=admin
quarkus.http.auth.permission.admin-permission.paths=/admin*
quarkus.http.auth.permission.admin-permission.policy=admin-policy
quarkus.security.users.embedded.enabled=true
quarkus.security.users.embedded.plain-text=true
quarkus.security.users.embedded.users.admin=password
quarkus.security.users.embedded.roles.admin=admin
```

Gehen wir die Konfiguration Zeile für Zeile durch:

1. Basic Authentication aktivieren
* Policy mit dem Namen `admin-policy` erstellen zu der alle Benutzer mit der Rolle `admin` gehören
* Permission namens `admin-permission` erstellen und den Pfad `/admin*` zuweisen (das `*` dient hier als Wildcard. Der Pfad matched also sowohl auf `/admin` als bspw. auch auf `/admin/foo/bar`)
* Zuvor erstellte `admin-permission` die Policy `admin-policy` hinzufügen
* Embedded Benutzerverwaltung aktivieren
* Klartextpasswörter aktivieren (ansonsten werden die Passwörter in dem Format `HEX( MD5( username ":" realm ":" password ) )` erwartet
* Benutzer `admin` mit dem Passwort `password` erstellen
* Benutzer `admin` die Rolle `admin` zuweisen

## Dependencies

Nun müssen wir nur noch die auf [WildFly Elytron](https://docs.wildfly.org/12/WildFly_Elytron_Security.html) basierte Quarkus-Extension unserer `pom.xml` als Abhängigkeit hinzufügen

```
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-elytron-security-properties-file</artifactId>
</dependency>
```

## Resources

Erstellen wir nun noch zwei Resources bzw. Endpoints um unserer Setup zu testen. 

```java
@Path("/admin")
public class AdminResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello admin";
    }
}
```

```java
@Path("/public")
public class PublicResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "hello user";
    }
}
```

Der `/admin`-Endpoint dürfte nur für den `admin`-Benutzer zugreifbar sein und `/public` für jeden - auch unauthentifizierten - Benutzer. Testen wir das einfach.

## Tests

```java
@QuarkusTest
public class AdminResourceTest {

    @Test
    public void testAdminEndpoint() {
        given()
                .when()
                .auth().basic("admin", "password")
                .get("/admin")
                .then()
                .statusCode(Response.Status.OK.getStatusCode())
                .body(is("hello admin"));
    }

    @Test
    public void testAdminEndpoint_WithoutAuth() {
        given()
                .when().get("/admin")
                .then().statusCode(Response.Status.UNAUTHORIZED.getStatusCode());
    }
}
```

```java
@QuarkusTest
public class PublicResourceTest {

    @Test
    public void testPublicEndpoint() {
        given()
                .when().get("/public")
                .then()
                .statusCode(Response.Status.OK.getStatusCode())
                .body(is("hello user"));
    }
}
```

Funktioniert!

## Fazit

Die gestellte Aufgabe ist wirklich schnell und einfach gelöst. Leider ist die  [Dokumentation](https://quarkus.io/guides/security#basic-and-form-authentication-mechanisms) [[2]](https://quarkus.io/guides/security-properties) dazu etwas wirr bzw. umständlich gehalten. Das mag sicherlich daran liegen, dass die geschilderte Anforderung doch eher die Ausnahme darstellt und man üblicherweise eine Lösung wie OAuth oder LDAP integrieren möchte.

Die beschriebene Konfiguration könnte nun auch problemlos um weitere Benutzer, Rollen, Permissions und Policies erweitert werden. Man sollte sich jedoch fragen, ob es bei einer Multi-User-Applikation nicht sinnvoller ist zumindest die Benutzerverwaltung in eine Datenbank zu schieben, wenn nicht sogar eher eine der bereits genannten Lösungen zu nutzen.

Eine lauffähige Demo ist auf Github zu finden: https://github.com/pklink/quarkus-simple-basic-auth

*(Titelbild von  [Ivan Bandura](https://flic.kr/p/e3qsFM))*
