Frontend public client and Backend confidential client

I have a backend with Spring-Security that connects to a confidential client of Keylcoak, and now I want to deploy a frontend in ReactJS connecting to a public client, because there are no more allowed confidential clients connecting to angular, react, javascript, etc.

But I always get a 401 from the backend because it can’t validate the bearer token either the policy enforcement.

How can I do it? I want to stay with the confidential client for the Authorization part of Keycloak.

1 Like

See:

I can make login successfully, but the problem is when I try to access to the API REST of the backend, that always returns me 403

I have deployed keycloak and spring boot application on the same network in docker, and it does not work either with a CURL call

You need to provide more details because you ask people to guess what your problem may be.
Show us your curl command to start of and your spring boot config

Here is the CURL function that I am calling wherein the port 18080 is deployed Keycloak and in the port 38080 is deployed my Spring-Boot app.

export token=$(curl -X POST \
            -H 'Content-Type: application/x-www-form-urlencoded' \
            -d 'client_secret=XXXXX&username=user&password=user&client_id=login-app&grant_type=password' \
            -v http://localhost:18080/auth/realms/FocusocKeycloak/protocol/openid-connect/token | jq .) 
        	

access_token=$(echo $token | jq -r .access_token)

curl -v -X POST \
          -H "Authorization: Bearer $access_token" \
          --noproxy localhost, http://focusoc:38080/api/v1/conjunction

Also here is my Spring-Boot configuration. As I am using the 9.0.3 it is loading from application.properties the configuration of the connection into Keycloak,

keycloak.realm=FocusocKeycloak
keycloak.auth-server-url=http://${KEYCLOAK_ADDR}:18080/auth
keycloak.credentials.secret=XXXXX
keycloak.ssl-required=external
keycloak.resource=login-app
keycloak.bearer-only=true
keycloak.securityConstraints[0].authRoles[0] = upload
keycloak.securityConstraints[0].securityCollections[0].name = protected
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /*
keycloak.autodetect-bearer-only=true

keycloak.policy-enforcer-config.on-deny-redirect-to=/accessDenied

I read in a lot of forums that the solution has to be putting the client in the backend side as confidential, but in the spring-boot application configure it as bearer-only, and in the frontend part as public.

Try also setting keycloak.principal-attribute=preferred_username
Try introspecting your token to see if the correct roles are present
Do you have set a GrantedAuthoritiesMapper to the KeycloakAuthenticationProvider in your Spring security config AuthenticationManagerBuilder?

I introspected the token and the roles are present.
I didn’t set any GrantedAuthoritiesMapper, should I? And how should i do it?

It’s wired what is happening because, if I execute keycloak out of docker, it works well…

I’ll try setting that property

EDIT: Property tested and nothing, same result: 403

I have a similar system, without docker.

The Angular application does login with the public client.
Then, it uses the token with my Java REST server (JAVA EJB class, no Spring).
The Java Application is configured to use the confidential client.

The problems I found:

  • public and confidential clients must work either in https or http, you cannot mix them;
  • a lot of problem with CORS : keycloak is installed on a different pc

With CORS problem i get 403 error

So I suggest you to rise log to maximum level and read what the java adapter send to server.

For example, this is what i read in the log (i’m using wildfly):

8:32:29,374 DEBUG [org.apache.http.impl.conn.tsccm.ConnPoolByRoute] (default task-13) Releasing connection [{s}->https://edu.svi:38443][null]
18:32:29,374 DEBUG [org.apache.http.impl.conn.tsccm.ConnPoolByRoute] (default task-13) Pooling connection [{s}->https://edu.svi:38443][null]; keep alive indefinitely
18:32:29,374 DEBUG [org.apache.http.impl.conn.tsccm.ConnPoolByRoute] (default task-13) Notifying no-one, there are no waiting threads
18:32:29,375 DEBUG [org.keycloak.adapters.authorization.AbstractPolicyEnforcer] (default task-13) Authorization GRANTED for path [PathConfig{name='BWCLogin', type='MODULI', path='/webservice/login/*', scopes=[read, print, update, delete, create], id='74fc7556-2a5e-41ca-bf8b-a1018a29424d', enforcerMode='ENFORCING'}]. Permissions [[Permission {id=74fc7556-2a5e-41ca-bf8b-a1018a29424d, name=BWCLogin, scopes=[print, read, create, update, delete]}]].
18:32:29,375 DEBUG [org.keycloak.adapters.authorization.PolicyEnforcer] (default task-13) Policy enforcement result for path [https://dan.svi:8443/SpesaWeb/webservice/login/getinfo] is : GRANTED
18:32:29,375 DEBUG [org.keycloak.adapters.authorization.PolicyEnforcer] (default task-13) Returning authorization context with permissions:
18:32:29,375 DEBUG [org.keycloak.adapters.authorization.PolicyEnforcer] (default task-13) Permission {id=74fc7556-2a5e-41ca-bf8b-a1018a29424d, name=BWCLogin, scopes=[print, read, create, update, delete]}
18:32:29,375 DEBUG [io.undertow.request.security] (default task-13) Authenticated as 51543276-5886-4520-bcde-f7132fbbc75c, roles [cliente]

I haven’t a CORS problem now, so i cannot produce a log, but there was an error saying “NotAllowed…”

But my main error is that if I deploy keycloak on docker and the spring-boot app deployed on the host, when I try to access to the API REST, it does not verify the token.

And after all test that I made, I think that is a problem with resolving names for keycloak because:

  • localhost:3000 (ReactJS)
  • localhost:38080 (Spring-boot app)
  • localhost:8080 (Keycloak)

If keycloak is deployed on docker, when the spring-boot app triesto verify the identity of the user it fails, I think because kecloak tries to verify a localhost address that actually is denied because is his localhost, inside the docker.

So I don’t know how to fix this problem.

Anyone has seen this?

I think we have the exact same problem, so if anyone need a bit more information maybe read my post. I still have no clue on how to fix this issue.

My post: Broker token request not working from backend

Are the settings in your client correct.
What do you have in redirectUris and webOrigins?
Did you increase the log level like @bssdev mentioned?
Try some settings in your spring boot app like keycloak.use-resource-role-mappings=false and keycloak.cors=true
Maybe you can put up your spring boot app on github so we can look into it?

In redirectUris I have http://localhost:38080/* and webOrigins I put “+” in the case of the confidential client.
I didn’t try the log level mentioned, I’ll see it.
I tried both properties, if I delete the cors one. it fails because of cors and the other one doest make any effect.

Sorry I cannot put the project to git because it’s confidential.

I didn’t ask to put the whole project online, just what is minimal needed to show the problem.
Is CORS configured in your Sprnig Boot API to allowed calls from your react front-end?
Show us the configuration for Keycloak of your front-end app.
Can you see the token being passed when your react front-end does the call to the backend?

@afvg
how you were able to get token from backend?
I am in same scenario even without docker i am not able to get backend working. I even tried postman.
After login iam getting code which is been sen to server and it returns me idtoken, refreshtoken and token. Now how are you using these values to authenticate with backend i.e., confidential or beareronly client?
please help

The configuration that I use nowadays is:

  • Frontend: public
  • Backend: confidential

And in the backend, I use SpringFramework and in the property “keycloak.securityConstraints[0].authRoles[0]” I put the role that I want to authenticate.
Also in the Keycloak configuration, I configurated a Client Scope and added to both clients: frontend and backend with the role that I mentioned before.