In certain cases we need to skip automatic login through Kerberos.
According to the documentation this should be done through the parameter ?prompt=login:
prompt - Keycloak supports these settings:
login - SSO will be ignored and the Keycloak login page will be always shown, even if the user is already authenticated
This works in most cases (we also use a NTLM waffle implementation) but with Kerberos the user is always signed in automatically.
Any hint or idea why? Are there alternative ways to force forwarding to the login page?
EDIT: The reason I need to skip the Kerberos authentication is because I need to login with an admin-account where I have to enter username+password.
EDIT2: We are using Keycloak.x version 14.0.0, also applies to version 15.0.2.
The parameter ?prompt=login will only skip the Cookie authenticator in your authentication flow. Execution of the Cookie authenticator will be marked as attempted but not as successful. So Keycloak will fallback to an alternative authenticator. I am assuming the Kerberos authenticator is configured as an alternative. If this is the case, you will be (automatically) authenticated by the Kerberos authenticator.
If you only need this behaviour for a particular client, you may want to create an additional authentication flow for that client without the Kerberos authenticator. Use Authentication flow overrides to configure the new flow for the client.
I just created a feature-request with a possible solution on the code side.
skip kerberos SSO authentication to use login-form
Might be able to override the default SpnegoAuthenticator with a custom one containing the login parameter handling.
I patched and tested it in a kerberos environment and it worked.
#Override
public void authenticate(AuthenticationFlowContext context) {
// +++ BEGIN CHANGE +++
AuthenticationSessionModel session = context.getAuthenticationSession();
Map<String, String> clientNotes = session.getClientNotes();
if ("login".equals(clientNotes.get("prompt"))) {
logger.info("skip SPNEGO authenticator because of client requests login prompt: " + clientNotes); //$NON-NLS-1$
context.attempted();
return;
}
// +++ END CHANGE +++
HttpRequest request = context.getHttpRequest();
String authHeader = request.getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authHeader == null) {
Response challenge = challengeNegotiation(context, null);
context.forceChallenge(challenge);
return;
}
Related
I am trying to implement Keycloak as an IAM, the Problem that I have is, that I need to authenticate the user (already working) but also authorize him. The authorization should be accomplished through keycloak directly, but the security information (like roles, etc.) is available over an REST interface externally.
The way it is working now goes as followed:
authentication request (default)
"authorization" request → keycloak server (with extra form param)
keycloak server → CustomProtocolMapper (calls external REST interface and adds claims to Token)
Token → frontend client
This worked until I used a refresh token to refresh the ID Token. The Cookie that is used to authenticate the user is not sent to the keycloak server, because of security reasons (Cookie labeled as "Secure" but connection over HTTP). To fix this I upgrade my keycloak server to use HTTPS/TLS and now i am getting errors because the "HttpRequest" is no longer available. Any ideas on how to get the Request Body of an HTTPS Request inside a CustomProtocolMapper? I know that the Authenticator Providers has access to it, but i dont know/ didnt find anyway to add claims to the Token inside it.
#Override
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession, KeycloakSession keycloakSession,
ClientSessionContext clientContext) {
String contextParamName = mappingModel.getConfig().get(CONTEXT_PARAMETER);
// worked with http
HttpRequest request = keycloakSession.getContext().getContextObject(HttpRequest.class);
String contextId = request.getFormParameters().getFirst("activeContext");
LOGGER.warn("activeContext: " + contextId);
}
Thanks in advance,
best regards
I'm using Jhipster 4.13.3 with the Oauth2/OIDC option to generate a gateway connected keycloak.
I think there could be an inconsistency in the generated code, or I missed something ;)
In the java config (MicroserviceSecurityConfiguration.java and oAuth2Ss0Configuration.java), CSRF is disabled.
http.csrf().disable()
But in the Angular UI (auth-session.service.ts), a resource is called to refresh the CSRF token.
logout(): Observable<any> {
// logout from the server
return this.http.post(SERVER_API_URL + 'api/logout', {}).map((response: Response) => {
// to get a new csrf token call the api
this.http.get(SERVER_API_URL + 'api/account')
So, first question, is that call to refresh CSRF token really needed since the CSRF protection is disabled ?
Second question, why is CSRF disabled ? I don't see access_token on the client, it's probably on the server, but there's a jsessionid cookie stored on the client, could it be stolen and used by csrf attack ?
Thanks !
Philippe
I'm developing a web app that will be used inside Cisco Jabber as a Custom Tab.
In my app the user needs to be logged in. The first authentication is done using Spring SAML (SSO). if this authentication fail then the user fallback to one of those auth process :
- A: directly with his userid (not a real auth but needed for some client)
- B: a login form (auth against client database)
The problem is that some actions are creating popups and with Jabber those popup are opened in Internet Explorer which doesn't have any information concerning my user and thus my app tries to authenticate him again. If SSO works no problem no action required by the user, if that fails auth A works fine but if auth B is selected then I have an issue because I need the user to be authenticated without him entering his credentials.
Is there a way with Spring, Spring Security to copy the session from Jabber to IE skipping the log-in page?
I followed the advice here and tried to set the jsessionid as parameter of my popup url like this:
var logUrl = 'login.do' + (this.user === '' ? ';jsessionid=' + sessionId : '?userId=' + this.user);
var w = window.open(logUrl, number, 'width=800,height=600,resizeable=yes,scrollbars=yes,toolbar=no,location=yes,status=yes,menubar=yes');
The problem is that when the user open the popup, the jsessionid in the url is not the same as the one in Jabber. And if I try to log in with the JSESSIONID of the user in Jabber it doesn't work.
Is there some configuration parameter I haven't set for this to work?
The session is tracked using the JSESSIONID cookie so you could pass this as a URL parameter on referral.
However, there are security concerns around session hijacking to consider with this approach.
For example, you must use SSL/HTTPS.
See this answer for more information.
Solution: We dropped the idea of re-using the session and are now using jwt instead as it achieve basically the same thing for us.
I'm beginner with OpenAM, I'm working on an existing project.
I use this documentation to improve our authentication service:
http://docs.forgerock.org/en/openam/10.0.0/dev-guide/index/chap-authentication.html
The login works fine, I receive my token Id and add it in the cookies. I stay connected when I browse restricted web pages.
Now I want to do a clean logout.
When you read the documentation about logout, they propose this code:
protected void logout(AuthContext lc)
throws AuthLoginException {
lc.logout();
System.out.println("Logged Out!!");
}
But in my program, I do not have the login AuthContext anymore.
Is there a way to get or create an AuthContext associated with my user ? This call is it necessary ? (actually, We modify the cookies to be rejected by OpenAM)
Thank you.
Answer:
SSOToken ssoToken = SSOTokenManager.getInstance().createSSOToken(tokenId);
AuthContext authContext = new AuthContext(ssoToken);
authContext.logout();
Firstly I think you should be able to create a new AuthContext by having access to the session token, by using this constructor.
Secondly it is not necessary to use the ClientSDK to perform authentication remotely, you could also just use the REST APIs, which probably would be a bit more lightweight.
I have a web application that I deploy using JBoss 5.2. In order for a user to use the application, he/she must authenticate with an LDAP server (using simple authentication) with a username and password. This is all done through setting up the login-config.xml for JBoss and providing a <login-module> with our implementation.
The problem comes in here: After having logged in, I have a scenario that requires the user to provide a username & password when a particular action is performed (which I will also authenticate with the LDAP server). I want to be able to reuse the same mechanism that I use for authenticating the user into the web application.
My form to log in to the application posts to j_security_check so in accordance with this, I was trying to send a request to j_security_check but JBOSS returns a 404. From reading around a bit, I've gathered j_security_check cannot be accessed by any arbitrary request and must be in response to a challenged request to a secured resource.
So then, how can I authenticate the second set of credentials the user has provided with the same LDAP server?
EDIT:
To clarify, the question is how to send the user's credential inputs to the LDAP server for authentication. Grabbing the input from the user, etc. is all done. All that is left is to take this input and send it to the LDAP server and get the response (which is where I am stuck).
If it helps to mention, the login to the web application uses a custom class that extends UsernamePasswordLoginModule.
So, after lots of research, I ended up finding a solution for JBoss environments (which is what I'm using).
Once you capture the user's credentials, you send them to your server via a POST/GET and your server can perform the following to use whatever authentication policy you have configured (in login-config.xml) to verify the credentials:
WebAuthentication webAuthentication = new WebAuthentication();
boolean success = webAuthentication.login(username, password);
To expand on this, I was also able to check the user's role/group via the HttpServletRequest (which is passed into my server-side handler):
boolean userIsInRole = servletRequest.isUserInRole("nameOfGroup")
The spring security documentation explains it
Wanted to add another answer for JBoss 6.2+, where WebAuthentication no longer exists.
I've used the creation of a LoginContext to achieve the same result:
String SECURITY_DOMAIN_NAME = "ssd"; // the security domain's name from standalone.xml
String username = "user";
String password = "password";
LoginContext lc = null;
try {
lc = new LoginContext(SECURITY_DOMAIN_NAME, new UsernamePasswordHandler(username, password.toCharArray()));
lc.login();
// successful login
} catch (LoginException loginException) {
// failed login
}
And the use uf lc.getSubject().getPrincipals() to verify roles.