Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quarkus tries to use client_credentials grant type when calling for JWT token to Keycloak, while it should use authorization_code. #5323

Closed
piotrgwiazda opened this issue Nov 8, 2019 · 12 comments
Labels
area/oidc kind/bug Something isn't working
Milestone

Comments

@piotrgwiazda
Copy link

piotrgwiazda commented Nov 8, 2019

Describe the bug
Quarkus tries to use client_credentials grant type when calling for JWT token to Keycloak, while it should use authorization_code.
Expected behavior
Quarkus should follow the Authorization Code Grant flow to authorize the user using OAuth 2.0

Actual behavior

  • I access http://localhost:8080/
  • I'm redirected to Keycloak (url looks good with scope=openid+email&response_type=code&client_id=web-application
  • I log in with sample user account
  • I'm redirected back with the code
  • Then I get an exception in Quarkus
Caused by: org.keycloak.authorization.client.util.HttpResponseException: Unexpected response from server: 401 / Unauthorized / Response from server: {"error":"unauthorized_client","error_description":"Client not enabled to retrieve service account"}
    at org.keycloak.authorization.client.util.HttpMethod.execute(HttpMethod.java:95)
    at org.keycloak.authorization.client.util.HttpMethodResponse$2.execute(HttpMethodResponse.java:50)
    at org.keycloak.authorization.client.util.TokenCallable.obtainAccessToken(TokenCallable.java:121)
    at org.keycloak.authorization.client.util.TokenCallable.call(TokenCallable.java:57)
    at org.keycloak.authorization.client.resource.ProtectedResource.createFindRequest(ProtectedResource.java:276)
    at org.keycloak.authorization.client.resource.ProtectedResource.access$300(ProtectedResource.java:38)
    at org.keycloak.authorization.client.resource.ProtectedResource$5.call(ProtectedResource.java:205)
    at org.keycloak.authorization.client.resource.ProtectedResource$5.call(ProtectedResource.java:202)
    at org.keycloak.authorization.client.resource.ProtectedResource.find(ProtectedResource.java:210)

The error in Keycloak is:

09:58:25,420 WARN  [org.keycloak.events] (default task-30) type=CLIENT_LOGIN_ERROR, realmId=quarkus, clientId=web-application, userId=null, ipAddress=172.17.0.1, error=invalid_client, grant_type=client_credentials, client_auth_method=client-secret

Why Quarkus tries to use "grant_type=client_credentials"? It should use the grant type = "authorization_code". This looks like a bug in Quarkus, but maybe there is a flag.

To Reproduce
Follow the mentioned steps

Configuration

# OIDC Configuration
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus
quarkus.oidc.client-id=web-application
quarkus.oidc.credentials.secret=ca21b304-XXX-XXX-XXX-51d38ef5da02
quarkus.oidc.application-type=web-app
quarkus.oidc.authentication.scopes=email

Screenshots
(If applicable, add screenshots to help explain your problem.)

Environment (please complete the following information):

  • Output of uname -a or ver:
  • Output of java -version:
  • GraalVM version (if different from Java):
  • Quarkus version or git rev:

Additional context
https://auth0.com/docs/api-auth/tutorials/authorization-code-grant#2-exchange-the-authorization-code-for-an-access-token

@piotrgwiazda piotrgwiazda added the kind/bug Something isn't working label Nov 8, 2019
@sberyozkin
Copy link
Member

@piotrgwiazda AFAIK, no Keycloak specific API is used by quarkus-oidc, where is a message with org.keycloak.authorization.client.... is displayed, in the Quarkus log ? Or is it reported back from KC server ?

@sberyozkin
Copy link
Member

@piotrgwiazda FYI, I've confirmed the tests work without KC specific APIs being on the classpath, so can you create a reproducer ? For example, using that quickstart as a base ?

@piotrgwiazda
Copy link
Author

piotrgwiazda commented Nov 8, 2019

Based on some tutorial I had
quarkus.keycloak.policy-enforcer.enable=true
Maybe that is the root cause. Let me retest my sample.

@sberyozkin
Copy link
Member

sberyozkin commented Nov 9, 2019

@piotrgwiazda might be related. Note, you don't need quarkus-keycloak-authorization if all you you need is the "web-app"/code flow, but quarkus-keycloak-authorization has to be able to co-exist with the "web-app"/code flow, without the client credential grant being issued under the hood, so please double check, if you can help with showing which configuration caused this side-effect then it would be nice, thanks.

@piotrgwiazda
Copy link
Author

@sberyozkin I've followed this tutorial https://quarkus.io/guides/security-keycloak-authorization then I've changed the application type to "web-app" to try another approach.

My dependencies are

  <dependencies>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-jsonb</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-oidc</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-keycloak-authorization</artifactId>
    </dependency>
  </dependencies>

When I removed

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-keycloak-authorization</artifactId>
    </dependency>

and removed quarkus.keycloak.policy-enforcer.enable=true the authentication with Keycloak works.

Also, using this tutorial seems to be a better idea in my case : https://quarkus.io/guides/security-openid-connect

I think you can close the issue, unless this indicates a problem somewhere else. Thanks for help.

@sberyozkin
Copy link
Member

sberyozkin commented Nov 10, 2019

@piotrgwiazda thanks, I'll keep it open as the policy enforcer should either work with the id tokens in this case or if it only works with service apps - then probably fail the application startup or log a warning. Thanks

Hi Pedro @pedroigor - what do you think - I guess the simplest approach is probably add a check if the application type is web-app and if not - fail. Or should it just check id token without trying to exchange it - probably not but with the user directly interacting with the web-app it might make sense after all ?

@pedroigor
Copy link
Contributor

The quarkus-keycloak-authorization extension should also work with web-app applications. The difference here is that to use the extension your client must be a confidential client and have a secret (for now Quarkus only supports client_id/client_secret for client authentication).

However, we only advertize in guides and cover in our testsuite the bearer token scenario, typical for service type applications.

I can review this and make sure we can deal with web-app too if you guys think that it makes sense.

@sberyozkin
Copy link
Member

@pedroigor thanks; @piotrgwiazda had quarkus-keycloak-authorization activated (from the earlier tutorial) which caused the exception, see the error description.

What do you mean it has to be a confidential client, the web-app is a confidential client, right ? The configuration reported by the user has it all set up, quarkus.oidc.credentials.secret=ca21b304-XXX-XXX-XXX-51d38ef5da02. Is it really about configuring the real in Keycloak itself and qualify the client properly ?

And which token quarkus-keycloak-authorization would check in case of the code flow, AccessToken is for the web-app itself to use if it needs it, so it would be IdToken ?

@pedroigor
Copy link
Contributor

Yes, the client in Keycloak should be configured to enable Authorization Services as per https://www.keycloak.org/docs/latest/authorization_services/index.html#_getting_started_hello_world_enabling_authz_services.

You have a good point in regards to the token the extension should use. It should use access token (although the token endpoint also allow using ID Tokens).

Based on what I mentioned before about initially supporting bearer tokens (service type applications), the extension is still trying to obtain a TokenCredential, what I think we should change to explicitly obtain a AccessTokenCredential instead.

I did some tests here is this change should be enough to get it also working for web-app apps.

@sberyozkin
Copy link
Member

sberyozkin commented Nov 12, 2019

@pedroigor Hey Pedro, but I wonder if we should leave it as is for the moment and keep quarkus-keycloak-authorization supporting the service applications only. AccessToken is not really targeting the web-app application, it is there for web-app to do the outbound calls with it if it wants to.
I propose to only update quarkus-keycloak-authorization to ensure if it is enabled then it ignores the web-app flows and review it in due time. Thanks

@pedroigor
Copy link
Contributor

@sberyozkin It works for me too. Let's wait for any demand from the community. It does make sense though, as you may want to externalize authorization from your web app. The fact that the client should be confidential is perfectly fine since web-apps are server-side apps that can securely store credentials.

I'm going to prepare a PR to include checks for the service type.

@piotrgwiazda
Copy link
Author

AccessToken is not really targeting the web-app application, it is there for web-app to do the outbound calls with it if it wants to.

I generally agree. On the other hand, sometimes you want to e.g. hide the button if rhe user is missin a permission. Then the backend-for-frontend (web-app) will need the permission details to pass to the GUI.

sberyozkin added a commit that referenced this issue Nov 14, 2019
[fixes #5323] - Only SERVICE type applications are supported
@gsmet gsmet added this to the 1.1.0 milestone Nov 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/oidc kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants