This document will provide detailed instructions to enable OAuth V2 authentication on Teiid's OData interface using the Keycloak as authentication server (IDP). Please note that use a different IDP server will not work with this implementaion as OAuth implementions are not interoperable. To work with separate IDP than Keycloak consult their documentation, replace the web layer semantics, like the "login-config" in web.xml file etc. Providing the details of other IDP is beyond the scope of this document.
This examples will show case an example, where Teiid's OData rest interface is secured using OAuth using Keycloak as IDP. The VDB accessed by the OData interface also depends on another web service which is used as a data source, that is also secured with OAuth using the same Keycloak IDP. The central idea behind this example is to pass the same "access-token" used at OData interface layer to passthrough the Teiid layer to bottom data source layer and gain access to the source.
- Login using the default "admin/admin" credentials into the Keycloak "master" realm.
- Add a new realm called "oauth-demo"
- Add a new user called "user" and add credentials.
Add two roles "odata" and "user". These are enterprise roles, that will be used by the web services to grant the access to user. Also these roles are used as "scopes" in the OAuth protocol.
- Add a new client called "odata4-oauth", this client represents the Teiid's OData client that we are going to create
and choose scopes "odata" and "user" for this client. Note that the redirect URI needs to be where the actual service is going to be available.
The client web-service typically defines what roles that logged in user must have in order for to grant the access. In the Keycloak OAuth implementation, these roles are used as "scopes". Note that the "odata4-oauth" client MUST have ALL the scopes that it is going to delegate the access-token for gaining access to bottom data services. In this example Teiid's OData web services requires "odata" role, the bottom web-service requires the "user" role. Since the OData accesses the bottom web-service it requires both the roles.
- Add another client called "database-service" and choose scope "user". Choose type as "Bearer".
- Download and install Teiid server
- Download Keycloak adapter for the EAP, and unzip over the Teiid server installation
- Download Keycloak SAML adapter for EAP, and unzip over the Teiid server installation. (optional but need for another exercise)
- Edit the standalone-teiid.xml, add the following sections
Run the following CLI to add Keycloak specific modules to the server
above commands will result in XML in standalone.xml or domain.xml file like
Add these two subsystems any where in the file, use the following the CLI script
above commands will result in XML in standalone.xml or domain.xml file like
In security-domains add following security domains using the following CLI
above commands will result in XML in standalone.xml or domain.xml file like (you can also edit standalone.xml directly)
Under Teiid subsystem, change the "security-domain" of the "odata" transport, to
results in XML
This finishes all the server side changes that are required to make OAuth authentication using Keycloak.
H2. OData Application WAR
In order to use OAuth authentication, the OData WAR needs to be updated to make use of the OAuth based security domain. By default Teiid installation comes with OData web service WAR file configured with "HTTP Basic" authentication. This WAR needs to either replaced or updated.
To build OAuth based OData WAR file, Teiid provides a template maven project, either download or clone the project from https://github.com/teiid/teiid-web-security
The above link provides templates for creating two WAR files, one WAR file is to create Teiid's OData service with OAuth, the next is a sample "database-service" for this demo. Please note that "database-service" is to mimic the database service, that will be different in a real use-case, however the steps defined for the access will be same.
Replace the "teiid-web-security/teiid-odata-oauth-keycloak/src/main/webapp/WEB-INF/keyclock.json" file contents with "installation" script in "keycloak.json" format from Keycloak admin console's "odata4-client" client application.
Similarly replace the "teiid-web-security/examples/database-service/src/main/webapp/WEB-INF/keyclock.json" file contents with "installation" script in "keycloak.json" format from Keycloak admin console's "database-client" client application.
to build the WAR files running the maven command
The above command will generate a new WAR file for deployment. Follow the below directions to deploy this new WAR file.
Replace the <jboss-eap-6.4>/modules/system/layers/dv/org/jboss/teiid/main/deployments/teiid-olingo-odata4.war" file with new WAR file, by executing a command similar to
If you are working with JDV 6.3 server or greater, then run the following CLI script, you may have change the below script to adopt to the correct version of the WAR and directory names where the content is located.
or overlay the new one using CLI script like
Edit the standalone-teiid.xml and under resource-adapters subsystem, add the following to add access to a database-service from the Teiid query engine.
Add a VDB with following contents (oauthdemo-vdb.xml)
Start both Keycloak and Teiid Servers. If both of these servers are in the same machine, then we need to offset the ports of Teiid server such that they will not conflict with that of the Keycloak server. For this example, I started the Teiid server as
where all ports are offset by 100. So the management port is 10090 and default JDBC port will be 31100. The Keycloak server is started on default ports.
There are two different mechanisms for testing this example. One is purely for testing the using the browser, then other is programatically. Typically using the browser is NOT correct for accessing the Teiid's OData service, but it is shown below for testing purposes.
Using the browser issue a query (the use of browser is needed because, this process does few redirects only browsers can automatically follow)
then you should see a message like "Congratulations!!! Login successful..". What this process is doing is negotiating a "access-token" from the Keycloak authentication server and places this in the client's web-session, such that subsequent calls to the service use this token for access.
Now to fetch the data from the "database-service" using the negotiated "access-token" issue a query
If all the configuration is setup correctly, then you will see the response like below.
|When above method is used to capture access token, it is possible that the access token gets expired after its lifespan, in that situation a new access token needs to be negotiated.|
This process of calling does not need to involve a web-browser, this is typical of scenario where another web-application or mobile application is calling the Teiid's OData web-service to retrieve the data. However in this process, the process of negotiating the "access-token" is externalized and is defined by the IDP, which in this case is Keycloak.
For demonstration purposes we can use CURL to negotiate this token as shown below (client_secret can found the Keycloak admin console under client credentials tab)
this should return a JSON payload similar to
from the above you can take the "access_token" and issue the query to fetch results like
You should see same XML response as above. Please note that to programatically achieve the access_token in your own program (not using curl) you can see some suggestions in this document http://keycloak.github.io/docs/userguide/keycloak-server/html/direct-access-grants.html