Why is quarkus.oidc.credentials.secret being ignored? - keycloak

I have a SPA (Vue.js) that communicates via REST with a Quarkus Resource API .
I am using my own Keycloak for Authentication/Authorization.
In Keycloak I have two clients in my realm:
Client ID: frontend-client
Access Type: public
Standard Flow enabled
Client ID: backend-client
Access Type: bearer-only
Secret: mySecret
My application.properties for my Quarkus API:
quarkus.oidc.auth-server-url=https://localhost:8082/auth/realms/myrealm
#quarkus.oidc.client-id=backend-service
#quarkus.oidc.credentials.secret=mySecret
My SPA uses the Standard Flow to authenticate with Keycloak and then redirects to my app ✅
Then I can make requests to my API and everything works despite quarkus.oidc.client-id and quarkus.oidc.credentials.secret being commented out ! Why is that? It also works when those lines are not commented out but with false values. 😳
Why is Quarkus ignoring those lines, and, more importantly, why does it work?
UPDATE
Adding the dependency
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-keycloak-authorization</artifactId>
</dependency>
Allows me to add this to application.properties:
quarkus.keycloak.policy-enforcer.enable=true
It now leads to this error:
{"error":"invalid_client","error_description":"Bearer-only not allowed"}
But at least now the secret is not being ignored, and providing a wrong secret leads to the correct error.
Follow-up question: Why is bearer-only not allowed?

I'm guessing that because your Quarkus application use a bearer only client, it will only check the authenticity of the bearer token using the signature.
Since it will not make any call to Keycloak for additional verifications, it will not use the client id and client secret in your properties.
You need to change the type of the client to confidential if you want quarkus to use that.
By the way, in the quarkus quickstart for protecting service applications : the keycloak client use a confidential client, and bearer only is set to false : https://github.com/quarkusio/quarkus-quickstarts/blob/main/security-openid-connect-quickstart/config/quarkus-realm.json#L395

Related

How to configure Keycloak for my Single Page Application with my own Login form?

I have a SPA (Vue) that communicates via REST with a Quarkus Backend. I would like to use Keycloak for Authentication/Authorization. However, I do not need the whole "Browser Flow" Keycloak feature, instead my SPA has its own Login Form to get a JWT from Keycloak (Direct Grant Flow). This token will be used to communicate with my REST Endpoints.
Frontend -> gets a JWT from Keycloak
Frontend -> gets access to protected resources with that JWT.
However I came accross this article that vehemently discourages devs from using the Direct Grant flow. So what now? Is there a way to still use my own login form with Keycloak?
Something along the lines of:
Frontend login -> Backend -> Keycloak Authentication/Authorization -> JTW
Frontend -> gets access to protected resources with that JWT.
I am slightly overwhelmed by all the different configuration possibilities in Keycloak and Quarkus. So far I managed to get a token from keycloak with a public client (direct grant), and that token is being used to access protected resources. My Quarkus backend knows the keycloak server too and communicates with it via a second client (acces type: confidential)
quarkus.oidc.auth-server-url=http://localhost:8081/auth/realms/myrealm
quarkus.oidc.client-id=backend-service
#quarkus.oidc.credentials.secret=my-secret
However, I am not sure why this works at all since the secret is commented out. Why would I need it in the first place ?
One way could be to use the authorization code flow with a custom theme for keycloak : https://www.keycloak.org/docs/latest/server_development/
As you are using react, you can take a look at https://github.com/InseeFrLab/keycloakify which allows you to reuse your react component with keycloak theming.
(Disclaimer: I belong to the organization maintening this library)

How do I properly auth with JWT to openapi UI for Quarkus / smallyre-JWT?

I have a Quarkus endpoint stood up. Secured by JWT and Roles.
It works in Postman. (Header <Authorization, Bearer ey……>)
I have looked and struggled and found I can’t do a typical #Header or #Parameter annotation exposing this Authorization header—it stomps out that precise value. “Authorization1” I can expose. But not “Authorization”.
I have got a jwt configuration option in the application.YML file. I now get an authentication “padlock” on the UI but whatever I enter there doesn’t get passed to the CURL command in “try it out” mode.
Has anyone solved this problem?
application.yml parts:
smallrye-openapi:
...
jwt-bearer-format: JWT
jwt-security-scheme-value: Bearer
security-scheme: jwt
These images may be useful:
It's not really a bug. There is a configuration that you can specify in Quarkus that allows you to inject the JWT token into each request from Swagger.
There is some work that you need to do in order to accomplish this simply because Swagger will not know beforehand how to read the JWT token and how to reuse it for subsequent calls.
Below is one method that you can use in order to make Swagger calls work in a Quarkus project.
There are a few things to unpack here.
Caveat
This has been tested to work with Quarkus 2.0.1.Final. Older versions of Quarkus use an old version of SmallRye that has a bug in it when rendering the request interceptor.
Use this configuration in Quarkus quarkus.swagger-ui.request-interceptor to inject the jwt token into the request headers of Swagger. This value goes into your application.properties. (Do modify this configuration to suit yml files)
quarkus.swagger-ui.request-interceptor=function(req){var authToken=sessionStorage.getItem('authenticationToken');if(authToken){req.headers['Authorization']='Bearer '+authToken;}return req;}
Now go to your Swagger UI and login using the login endpoint that you use. This will return the jwt token. Go to the browser and input the value into your browser's Session Storage under the key 'authenticationToken'
Now when you hit any endpoint that you want to test, Swagger will use the request interceptor (defined in 1) to inject the JWT from your browser's session storage and your calls will work.

Keycloak Applications vs Client authentication

Hi i am a bit confused as to how to secure applications through keycloak, the website shows how to secure clients. The application which i need to secure in my setup is a desktop application which uses keycloak + keycloak-gatekeeper protected endpoints.
i managed to get it working using the following library in python
https://bitbucket.org/agriness/python-keycloak/src/master/
however, it requires me to enter the client-secret and i am wondering if this is safe?
also, when i use the browser login instead, the browser doesnt need the client secret, but goes though gatekeeper, this tells me that i am doing something wrong here.
thanks
Use public access type client (Clients doc):
Public access type is for client-side clients that need to perform a browser login. With a client-side application there is no way to keep a secret safe. Instead it is very important to restrict access by configuring correct redirect URIs for the client.
You can change access type on clients - choose client - settings tab admin interface.
in your case, I would use Access type as confidential
and Authorization Enabled > on
and you should use the secrecy key to authorize your call to keylock when you want to interact with keycloak API
Keycloak keycloak = KeycloakBuilder.builder()
.serverUrl("localhost")
.realm("myRealm")
.grantType(OAuth2Constants.PASSWORD)
.clientId("myclient")
.clientSecret("xxxx-xxxxx-xxxx-xxx")
.username("foo")//the admin user
.password("password")
.build();
keycloak.realm("myRealm").users().list();

Generating an API Client with Swagger OpenAPI 3 with OAuth2 Client Credentials

I am using the Swagger OpenAPI 3.0.2 version for describing my API.
I built swagger-codegen 3.0.5 snapshot from the Swagger gihub repo.
I want a Java client that will obtain the OAUTH2 token for a grant type of client_credentials. I want client credentials because this is one machine talking to another, I am not asking a user for their credentials. I have the following bit in my spec file:
securitySchemes:
oAuth2ClientCredentials:
type: oauth2
description: Standard OAUTH2
flows:
clientCredentials:
tokenUrl: my_token_url
scopes: {}
security:
- oAuth2ClientCredentials: []
I want a Basic Authentication header with the client ID and the client secret in the standard base64 encoding with the grant_type as a URL encoded form. This is pretty standard OAuth2 authentication.
I seem to sometimes get code for the OAuth authentication and sometimes not. The python library has nothing for OAuth other than me proving the access token by hand. The Java library doesn't have it unless I ask for retrofit as the base library, but it generates a Bearer Authentication header, rather than a Basic Authentication Header. Retrofit2 doesn't even work, the handlebars template has an illegal character in it that handlebars barfs on.
So what do people do to get their access tokens when they have a client ID and a client secret? Do you craft the code to get the access token by yourself? Or is there some magic way of getting swagger-codegen-cli to generate the code for me, depending on the libraries that I use?
If anyone has managed to get swagger-codegen-cli to generate everything they need for OAuth 2 client credentials with an OpenAPI 3.0 specification, please let me know.

JWT and KONG with custom authrizations

I went through this tutorial on KONG
https://getkong.org/plugins/jwt/
I have an understanding of JWT and authorization concepts. I have prototyped JWT with Spring Boot where I could put my own key value like this {"authorizations":"role_admin, role_user"}.
It is easy to do that in Spring Boot but I am not able to find information on how to do this with KONG. Anyone has any info about it?
Kong community edition can handle only the authentication process, (give or deny access to a customer).
Authorization process (what a given customer can do in your application) is handled by your application or by https://getkong.org/plugins/ee-oauth2-introspection/ oauth2 introspection plugin which is enterprise edition only
you can write your own authorization server based on X-Consumer-Username request header if user passed authentication or original token header proxied by kong
hope helps
The kong jwt plugin does not support sending custom payload parameters to the upstream api. It does however seem like you can use this plugin (I have not tested it):
https://github.com/wshirey/kong-plugin-jwt-claims-headers
Update:
If you set Kong to forward all headers you'll get the raw Authorization header with the jwt token. So you could base64 decode the jwt token and pull out the claims/payload parameters you need manually in your service.