Can you post your code for your IdentityProvider implementation
Sure, thanks for your help.
This is the Provider
public class WebSealIdentityProvider extends AbstractIdentityProvider<WebSealIdentityProviderConfig> {
public WebSealIdentityProvider(KeycloakSession session, WebSealIdentityProviderConfig config) {
super(session, config);
}
@Override
public Response retrieveToken(KeycloakSession keycloakSession, FederatedIdentityModel identity) {
return Response.ok(identity.getToken()).type(MediaType.APPLICATION_JSON).build();
}
@Override
public Response performLogin(AuthenticationRequest request) {
try {
URI webSealLogin = new URI("http://localhost:80/webseal");
return Response.seeOther(webSealLogin).build();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
@Override
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
System.out.println("CALLBACK ---> - " + callback.toString());
return new WebSealEndpoint(this, this.getConfig() , callback);
}
}
The performLogin is redirecting to a local Docker container running WebSeal, hence the localhost
This is the WebSealEndpoint, where I think the problem is:
public class WebSealEndpoint {
private WebSealIdentityProvider provider;
private WebSealIdentityProviderConfig config;
private IdentityProvider.AuthenticationCallback callback;
@Context
protected HttpHeaders headers;
private static final String EFIKEY = "EFIAPPUSERNAME";
@Context
protected KeycloakSession session;
public WebSealEndpoint(
final WebSealIdentityProvider provider,
final WebSealIdentityProviderConfig config,
final IdentityProvider.AuthenticationCallback callback) {
this.provider = provider;
this.config = config;
this.callback = callback;
}
@GET
public Response done(@Context HttpHeaders headers) {
Map<String, Cookie> cookies = headers.getCookies();
String id = getUsername(headers);
AuthenticationSessionModel authSession = this.callback.getAndVerifyAuthenticationSession(id);
session.getContext().setAuthenticationSession(authSession);
// The above 2 lines are necessary to avoid -> java.lang.NullPointerException: Cannot invoke "org.keycloak.sessions.AuthenticationSessionModel.getClient()" because "authenticationSession" is null
try {
BrokeredIdentityContext identity = new BrokeredIdentityContext(id);
//identity.setAuthenticationSession(authSession);
//identity.setBrokerSessionId("239832Aisji");
identity.setId(id);
identity.setIdpConfig(config);
identity.setIdp(this.provider);
identity.setUsername(id);
identity.setFirstName("John");
identity.setLastName("Doe");
identity.setBrokerUserId(id);
identity.setModelUsername(id);
return callback.authenticated(identity);
} catch ( WebApplicationException e ) {
e.printStackTrace();
return e.getResponse();
} catch (Exception e) {
throw new RuntimeException("Failed to decode user information.", e);
}
}
private String getUsername(HttpHeaders headers) {
Map<String, Cookie> cookies = headers.getCookies();
for (String cookie : cookies.keySet()) {
if (cookie.equals(EFIKEY)) {
return cookies.get(cookie).getValue();
}
}
throw new NullPointerException("no user!");
}
}
As mentioned in a previous comment, I have setup a new client that uses a custom flow that internally uses this Id Provider.
Keycloak correctly redirects me to the WebSeal page, but after login in that page the Keycloak console logs:
DEBUG [org.keycloak.services.resources.IdentityBrokerService] (executor-thread-5) Invalid request. Authorization code, clientId or tabId was null. Code=dddd, clientId=null, tabID=null
ERROR [org.keycloak.services.resources.IdentityBrokerService] (executor-thread-0) invalidRequestMessage
WARN [org.keycloak.events] (executor-thread-0) type=IDENTITY_PROVIDER_LOGIN_ERROR, realmId=cd8a6a33-93c3-4343-82b5-2261744275a3, clientId=null, userId=null, ipAddress=127.0.0.1, error=invalidRequestMessage