quarkus: Quarkus 1.13.0: `401 Unauthorized` using different host names for Keycloak

Describe the bug

The authorization configuration for endpoints based on quarkus.http.auth properties that was working on Quarkus 1.12.2 provides a 401 Unauthorized once migrated to Quarkus 1.13.0. At my understanding, the issue is triggered by requesting the access token to Keycloak using a URL that is different from the one in the application’s configurations for the property quarkus.oidc.auth-server-url. But this seems to a fair common situation for a K8s/OCP deployment:

  1. a Web UI running in a client’s browser requests the access token using the keycloak’s external URL
  2. the backend endpoint receives the access token and validates it using the k8s’ service name associated with Keycloak

Expected behavior

Having the requests to be authorized.

Actual behavior

Requests are unauthorized.

To Reproduce

Reproducer based on security-keycloak-authorization-quickstart available at https://github.com/mrizzi/quarkus-quickstarts/tree/401-unauthorized/security-keycloak-authorization-quickstart

Steps to reproduce the behavior (based on the commands from https://quarkus.io/guides/security-keycloak-authorization):

  1. start keycloak within a container in docker/podman
  2. ./mvnw clean compile quarkus:dev
  3. request the access token using the host’s IP (e.g. 192.168.49.1):
    export access_token=$(\                                                                          
     curl --insecure -X POST https://192.168.49.1:8543/auth/realms/quarkus/protocol/openid-connect/token \
     --user backend-service:secret \
     -H 'content-type: application/x-www-form-urlencoded' \
     -d 'username=alice&password=alice&grant_type=password' | jq --raw-output '.access_token' \
    )
    
  4. curl -v -X GET http://localhost:8080/api/users/me -H "Authorization: Bearer "$access_token gives 401 Unauthorized
  5. restart the application with ./mvnw clean compile quarkus:dev -Pquarkus-12 (a profile I’ve added to use Quarkus 1.12.2)
  6. request the access token using the host’s IP as above
  7. curl -v -X GET http://localhost:8080/api/users/me -H "Authorization: Bearer "$access_token works (i.e. provided {"userName":"alice"})

I’ve also added the quarkus-999 profile to check if the issue was already fixed upstream but it’s not solved.

Configuration

I’ve disabled the policy enforcer to use the Quarkus integrated web security layer because it’s the one we’re using in our application. The OIDC part is unchanged.

# Configuration file
quarkus.oidc.auth-server-url=https://localhost:8543/auth/realms/quarkus
quarkus.oidc.client-id=backend-service
quarkus.oidc.credentials.secret=secret
quarkus.oidc.tls.verification=none
quarkus.http.cors=true

# Enable Policy Enforcement
#quarkus.keycloak.policy-enforcer.enable=true

# Disables policy enforcement for a path
#quarkus.keycloak.policy-enforcer.paths.1.path=/api/public
#quarkus.keycloak.policy-enforcer.paths.1.enforcement-mode=DISABLED

quarkus.http.auth.permission.authenticated.paths=/api/users/*
quarkus.http.auth.permission.authenticated.policy=authenticated
quarkus.http.auth.policy.role-policy.roles-allowed=admin
quarkus.http.auth.permission.role.paths=/api/admin/*
quarkus.http.auth.permission.role.policy=role-policy
quarkus.http.auth.permission.permit.paths=/api/public/*
quarkus.http.auth.permission.permit.policy=permit

Environment (please complete the following information):

Output of uname -a or ver

Linux fedora-p1 5.11.10-200.fc33.x86_64 #1 SMP Thu Mar 25 16:51:31 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "11.0.10" 2021-01-19
OpenJDK Runtime Environment 18.9 (build 11.0.10+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.10+9, mixed mode, sharing)

GraalVM version (if different from Java)

Quarkus version or git rev

1.13.0

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 33 (33 by maintainers)

Most upvoted comments

@mrizzi Can you please add

quarkus.log.category."io.quarkus.oidc.runtime.OidcProvider".min-level=TRACE
quarkus.log.category."io.quarkus.oidc.runtime.OidcProvider".level=TRACE

and check what is being logged ?

thanks

@sberyozkin my opinion right now is that we will wait for quarkus.oidc.token.issuer=any to be available from #16324 so that we can keep our k8s/OCP templates basic as they’re without any need for manual intervention only for development purposes

Then when my team will work on creating an operator, we will enforce there all the “production level” security requirements

@mrizzi

Ok, thanks for the tests - so it looks not bad in 1.13.x with KEYCLOAK_FRONTEND_URL - looks like it affects how Keycloak sets the issuer in the discovery doc and in the iss claim - same value - so no need to customize with the property ; combined with the possibility of skipping the authentication completely, it should cover this issuer space qutie well

@sberyozkin maybe I’m wrong but was this a bug of previous Quarkus versions? I mean, is Quarkus 1.13.0 working as expected about issuer validation? It seems like previously the issuer validation was done only if quarkus.oidc.token.issuer property was provided (ref. OidcUtils#validateClaims in Quarkus 1.12.2) If the failure comes from the Iss validator, then if I add the quarkus.oidc.token.issuer=https://192.168.49.1:8543/auth/realms/quarkus property it works. If all confirmed, the only improvement I can see would be to have quarkus.oidc.token.issuer to become a list of values rather than only one to be able to have both internal and external URLs as valid issuers without having to choose only one. Does it make sense?