Keycloak SSO OIDC

107 views
Skip to first unread message

Patrik B

unread,
Jun 3, 2025, 12:17:50 PM6/3/25
to WildFly
Dear All!

I have a little Jakarta EE project which has 3 WARs(common-web, admin-web, customer-web) and 3 EARs.
Using Wildfly 35.0.1.Final, Keycloak v23.0.0 and Angular V15.
Have the same oidc.json in every WAR:
{
"realm": "${keycloak.realm}",
"auth-server-url": "${keycloak.auth.server.url}",
"ssl-required": "none",
"resource": "common-web",
"credentials": {
"secret": "xxxxx"
}
}
in web.xml:
<login-config>
<auth-method>OIDC</auth-method>
</login-config>
Browser flow:
  • open angular app localhost:8080/common-web (it's a wildfly proxy which proxies to localhost:4200 where angular lives)
  • because of the OIDC configuration browser redirect happens to keycloak login screen
  • username/password typed and logs in
  • redirect to localhost:8080/common-web works
  • angular xhr is sended to localhost:8080/admin-web/rest/session-data/ping
  • xhr is redirected to keycloak because there is no auth indentity but xhr OPTIONS is got CORS error because keycloak v23.0.0. not allow (error 405) OPTIONS preflight in /auth endpoint (worked well before keycloak v23.0.0.)
This CORS problem was tried to fix with auth data shared between WARs but haven't got any success.
Is there a way to share Identity between WARS and if how can I setup standalone.xml?
Wildfly security trace is:
  • [org.wildfly.security.http.servlet] (default task-2) Created ServletSecurityContextImpl enableJapi=true, integratedJaspi=true, applicationContext=default-host /admin-web
  • [org.wildfly.security.http.servlet] (default task-2) No AuthConfigProvider for layer=HttpServlet, appContext=default-host /admin-web
  • [org.wildfly.security.http.servlet] (default task-2) JASPIC Unavailable, using HTTP authentication.
  • [org.wildfly.security] (default task-2) No CachedIdentity to restore.
  • [org.wildfly.security] (default task-2) Created HttpServerAuthenticationMechanism [org.wildfly.security.auth.server.SecurityIdentityServerMechanismFactory$1@798c90bf] for mechanism [OIDC]
  • [org.wildfly.security.http.oidc] (default task-2) adminRequest http://localhost:8080/admin-web/rest/session-data/ping
  • [org.wildfly.security.http.oidc] (default task-2) --> authenticate()
  • [org.wildfly.security.http.oidc] (default task-2) try bearer
  • [org.wildfly.security.http.oidc] (default task-2) try query parameter auth
  • [org.wildfly.security.http.oidc] (default task-2) try oidc
  • [org.wildfly.security.http.oidc] (default task-2) Account was not in session, returning null
  • [org.wildfly.security.http.oidc] (default task-2) there was no code
  • [org.wildfly.security.http.oidc] (default task-2) redirecting to auth server
  • [org.wildfly.security.http.oidc] (default task-2) callback uri: http://localhost:8080/admin-web/rest/session-data/ping
  • [org.wildfly.security.http.oidc] (default task-2) Sending redirect to login page: https://xxxx/realms/xxxxx/protocol/openid-connect/auth?response_type=code&client_id=common-web&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fadmin-web%2Frest%2Fsession-data%2Fping&state=xxx&scope=openid
So I tought if the first common-web SecurityIdentity somehow be cached between the WARS each WAR can be found it and only calling token validation, etc and no redirect will be needed to keycloak again.

Thanks in advance

Stephen Sill II

unread,
Jun 3, 2025, 3:25:24 PM6/3/25
to WildFly
I'm not sure, my only use-case ever was a single war.   you might try wildfly 36.0.1.  I had a long standing issue that was resolved in the oidc client in 36.0.1

Stephen Sill II

unread,
Jun 3, 2025, 3:31:40 PM6/3/25
to WildFly
I'm not seeing a client-id in your oidc.json.  In the client in keycloak identified by client-id you can configure your origins and allowed redirect urls.

My pod start up writes out an oidc json that's applied via an overlay in the war

cat << EOF > /opt/bitnami/wildfly/stage/oidc.json
{
    "client-id": "${OIDC_CLIENT_ID}",
    "provider-url": "${OIDC_PROVIDER_URL}",
    "ssl-required": "${OIDC_SSL_REQ}",
    "public-client": ${OIDC_PUBLIC_CLIENT},
    ${TRUST_MANAGER_SNIPPET}
    "confidential-port": 443,
    "connection-ttl-millis": 60000
}
EOF

On Tuesday, June 3, 2025 at 10:17:50 AM UTC-6 Patrik B wrote:

Patrik B

unread,
Jun 5, 2025, 6:36:36 AM6/5/25
to WildFly
It's called "resource" in my file. If you download adapter config from keycloak admin web ui it's generating "resource" too not "client-id", i didn't analyze the code but I think it's the same because it's works.
But finally I managed to use SSO, need this two key/value pair in oidc.json:
"token-store": "cookie"
"adapter-state-cookie-path": "/"
Token store is Session by default which is not good in this scenario, and cookie path need to be set to / for each war do not make it's own path cookie like (/common-web, /admin-web, /customer-web)
But now when I calling my logout endpoint which only calls this:
@GET
@Path("/logout")
public Response logout() {
    try {
         request.getSession().invalidate();
        request.logout();
    } catch (ServletException e) {
         throw new RuntimeException(e);
    }
     return Response.ok(new ResponseWrapper<>(true)).build();
}  
it's logouts from keycloak - the user session is deleted from it (in keycloak admin ui no session exists for the user which is good) - but not deleting the created OIDC_STATE cookie from the browser and I can still use all of the endpoint because wildfly thinks session is still exists.
I debugged OidcCookieTokenStore.java (logout(boolean glo)), OidcHttpFacade.java (authenticationComplete()) all of them called and logout happens, cookie is reseted but don't understand why not sended back to browser (also JSESSIONID cookie sent back with expired...) 

Stephen Sill II

unread,
Jun 5, 2025, 7:06:05 AM6/5/25
to WildFly
Glad you figured it out.   My cases is slightly different, I'm using oidc-client auth in front of a vaadin app.
Reply all
Reply to author
Forward
0 new messages