I am working on a project where I need to create an application that shall act as an OIDC mediator between a client which only supports OIDC for authentication and a REST api. The REST api is able to generate tokens and give user info but does not support OIDC.
To achieve this I am thinking of using keycloak to handle the OIDC communication with the client and implement my own java application that keycloak can trigger to realize the authorization, token and userinfo endpoint (sort of a custom ownmade identity provider) handling the communication with the rest api.
I have created a realm in keycloak and configured the realm to use an Identity Provider Redirector with an Identity Provider I added in keycloak (user-defined OpenID Connect v1.0). In the identity provider configuration I have set all the URLs to point to my java application but the initial OIDC authorization call from the client just redirects to the redirect_uri with a #error=login_required without any of my endpoints in the java application beeing triggered.
I guess there is something I have missed… I need to intervene the authorization flow so that I can pick up a query param from the authorization request that needs to be handled in my java application. I also need to map the token from the rest api into the token request (when this request comes from the backend of the client app), and finally map the userinfo object as a response to the userinfo request.
I really hope someone have time to point me in the right direction. Thank you so much in advance.
Recently i was also looking at creating a custom IDP, about OIDC flow you can see at this OIDCIdentityProvider.java
keycloak does not have particularly good documentation, so you can view libraries that have been written by others, likes Keycloak-FranceConnect
, keycloak-discord
, you can search libraries in github
In my exploration of the past few days, development based on keycloak 8.0.0 version may be better.
1 Like
I have made a sequence diagram to try to explain it better:
I need to intercept the authorization request call to pick up a custom query param (endUserString) that identifies the user. There will be no user login form. I need the param in my code that uses this towards the REST API. Both the token and the userinfo must be received from my APP and not from keycloak itself.
The Java Mediator may ask for a token in advance (A) and use this to access the Rest API (using a predefined clientId and clientsecret). Alternatively this token may be fetched for each method. To token must be used to retrieve customer info from the REST API (B). I want to wrap this with OIDC support without any login form. A browser will just redirect to the authorization flow with the endUserString identifying the end user. The customer info will be returned from the java mediator into keycloak responding this in the GetUserInfoRsp.
Did you do it?
I think this is pretty straightforward:
- Check
org.keycloak.authentication.authenticators.browser.IdentityProviderAuthenticator
for an example of how to get uri params in the authentication flow and then CookieAuthenticator.java
for how to communicate success to the flow.
- Setup a custom flow using your authenticator
The steps above will authenticate a user in the keycloak database. The second part would be to get this user form your rest API.
For that, you need to implement a UserLookupProvider
.
In your authenticator, when you ask for the user with id endUserString
all classes implementing UserLookupProvider will be called until one return an UserModel. You just implement the query to your rest API here, convert the api data to Keycloak Model (user info, roles and permissions) and let keycloak handle the rest of the OIDC flow.
Hope this helps.
1 Like
Hi. Thanks. Sorry for the late response as I haven’t been logged in to this forum for quite a while. I followed the comment from Allan on stackoverflow (java - Create a custom identity provider and configure it with keycloak - Stack Overflow) and managed to create a custom Authenticator intercepting the OIDC authentication flow. I added ‘extends AbstractUsernameFormAuthenticator imlements Authenticator’ to my class and fetched the query param from context.getHttpRequest().
Then I called my rest api and added the params to the context.getSession().users(). In addition I added mappings from User Attributes in keycloak and everything was working well in the getUserInfo method.