I was just wondering how does the control of the execution reach the Authentication EntryPoint in spring security. I did not find anything in the Authentication Filters that transfers the control to the Entry point.
I have a custom Authentication Filter and Custom Authentication Provider. I need to redirect to a third party authentication server for authentication and this apps send me the authentication token that will authenticate the local app.
How an from where do i send the control to authentication Entry point.
Please do let me know if i am missing something obvious here.
The best place to start is the API docs for the interface. This points you to the ExceptionTranslationFilter which explains when the authentication entry point is invoked. Basically, it is used when someone is not authenticated and their request is rejected because they need to be.
If you have an external authentication server, you might want to look at the CAS implementation as a guide. Your filter should probably be checking the incoming request for a token and redirecting to the external server if it isn't present. In that case you might not need an AuthenticationEntryPoint at all, since no unauthenticated requests would get past your filter.
It's hard to give more specific information without knowing how your external authentication server works.
Related
I wrote a chain of spring applications, each of which performs some unique functionality. It is a stretch to call this combination of separated services a microservice architecture. And now, I would like to implement spring-security. However, I think it's silly to implement authorization and authentication functionality for each of the services.
Can you advise how right it is to make one more service which would serve as a common place for authorization and authentication? And already in each of the already written "microservices" I would check this authorization.
For example, I see the following path to a "microservice". The client makes a request to the common security service and gets some kind of jwt token there and with this jwt token goes to any of the services and gets authorized there. In this case, this jwt token determines what rights are granted to this user. I would like to control access to end-points within the applications themselves, and get the jwt token from the outside.
The most important question. Is it possible to implement this? If it's possible, is it the right way to do it?
I would be immensely grateful for any examples or articles on the subject!
We have specific requirements around the authentication flow and UI/UX that cannot be satisfied through Keycloak's theming engine and extensions to the Authenticator SPI.
I looked into the Action Token SPI and it seems like an extension point that could be used to delegate (most of) the authentication flow to an external application. According to the keycloak quickstart action-token-authenticator example (https://github.com/keycloak/keycloak-quickstarts/tree/latest/action-token-authenticator), it seems like it can be used specifically for this purpose.
For a browser authentication flow, the idea would be that we would have keycloak initiate the flow by first verifying the username/password. If that is successful, we would redirect the user to the external application (supplying it the action-token and username/id of the user) to perform the supplemental authentication process - e.g. custom MFA. If the external application successfully performs the supplemental authentication, it will then redirect back to keycloak with the action-token, to resume and complete the authentication process that was initiated earlier. With this externalized login process, we would have full control on every aspect how it can be designed/implemented.
Any thoughts/comments on whether this approach is feasible, secure and proper use of Action Token SPI?
Thanks in advance.
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.
Edit:
I have added a sequence diagram 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.
I think there might be a simpler solution than what you envisioned: implementing your own custom authenticator for Keycloak.
Keycloak has a notion of authentication flow which is a tree of authenticators than are provided by Keycloak or custom made. Each authenticator can be called to try to authenticate the user.
The most common one is the Username/Password Form which displays a login page to the user and authenticates the user if the provided credentials are valid. But you could imagine any type of authenticator such as an SMS authenticator or a magic link one.
You can find the existing Keycloak's authenticators on their repo and the documentation on how to create your own here.
In your case, you would need to implement your own logic where your authenticator would get the endUserString param from the request and call the REST API to validate the user's identity. You could fetch the REST API token at initialisation or for each request. You could also modify the user stored in Keycloak with data coming from the REST API's user info endpoint (common OIDC attributes or custom attributes).
Please note that the dev team announced Keycloak X, a sort of reboot of the project which will probably bring breaking changes to their APIs.
Also, please consider all the security impacts of your design as, from what you provided, it seems the authentication of a user will only rely on a simple query parameter which, if it doesn't change over time for example, feels like a big security hole.
I have a spring app, which is hidden behind the proxy. App requires authentication on the start screen (log in form). Proxy also requires authentication (basic auth). Let assume that I cannot get rid of proxy.
Obvious idea is to not force users to log in twice (credentials are usualy the same).
However, that would mean, that users would be authenticated with GET request (using basic auth), which seems a bad idea, so I have few questions:
Is it a generally not-so-bad idea to authenticate users during GET request ?
I still try to implement it by my own with spring authentication filters, however I want to ask if this a good approach? For log in form I have my own WebSecurityConfigurerAdapter and also my own endpoint which handles authentication (which basically sets a cookie).
I assume that for my case I would have to have second WebSecurityConfigurerAdapter which will authenticate users through basic auth using authentication filter ?
If yes, is there a way to set ant matchers only once ? Otherwise how I see it, is that I will have to set the request matchers for both Configurations which of course some day may lead to inconsistency ?
I have a hopefully quick question about Spring Security.
I am looking for a solution to integrate security into our application which provides SSO but HTTP basic as well.
One of the automated pieces of our system can only support basic authentication and we are pretty locked into it. Currently we are targeting to use Kerberos for our SSO solution and then also support basic (for very restricted usage). All of this will protect RESTful web services that run through resteasy.
Does anyone see any inherent impossibilities in this solution of both Kerberos and BASIC chained together in spring security? We had problems with WildFly and undertow not being able to support multiple different authentication methods, that use HTTP response codes in their handshakes.
Thanks for the input
Since this question is a bit tough, I assume you are already familiar with the Spring Security Kerberos samples that show how to configure kerberos auth with a form auth as fallback.
I have no evidence that it'll work but I think you should be able to chain your kerberos auth with basic auth without any problems. I share my thoughts on this...
Thought 1: FilterChains
The trick to support mulitple authentication methods is to set the order of the authentication filters correctly.
If the order is wrong, the client could hang in the basic auth and might never reach the kerberos authentication filter, because the browser's basic auth dialog would pop up. This might depend a bit on how the basic auth provider and filters are implemented in Spring. Anyway, if the order is correct, the filter next in chain after the kerberos filter (the basic auth filter) will start its work.
Thought 2: Kerberos auth shouldn't break basic auth
The browser should treat the communication with the kerberos service provider different to the communication with the basic auth provider, since the protocols are different.
The SAML communication runs in it's own namespace, thus in my opinion it shouldn't affect the basic auth communication which is based on authorization element in the HTTP header.
EDIT: Even if the assumption about the namespace doesn't play any role in the browsers behavior, step 6 in the sequence diagram will be a crucial point. When the filter chaining is correct, Spring should return a 401 response like 401 - Access denied - WWW-authenticate - Basic realm = "your domain" which will force your browser into basic auth.
Thought 3: Spnego Negotiate in Spring Security Kerberos
The Spnego configuration in the Spring Security Kerberos documentation is acutally build upon those thoughts. This can be seen in the samples, too, in line 49 and 50 of this WebSecurityConfig.java
I would be surprised if you experience troubles.
One last thought
If no requirements force you to do a basic auth, I would recommend to not use it. Better stay with a token based authentication. Even if I don't fully agree on all details of this blog it explains why basic auth shouldn't be used, if you can avoid it.
I strongly recommend you read Mika's answer. It is very well done and gave me the confidence to move forward.
Ultimately this worked; but I will explain a couple sticking points I had.
I use Request matcher's to split my calls into different HTTP configuration blocks
In order 1 I configured a block to filter in requests from a specific tool, by user agent. In that block I configured basic authentication in basically the standard OOTB way. I did write and provide my own authentication provider though, this provider called to an underlying system we use to manager our users by username / password.
Then, in order 2, I configured a block to process Kerberos. After wrestling with the Kerberos provider configuration and coming up with a scheme to authenticate in our underlying system, this all processed fine. After getting the username from Kerberos for the domain user connected to my web app, I then checked to see if that username was in my system. If they are, we log them in. If not, we direct them to the login page. (Not every domain user is authorized for our web app, even if they are authenticated)
Then finally, the last block was configured for form authentication.
But there were a few sticking points.
I had to globally configure the authentication manager for both my custom basic/form and the Kerberos provider.
And also as a side note, I did have to configure my authentication manager bean like this link suggests. Probably due to the cobbled together shamble of of xml/java configuration I have created.
IE was also weird. Down my kerberos chain, I also configured a login form. This allowed users who qualified for the chain to navigate directly to the login form to authenticate; or if someone failed my Kerberos username check I could forward them to the login page. This worked fine with FireFox, but IE continues to send the Negotiate header even after my server sent a redirect. Basically the user fails kerberos, gets a redirect to the login page, but IE sends the Kerberos token along still. This causes the SpnegoAuthenticationProcessingFilter from Spring Security to fire again and validate the Kerberos token, of course this fails again, and sends the user the login page which continues the loop.
In summary Spring Security allowed for 3 nice, fairly clean blocks which all do various different authentication / authorization, and then it all works in tandem to provide the same user context object to our web app.