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:
My testing environment is the offical docker container from hub.docker.com/r/jboss/keycloak/
Keycloak is designed to cover most use-cases without requiring custom code, but we also want it to be customizable. To achieve this Keycloak has a number of Service Provider Interfaces (SPI) for which you can implement your own providers.
Developing a Keycloak extension To develop your extension, simply create a new maven module, e.g. simple-auth-extension in the keycloak-extension-playground . Then add the module as a dependency to the keycloak-playground-server project.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With