Authenticate credentials with LDAP for specific requests - java

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.

Related

Skip kerberos sso authentication in keycloak

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;
}

Programmatically authenticate user with Keycloak in java

I have been looking through the Keycloak documentation but cannot see how to do this. With Java, I'd like to take a valid userid and password and then generate a token. How can I do this?
--EDIT 2018-08-31--
You can use the Authorization Client Java API. Once you have created an AuthzClient object, you can pass the username and password to the AuthzClient#authorization(username, password) or AuthzClient#obtainAccessToken(username, password) method to authenticate the user and get the access token (and/or ID token in the first case):
// create a new instance based on the configuration defined in keycloak-authz.json
AuthzClient authzClient = AuthzClient.create();
// send the authorization request to the server in order to
// obtain an access token granted to the user
AccessTokenResponse response = authzClient.obtainAccessToken("alice", "alice");
On a side note, if possible, you'd rather reuse one of the Keycloak Java Adapters to cover more features, such as other authentication methods (the user is typically redirected to Keycloack WUI where you can enforce very flexible authentication and authorization policies).

Load user session with spring security

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.

OpenAM Authentication - logout

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.

User authentication and user related content using java jax-rs and angular js

I am trying to get a grasp on how to create a web application using REST (jersey) on the server side, and angularJS on the client, where a user can register/sign in in a secured fashion.
Once a user is signed in, I want to show user related content (his profile).
There are a few questions on this topic but are focused on specific aspects rather then a complete example, so there are few things I'm still missing.
to be more specific:
How do I use HttpServletRequest.login? the documentation specifies "Validate the provided username and password in the password validation realm used by the web container login mechanism configured for the ServletContext"
How do I specify a login mechanism?
Once a user is signed in, how can i display his profile?
Also, an example of such web application would be wonderful.
I think it will be helpful for you to take a look at Stormpath. In your backend, you can use the Stormpath Java SDK to easily delegate all your user-management needs. Since you are specifically interested in the login functionality, this is the way you would do it with Stormpath:
There are three options here...
You can completely delegate the login/register functionality to Stormpath via its IDSite
You can also delegate it to our Servlet Plugin
You want to develop your own login
If you decide to go with option 3:
Your front end will display the login form (BWT, Stormpath also supports Google, Facebook, LinkedIn and Github login)
When the user presses the login button, your front end will send the credentials securely to your backend-end thorough its REST API.
Your backend will then try to authenticate the user against the Stormpath Backend:
/** This code will throw an Exception if the authentication fails */
public void postOAuthToken(HttpServletRequest request, HttpServletResponse response) {
Application application = client.getResource(applicationRestUrl, Application.class);
//Getting the authentication result
AccessTokenResult result = (AccessTokenResult) application.authenticateApiRequest(request);
//Here you can get all the user data stored in Stormpath
Account account = accessTokenResult.getAccount();
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json");
//Here you can also return some of the user data to your front-end in the response
JSONObject dataSet = new JSONObject();
dataSet.put("Email", account.getEmail());
dataSet.put("Username", account.getUsername());
response.getWriter().print(dataSet.toString());
response.getWriter().flush();
}
Please take a look here for more information
Hope that helps!

Categories