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
Related
I have gone through multiple blog posts and StackOverflow questions before writing my own. I have multiple queries and none of the posts answer them.
I am using Keycloak Spring Security Adapter to secure my legacy Spring application. I referred to the keycloak documentation here and was able to have OAuth flow running for me. I am using Client Id and Secret as Client Authenticator.
For eg: Access to localhost:8080/about.htm will redirect me to keycloak login screen and after successful authentication, I will be able to view my page. I am also using the below code to read the user details from the token,
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) auth.getPrincipal();
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
user.setUsername(idToken.getPreferredUsername());
Now when I test this application using postman and modify the generated access token, obviously the server gives an error. Ref : How to test application using postman.
However, this is the flow :
Client sends a request to the resource server, resource server checks for a token - if it exists, the client does the validation. If it doesn’t exist or is invalid, it redirects to the authorization server (KC).
My question is,
Who is validating this token? How does postman flow throw an error
if I fiddle with the token?
Do I really need to write a JwtTokenValidator in my application for
each request? Won't that be overkill?
If I use Client Authenticator as Signed Jwt with client secret, will this validation still be required? I am not using it as it introduces latency.
Please assist.
Answer to #1:
When you use any Keycloak adapters in your application (in your case the Spring adapter for Keycloak), that's the one who does the validation and redirects to the login if necessary. As part of the validation, it checks the signature of the token issued by Keycloak. So when you fiddle with the token, the signature doesn't match, hence it throws an error.
Answer to #2
No, you shouldn't need to implement a JwtTokenValidator. The adapter does it for you and a request should reach your endpoint/URL only if it has a valid token. You may only need to do that if you have a special requirements about validating the token (e.g. checking specific claim in the token against some service). Otherwise, you can safely use the claims in the token you received from the KeycloakSecurityContext. You can even setup authorization based on your URL patterns and Keycloak will enforce them too and allow the request to pass if user has necessary roles (like this example).
Answer to #3:
That option only changes the method used to authenticate your app to the Keycloak and has nothing to do with the user's token validation inside your app. In your current setup, when your app wants to communicate with Keycloak (e.g. to exchange auth code with auth token), it authenticate itself to Keycloak with a client-id/client-secret pair (otherwise Keycloak would not know it's your app and will reject the request).
If you choose the "Signed Jwt with Client Secret" option, your client can not just use a client-secret to authenticate to Keycloak. It should support the RFC7523 specification. So it's quite complex in compare with a simple clien-secret approach. In an environment in which you trust your clients (e.g. they're all known apps developed inside the company and you're not going to support public clients to join your Keycloak and use its services) it's quite common and safe to use client-secret approach.
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).
I have created Java Web Application by using Netbeans IDE. I have created entities with relationships. Webpages are simple dashboards where I can add new entities, change them and delete them.
I have added Restful web services to my entities. So web page will be available only for admin and I want to create client application that will have access only for his own data. That means client must login or register to my server.
When user logins/registers on website, server will create session for this user. I know that in RESTful service there is no sessions. My thought is to pass login and password every time when client wants to do some operation with server.
Question: is there any other method to create something like session between client and server? I hope it is not connected with encryption.
There are many options for authentication as well as authorization. If you want to use simple authentication then 'Basic Auth' of HTTP. Check out https://www.rfc-editor.org/rfc/rfc2617 for details. Remember that this is unsafe because the username/password flows on wire. Anyone can sniff username/password. This is updated by new RFC7235 - https://www.rfc-editor.org/rfc/rfc7235#section-4
Safer choice is oAuth. Explained in RFC6749 https://www.rfc-editor.org/rfc/rfc6749. In this case an access token goes with each request.
In both the cases the credential details travel with headers. No interference with parameters.
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
I'm developing a web application that has a REST api. At the moment the Api are protected in the server side trough spring security with a form-login authentication. Recently I also added spring social to allow access with facebook and twitter and all this works. So a user has to be registered to access some endpoint.
Now I have to build a mobile application that has to access the REST api and I was wondering what strategy I should use.
I saw that facebook has a android/ios sdk to allow the authentication on mobile side. So once theuser is authenticaded on the mobile I should do the request to my server so how should I authenticate the user on the server side to access the resources?
If you think that is not a good solution can you give me an advice how I should solve this problem?
Two options:
Your mobile app can login to your API the same way your other client code does, via form-login or spring social. Simply send the same session ID cookie with your API calls after login.
You can allow your app to accept a username and password as HTTP headers via HTTP-Basic, to save yourself the initial login step. This might be more useful if you don't need to make a lot of API calls per session.