In tomcat, I can setup security constraints that require certain resources to only be accessed by authorized users. The users are authenticated using either BASIC or FORM authentication, where a username and password is provided.
However, I'd also like to allow users to authenticate externally using an oauth provider. Is this possible?
Note that I can already pass all the information I need to acquire the access tokens for the user. From there I can get the username and other profile metadata.
But how do I then log the user into tomcat? The only way I can think to make this work is to take this username and create a tomcat account, maybe setting the access token as the password. Then I could do a tomcat login on behalf of the user, so she is locally authenticated. On subsequent logins I'd just update the password to the new access token.
But this seems like a hack, and when it comes to users and security I'd prefer to avoid hacks.
It looks like JASPIC might offer a solution for this? Unfortunately, it looks like it became available to tomcat starting at 8.5 but I'm stuck using 8.
Are there any other options?
Thanks!
Related
I would like to authenticate against KeyCloak using "Direct Access Grant": https://www.keycloak.org/docs/latest/server_admin/index.html#resource-owner-password-credentials-grant-direct-access-grants
I works like a charm when keycloak manages users and passwords on its own.
But, my scenario is different:
I would like keycloak to act a Broker to some external IDP. KeyCloak has identity brokering feature - but in only works in "Authorization Code flow" - redirecting user to external IDP login form.
I have mobile app and would like ot use "direct access grant" - so that app comunicates with keycloak to authenticate user - and keycloak, as a broker, authenticates this user (using openid-connect) in external IDP
How to achieve such scenario ? I know that it is not possible out of the box - but maybe somebody could advice how write an extension to keycloak do make this scenario possible ?
Whatever it is you are trying to achieve this way, it goes directly against what OAuth and OpenID Connect were designed for. The whole idea of using access tokens is to allow some relying party (such as a mobile app) to interact with a service on behalf of the user without ever getting to see the user's credentials (like a password).
Think of it like this. Let's say you have some app on your mobile phone. It can make use of certain services by Google. In order to do so it offers you to log in with Google and grant the app access. Now, would you want to do so by putting your Google email and password directly into the app? Of course not. That could give it complete control over your Google account, other apps and sites using your Google identity, possibly services that allow you to pay through your Google wallet... It would be insane to simply hand some phone app your Google login.
So instead with OAuth2 or OpenID Connect you can use the authorization code flow or implicit flow to have the user redirected to the identity provider (Google in our example) where they will complete their login process, and then the identity provider redirects back to the app or a site with an authorization code that can be exchanged for tokens or, for the implicit flow, the tokens themselves.
Now, when it's your own app and your own identity provider (like Keycloak) which are under your control it doesn't really matter. You can use a direct grant to simply have the user input their username and password into the app because you know it's not trying to steal user credentials to maliciously use your service. They're both under your control. In that case OAuth or OIDC are a bit overkill, but you could have separate clients for direct grants (your own app) and authorization code flows (third-party apps using your service). When you want to use Keycloak identity brokering, however, an external identity provider like Google or Facebook is not going to offer a direct grant and invite apps to steal their user's credentials. So you won't be able to interact with them this way.
Depending on what you're trying to achieve you may find some use in the token exchange process. If however the idea is that you want your user to log in with their external identity provider credentials, in your app, without a redirect... Don't.
This is a real use case, unfortunately Keycloak doesn't have a direct way of solving this issue. AWS's "IAM Roles for Service Account" feature works based on token exchange with direct access grant using external IDP. I found this discussion on how to workaround this lack of support in Keycloak but not sure if it solves all the usecases - https://lists.jboss.org/pipermail/keycloak-user/2017-January/009272.html
Do you stick with Direct Access Grant as a method of user authentication in your mobile app? In my opinion, you need to use Authorization Code Flow when the IDP is a third party service as it won't provide an API to authenticate users, and even with your own (first party) IDP, it'd be better to use Authorization Code Flow as stated in OAuth 2.0 Security Best Current Practice section 2.4.
To implement Authorization Code Flow in mobile apps, you will need to use in-app browser tab to show login screen provided by the IDP. Please refer to RFC 8252: OAuth 2.0 for Mobile and Native Apps for details.
I have the hope to use the token generation and management abilities of Keycloak, without authenticating against Keycloak's users but instead, 3rd party systems that do not use token based authorization.
In other words, I want to create a realm that generates tokens not for Keycloak users but for that 3rd party's users, meaning that there is no need to store users in Keycloak's DB.
Is this even possible? If it is could anyone give me some pointers?
From what I've seen the closest ability that Keycloak provides is the Identity Providers option available the Administrator console. Unfortunately and as expected, it works only for OpenID Connect and SAML which of course are token based.
I have a web application which is hosted on apache web server. And i have external java application which runs on tomcat integrated in this web application.
The apache is kerberized and I get the username of the person accessing it in the intranet. I want to use the same username and pass it on tomcat to check against ldap and authorize the user.
I was looking into JNDI realm which supports LDAP module. But the problem is I do not have access to the user's password. But I'm able to get the groups the user belongs to and based on that I want to authenticate the user.
So my question is will i be able to authenticate a user against Tomcat server via LDAP with just the username and not the password?
PS: Sorry there is no code or configuration that I can post at this point. The only resources i found implemented both username and password. I cannot kerberize the tomcat server because I have other issues in the network.
"I was looking into JNDI realm which supports LDAP module. But the problem is I do not have
access to the user's password. But I'm able to get the groups the user belongs to and based
on that I want to authenticate the user."
Once I was asked to write some code to do the very same thing. I found a way to make it work. However, although it seemed to work well enough with Internet Explorer which would automatically detect the Windows username (because my code was parsing some NTLM information that only Internet Explorer passes in as a header), in Firefox or any other browser the user would be presented with an authentication box and any username they typed in would be accepted! Its very insecure.
(Well, its not really true that only IE passes the header in. Only IE passes it in automatically; but Firefox also passes it in after someone gets the authentication box and types in any name they want. That's the problem.)
What I would suggest is writing a C#.NET service to do the authentication for real on a webserver that is IIS and has Integrated Authentication on. Then, redirect to the C# service when someone hits the Java site and the username session variable is null. Have the C# service save the info in a trusted/secure database including ip address and browser and redirect to the Java app which reads the db to validate IP address and browser and that the record was just created.
Edit: I just noticed you said your Apache is kerberized and already gets the Windows username, which may render the problem above about the unreliability of parsing the NTLM header null and void. In this case, if you can get the AD groups via LDAP you can authenticate the user in your webapp with your own code, but probably not using the official Tomcat authentication scheme. What is described above is just because my Tomcat is not paired with an Apache server but with a IIS server. So basically, its the same thing, except you won't need C#.
Since I'm running Java with Tomcat6 as servlet container I found it appropriate to use the Tomcat JNDIRealm feature so that LDAP users can log into my site without any additional efforts. The LDAP server I'm using is OpenLDAP on Ubuntu.
On top of this I have the login page using form-based authentication over an https connection.
I found two very good examples of authentication users via LDAP, here and here, that both achieve what I feel I almost achieved. Why almost achieved?
When I attempt to login with the wrong credentials I'm appropriately sent to the <form-error-page>, login-failed.html in my case.
When my credentials are good and I authenticate successfully I start getting a 403 for all urls in the site. And I cannot remove the 403 error (not even for the login page!) unless I restart Tomcat.
I suspect the reason is because I don't have roles in the realm or other config files set up correctly. For the sake of brevity I put the relevant config files excerpts on pastebin:
Realm in Tomcat server.xml
Relevant tomcat-users.xml part
Relevant web.xml part
Basic LDAP structure, dashes indicate tree structure
Note that Tomcat-based auth works perfectly since the role is easily attached to the user in the tomcat-users.xml. Therefore I believe it's a problem in getting the role for an authenticated user from LDAP once it has been successfully been authenticated.
TL/DR
I have a config issue in connecting Tomcat to LDAP auth. User data fetched properly, but not the user's role. LDAP log messages available on request ;)
UPDATE: I pasted the LDAP data here.
That is correct. Your LDAP roles aren't being found by the JNDIRealm. You need to test your role search string outside Tomcat to ensure it yields what you think it should yield. As you haven't provided any LDAP details it isn't possible to comment further.
Putting a security-permission on the entire site with /* is a mistake. You need to exclude the login page and probably also the front page and the forgot-password page, maybe more, from requiring a role.
I have a couple of Java-based web applications developed. Both the applications have separate Authentication logic based on some ActiveX directory implementation.
Now, I need to change this to Windows authentication so that whenever the user hits the URLs of my web applications, instead of redirecting him to login page I need to check his Windows credentials.
I do not want to store his windows credentials in URL.
Is there any good way to do this ?
Depending on the level of integration you want your web application to have, Spring Security should have you covered in just about all aspects of what you are after.
If redirecting to a login page and authenticating the entered credentials against an Active Directory server via LDAP is acceptable, then the LDAP extension is the way to go.
If you want more of a Single Sign On (SSO) flow and your users are already authenticated against the authoritative Active Directory server in question (eg. they are logged in to the domain), then the Kerberos plugin for Spring Security may be more appealing, since your users will simply have to go to the web application and won't have to go through any other authentication steps. The systems will take care of it behind the scenes.
You can also combine / layer these approaches if you which and try Kerberos-based authentication first and if that falls through, fall back to a login form and LDAP-based authentication.
If you need to go beyond that, Spring Security is flexible enough to allow you to use OpenID or in-app authentication as well if needed.
I'd recommending using Active Directory to expose it's windows authentication layer over LDAP, which can then be hit by something like Spring Security.
This would effectively force anyone using your application to use their windows login.