keycloak realmresourceprovider corse

3k Views Asked by At

I'm evaluating some IAM Products and encountered a Problem with CORS with the RealmResourceProvider from Keycloak. The goal is to write an angular4 client able to create user and manage groups with a REST interface from Keycloak.

Server-side:

I tried to implement the Rest interface with the RealmResourceProvider Interface in order to access Realm and User Data as easy as possible. I followed the Beercloak example (github.com/dteleguin/beercloak) and got it working, but without a custom theme (only the REST-Resources). My own application is packaged as Jar. I managed to call this Facade via REST Client and it worked (By calling localhost:8080/auth/realms/master/protocol/openid-connect/token first and then stuffing the Token in the Authorization-Header).

keycloak-configuration But if i test it via Browser, I will need to enable Cross-Origin-Ressource-Sharing. In order to do that I added the 'enable-cors' attribute to the 'keycloak.json' in the server application:

{
"realm": "master",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "pharmacyRessource",
"public-client": true,
"enable-cors": true
}

Additionally I Created a Client in the Keycloak Admin. Client Config

Client-Side and Problem:

The angular client uses Mohuks ng2-keycloak service from github.com/mohuk/ng2-keycloak/blob/master/src/keycloak.service.ts to obtain the accesstoken. - Works fine. But in case i make a GET-request to my Resource, the preflight fails because of missing Access-Control-Allow-Origin Header: Error 401 The keycloak.json used for initializing the keycloak-client in javascript looks like this:

{
  "realm": "master",
  "auth-server-url": "http://localhost:8080/auth",
  "ssl-required": "external",
  "resource": "pharmacyRessource",
  "public-client": true
}

My failed solutions:

  • I tried to implement a CORS Filter, but i didn't succeed because i couldn't get it registered by keycloak.
  • I also implemented the @OPTIONS Method and appended CORSE Headers by myself. Didn't work either, because the Method never got invoked.
  • I tried to package it as .war in order to enabling a custom Filter/Provider, but failed at registering the Resources to keycloak.

My testing environment is the offical docker container from hub.docker.com/r/jboss/keycloak/

2

There are 2 best solutions below

0
On

Do you need enable CORS in your keycloak server (that runs in wildlfy) . You can do it, putting the code bellow into your standalone.xml from wildfly:

        <subsystem xmlns="urn:jboss:domain:undertow:4.0">
        <buffer-cache name="default"/>
        <server name="default-server">
            <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
            <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
            <host name="default-host" alias="localhost">
                <location name="/" handler="welcome-content"/>
                 <filter-ref name="server-header"/>
        <filter-ref name="x-powered-by-header"/>
        <filter-ref name="Access-Control-Allow-Origin"/>
        <filter-ref name="Access-Control-Allow-Methods"/>
        <filter-ref name="Access-Control-Allow-Headers"/>
        <filter-ref name="Access-Control-Allow-Credentials"/>
        <filter-ref name="Access-Control-Max-Age"/>
                <http-invoker security-realm="ApplicationRealm"/>
            </host>
        </server>
        <servlet-container name="default">
            <jsp-config/>
            <websockets/>
        </servlet-container>
        <handlers>
            <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
        </handlers>
            <filters>
        <response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
        <response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
        <response-header name="Access-Control-Allow-Origin" header-name="Access-Control-Allow-Origin" header-value="http://localhost"/>
        <response-header name="Access-Control-Allow-Methods" header-name="Access-Control-Allow-Methods" header-value="GET, POST, OPTIONS, PUT"/>
        <response-header name="Access-Control-Allow-Headers" header-name="Access-Control-Allow-Headers" header-value="accept, authorization, content-type, x-requested-with"/>
        <response-header name="Access-Control-Allow-Credentials" header-name="Access-Control-Allow-Credentials" header-value="true"/>
        <response-header name="Access-Control-Max-Age" header-name="Access-Control-Max-Age" header-value="1"/>
      </filters>
    </subsystem>
1
On

Keycloak should automatically handle CORS headers for you when you set "enable-cors": true in the client configuration JSON file as you mention.

The reason why the server is not adding the Access-Control-Allow-Origin header is because Keycloak rejects the origin unless the token is configured (via the admin console) to do so. It's very subtle, but it's mentioned in the docs (https://www.keycloak.org/docs/4.1/securing_apps/index.html):

enable-cors This enables CORS support. It will handle CORS preflight requests. It will also look into the access token to determine valid origins.

Notice the last sentence. The "valid origins" in the "access token" are part of the client configuration, which is set via the admin UI.