We are using keycloak-adapter with Jetty for authentication and authorization using Keycloak.
As per Keycloak doc for OIDC Auth flow:
Another important aspect of this flow is the concept of a public vs. a confidential client. Confidential clients are required to
provide a client secret when they exchange the temporary codes for
tokens. Public clients are not required to provide this client secret.
Public clients are perfectly fine so long as HTTPS is strictly
enforced and you are very strict about what redirect URIs are
registered for the client.
HTML5/JavaScript clients always have to be public clients because
there is no way to transmit the client secret to them in a secure
manner.
We have webapps which connect to Jetty and use auth. So, we have created a public client and it works awesome for webapp/REST authentication.
The problem is as soon as we enable authorization, client type gets converted to Confidential from Public and it does not allow the reset it as Public. Now, we are in soup. We cannot have public clients due to authorization and we cannot connect webapps to confidential client.
This seems to be contradictory to us. Any idea why client needs to be confidential for authorization? Any help on this how can we overcome this issue?
Thanks.
As far as I understood, you have your frontend and backend applications separated. If your frontend is a static web-app and not being served by the same backend application (server), and your backend is a simple REST API - then you would have two Keycloak clients configured:
public client for the frontend app. It would be responsible for acquiring JWT tokens.
bearer-only client, which would be attached to your backend application.
To enable authorization you would create roles (either realm or client scoped, start on the realm level as it's easier to comprehend). Every user would then be assigned a role/s in the Keycloak admin UI. Based on this you should configure your keycloak adapter configuration (on the backend).
All things considered, in order to talk to your REST API, you would attach a JWT token to each HTTP request in the Authorization header. Depending on your frontend framework, you can use either of these:
Keycloak js adapter
Other bindings (angular, react)
P.S. For debugging I have just written a CLI tool called brauzie
that would help you fetch and analyse your JWT tokens (scopes, roles, etc.). It could be used for both public and confidential clients. You
could as well use Postman and https://jwt.io
HTH :)
I think you are referring to the "Authorization Enabled" switch in the admin console of Keycloak, when creating a client. If you go over the question mark next to the label, you'll see the hint "Enable/Disable fine grained authorization support for a client.
Create client in Keycloak admin console (v 6.0.1)
This is meant for when you create a client for a backend application that serves as a resource server. In that case, the client will be confidential.
If you want to create a client for a frontend app, to authenticate a user and obtain an JWT, then you don't need this.
See also: https://www.keycloak.org/docs/latest/authorization_services/index.html
After much deliberation, we found that authorisation is not required to be enabled on public client really when you connect to it. When any request come to public client, it only does the authentication part. Authorization part is done when actual request lands on the resource server (in our case, Jetty) using the confidential client (as Jetty has knowledge of confidential client configured in it).
Related
I have a spring boot (backend) & angular (frontend) app that I'd like to secure with keycloak (for the authentication).
I have a very basic deployment, in which the executable jar created by spring also serves the client code (from angular).
I have seen several tutorials where the front and back are separated, and the front uses the code flow + pkce to delegate its authentication to keycloak, while the back is stateless and checks for presence of a jwt token certified by the keycloak instance.
However since I have a backend server, I'd like to avoid using a public client and instead rely on the back-channel token exchange on the server side. So the front should not have any knowledge of the keycloak instance.
Is that possible / is it a best practice ? Is there a front library that helps me to achieve that ? I've come across the library keycloak-angular, but it seems to be directed towards the first case, where the SPA connects directly to Keycloak instead of using a backend server.
In such a case you don't need a frontend library. In your frontend you should just handle user session (have a session cookie) and send the cookie every time to your backend. Then the backend server should use any oauth client to communicate with your keycloak server, and once it gets the tokens it can save them in a db together with a handle to your session.
Here's how this flow might look like:
request client -> backend server -> reply with a 302 to the keycloak authorization endpoint. Registered redirect_uri should be a uri exposed by the backend server
user performs authentication / consent, etc.
Keycloak redirects to redirect_uri with code
Backend receives code (as it listens on the redirect uri address), and exchanges it with Keycloak.
Backend receives access token and saves it in a DB together with session ID.
When clients makes another request to backend with their session, backend picks an access token from the DB and can call an API.
We are implementing Single Sign On [SSO] across multiple applications, which are hosted on different domains and different servers.
Now as shown in the picture, We are introducing a Authenticate Server which actually interacts with LDAP and authenticate the users. The applications, which will be used/talk to Authenticate Server are hosted across different Servers and domains.
for SSO, I can't use session variables, as there are different servers and different applications, different domains, a domain level cookie/session variable is not helpful.
I am looking a better solution which can be used for SSO across them. Any demonstrated implementation is existing? If so, please post it or point me in the right direction for this.
You can achieve this by having all your log-ins happen on the auth server. The other applications can communicate to the auth server through a back channel. The general principle is like this:
User accesses application 1.
Application 1 needs the user to sign on, so it sends a token to the auth server through the back channel. Application 1 then redirects the user to the log in page on the auth server with the token as a parameter on the request.
User logs in to auth server. Auth server sets a cookie, flags the token as authenticated and associates the user details with it. Auth server then redirects user back to application 1.
Application 1 gets request from user and calls auth server over back channel to check if the token is OK. Auth server response with user details.
Application 1 now knows that the user is authorised and has some basic user details.
Now this is where the SSO bit comes in:
User accesses application 2.
Application 2 needs the user to sign on, so it sends a token to the auth server through the back channel. Application 2 then redirects the user to the login page on the auth server with the token as a parameter on the request.
Auth server sees that there is a valid log in cookie, so it can tell that the user is already authenticated, and knows who they are. Auth server flags the token as authenticated and associates the user details with it. Auth server then redirects user back to application 2.
Application 2 gets request from user and calls auth server over back channel to check if the token is OK. Auth server response with user details.
Application 2 now knows that the user is authorised and has some basic user details.
There are some existing implementations of this method, for example CAS (Central Authentication Service). Note that CAS is supported out of the box in Spring Security. I would advise you look at using an existing implementation, as writing your own will be hard. I have simplified things in my answer and there is a lot of potential for introducing security holes if you're new to this.
I will recommend you check out OAuth. It is a good Authenticaiton and Authorization protocol used by several large organizations including facebook, google, windows live and others. It may have an initial learning curve, but it is a production grade solution.
It also has libraries for Java, Ruby, PHP and a range of other programming languages.
For example, the following server side implementations are available for Java.
Apache Amber (draft 22)
Spring Security for OAuth
Apis Authorization Server (v2-31)
Restlet Framework (draft 30)
Apache CXF
Following client side Java libraries are also available:
Apache Amber (draft 22)
Spring Social
Spring Security for OAuth
Restlet Framework (draft 30)
Please refer here for more details:
http://oauth.net/2/
http://oauth.net/documentation/
The bigger question is how you are implementing single sign on. Many open source and even proprietary (IBM Tivoli) offerings worth their salt offer cross domain single sign on capability. This would be the easiest and best way to implement cross domain sso. You can configure the LDAP server you use in the sso server you choose.
Taking for instance open sso, here is an article to configure cross domain single sign on
http://docs.oracle.com/cd/E19681-01/820-5816/aeabl/index.html
To configure LDAP in open sso,
http://docs.oracle.com/cd/E19316-01/820-3886/ghtmw/index.html
Reference on the issue is presented in a neat diagram here
http://docs.oracle.com/cd/E19575-01/820-3746/gipjl/index.html
Depending on which offering you use, you can configure cross domain single sign on.
With this, your diagram will look like this, with the auth server being your utility to interact with sso server of your choice.
Having an auth server that communicates with sso is a sound architecture principle. I would suggest making calls to authenticate as REst end points which could be called via http from different applications.
You cannot use Rest Service .
You could use what i call a Refferer Url Authentication
Say you have a Authentication application running on www.AAAA.com
In the applications , where you want to authenticate , you could have a filter which looks for a authenticated cookie in its domain else redirect to www.AAAA.com for authentication
On Successfull authentication , you could pass the user profile information as encrypted GET / POST data back to the application
Since I have built a Java application, I have been looking for an SSO solution for it. I found a free Java SAML Connector using which you can achieve SSO in java based applications built using any java framework.
Here's the link to it - https://plugins.miniorange.com/java-single-sign-on-sso-connector
Setup
We're developing a distributed application with Java and Spring where our existing client front end (complete with its own authentication, database, accounts, etc.) uses REST calls to access our new server for additional services. We want to protect these resources with Oauth.
Access should be restricted by role or account. However we don't want the user on the client side to have to worry about any additional authentication apart from the already existing account. At the same time we need to provide a means for third party applications to access some resources from the outside after going through some kind of registration against the server (which is why we're distributing in the first place).
So we have set up spring security on the server side to provide accounts that should be used to restrict access to the resources. The user should log in on the client side and then be able to access only those server resources assigned to him. We have some kind of registration process that sets up the user on the client side to be able to access the server services so any account setup I think should be done there.
So the questions are
How can I enable the client side to obtain an access token for the protected resources without the user having to log in to his server-side account?
And how do I setup the server side account without needing any user input?
My thoughts
This won't do
I'm thinking I'll have to either tell the client about a new account created on the server side for that user (but then, how would I choose and communicate a password?) or synchronize the client side account to the server, and use those credentials to authenticate the client against the server and generate access tokens. But how save can that be? Also the server has a much higher security (one way encrypted, salted passwords) on its accounts and I don't really want to compromise this by using the less save client accounts.
Maybe this will?
Maybe the way to go will be to tell the server about the client account during the first authentication, create an account on the server side, store the generated token on the client side and then authenticate the client against the server with that token for each subsequent request..? Will the server be able to log-in the client using its server-side account via that token for each request?
I'd need a special resource for that initial (2-legged?) handshake that can only be accessed from the client server, right?
Also:
Which would be better suited for the task, OAuth 1 or 2?
I'm hoping someone understands my problem and can help me sort through possible missunderstandings and knowledge gaps (I'm reading through Oauth and spring security documentations right now, so I'll update if I come up with a clearer picture and thus clearer questions of what to do)
Thanks for any help!
So our current status is to use OAuth2 mostly for reasons of simplicity. We're also sure that the flaws it might have concerning security we can cover ourselves as needed and they will most likely be addressed in the future by the implementation vendors or the IETF.
To handle the communication between REST server and REST client (both in our control) we use the formerly known as 2-legged authentication, now client credentials grant. I've asked a few questions on SO about that including
our current spring-security context setup
the client credentials flow in particular
the use of long lived tokens versus reauthentication
and how to limit REST access by HTTP method
Concerning the use of client based user accounts for authentication against the server we didn't get any further.
For now we authenticate the user against our old client web application as before and then authenticate the client against the server 2-legged. In theory this will allow any user to access any resource using the client accesstoken but for now that's okay for us so we will not investigate further down that road.
Still, should anyone have a good idea on how this might be solved we'll pick it up, just to tighten security further. So, I'll leave this question open.
My thoughts currently are along the line of registering a new client ID for each user on the authentication server with a generated secret and then synchronize those back to the client server and use those client_id / secret combinations to access resources for a user represented by the generated client_id in a client credentials flow.
For our latest application we'll store accounts on the REST server (authentication provider) and have the user login against that server and then use the token to access the REST resources as intended by the spec.
I'm developing a html5+jquery+phonegap application. Server side is written in java and Spring MVC.And I hope to implement an authentication model as follows.
client signs up using his email which would be used as his userID.
A token is sent to his email.
He is given a screen to enter the token.
That token is stored in the local storage of the client.
everytime the client calls a webservice, his userID and token is sent by the app over https.
Server authenticates him and responds.
What are the options available to implment this kind of security from the server side? can Spring-security be used in this way? I tried to find any implmentation with Spring-security, but couldn't find any implmentation other than basic authentication.
You can use PreAuthenticationProcessingFilter to achieve this requirement, have a look similar case and spring security doc
Today's there is more and more web services developed for internal use to connect applications together. We do not have an ESB to control and secure this web services so I guess on what is a good way to secure them.
We have try to setup Two-Way SSL but we are not able to control the authorization on a particular web service.
My need is to be able to control which application is calling my web service and is this application authorized to call it.
I don't like WS-Trust and Ws-Security because this alter the original SOAP message but it seems that they are no other solution.
Any idea?
Thanks
In your question you mention that you do not want to modify the current SOAP message - that means message level security is out.
So you need to go ahead with transport level security.
Even with two way SSL you wil be able to authorize users based on the thumbprint of the user certificate - how to do that depends on the stack you use.
Other option are..
Basic Authentication over HTTPS
2-legged OAuth
The difference is, 2-legged oauth supports non-repudiation while basic auth does not.
Irrespective of the mechanism you use to authenticate, you can use XACML for fine grained authorization...
you can use the http basic authentication over https. It lets back end application to know the user and hence possible to do authorization.
This link[1] shows how I have done a similar thing with WSO2 ESB. But depending on your stack there may be a way.
[1] http://wso2.org/library/articles/2011/06/securing-web-service-integration
My need is to be able to control which application is calling my web
service and is this application authorized to call it.
i feel that what you want is an authorization mechanism at your Service provider side.
if you do not want to do any encryption on your soap messages, you may consider to add new parameters to soap msg. e.g. client sents <applicationId> and <password> (or an encrypted AppId, PassWord string ) as new parameter to WS, at the WS provider side, WS checks if the application has right to call.
but this brings the changes to Client and Service implementation.
Or you could check the client IP of the request, to decide that it is from which application. If your applications have fixed Ip Addresses.