Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Security basics

Right now anyone can delete any post. Two things are needed. Authentication finds out who sent the request by checking a login and password. Authorization decides whether this user may do what they ask: for example, only the admin role may delete posts. In Quarkus the checks are described with the standard @RolesAllowed annotations, and the source of users is added with an extension.

Adding it

For learning we take the simplest source — users right in application.properties:

./mvnw quarkus:add-extension -Dextensions="elytron-security-properties-file"
# src/main/resources/application.properties
quarkus.security.users.embedded.enabled=true
quarkus.security.users.embedded.plain-text=true
quarkus.security.users.embedded.users.anna=changeme
quarkus.security.users.embedded.roles.anna=admin
quarkus.security.users.embedded.users.oleg=changeme
quarkus.security.users.embedded.roles.oleg=user
quarkus.http.auth.basic=true

Anna has the admin role, Oleg has user. quarkus.http.auth.basic=true turns on Basic authentication: the client sends the login and password in the Authorization header of every request. Plain-text passwords are fine only for learning; on a server users are kept in a database with password hashes, or tokens are used (see the end of the lesson).

Protecting a method

// src/main/java/com/example/blog/PostResource.java
@DELETE
@Path("/{id}")
@Transactional
@RolesAllowed("admin")
public Response delete(@PathParam("id") long id) {
    if (!Post.deleteById(id)) {
        throw new PostNotFoundException(id);
    }
    return Response.noContent().build();
}

@RolesAllowed("admin") (import jakarta.annotation.security.RolesAllowed) lets in only users with this role. The other methods of the resource stay open. Let's check three cases — without a password, as Oleg and as Anna:

curl -i -X DELETE http://localhost:8080/posts/1
curl -i -u oleg:changeme -X DELETE http://localhost:8080/posts/1
curl -i -u anna:changeme -X DELETE http://localhost:8080/posts/1
HTTP/1.1 401 Unauthorized
www-authenticate: basic

HTTP/1.1 403 Forbidden

HTTP/1.1 204 No Content

The -u flag passes the login and password. 401 means "I don't know who you are" — you need to log in. 403 means "I know who you are, but you may not". A wrong password also gives 401.

Who made the request

The current user is available in code through SecurityIdentity:

// src/main/java/com/example/blog/MeResource.java
package com.example.blog;
 
import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
 
import java.util.Set;
 
@Path("/me")
@Authenticated
public class MeResource {
 
    @Inject
    SecurityIdentity identity;
 
    @GET
    public Me me() {
        return new Me(identity.getPrincipal().getName(), identity.getRoles());
    }
 
    public record Me(String name, Set<String> roles) {
    }
}

@Authenticated on the class lets in any logged-in user, whatever the role.

curl -u oleg:changeme http://localhost:8080/me
{"name":"oleg","roles":["user"]}

Access annotations

AnnotationWho gets in
@PermitAllEveryone, even without logging in
@AuthenticatedAny logged-in user
@RolesAllowed("admin")Only users with the role
@DenyAllNobody

What is used in practice

Real APIs usually use tokens: the oidc extension checks tokens from Keycloak or another login server, smallrye-jwt checks JWT tokens signed with your key. The @RolesAllowed and @Authenticated annotations stay the same — only the source of users changes.

Common mistake

Basic authentication sends the password almost in plain text: the Authorization header is just the login and password in Base64, which is decoded in a second. Without HTTPS anyone in the middle of the network can see it. Use Basic only locally or over HTTPS, and do not keep real passwords in application.properties — this file goes into Git and into the built application.

Thanks for reading!

Donate to the site — we work hard for you.