Spring Authorization Server. What's the difference between RegistredClient and UserDetails? - java

On their Getting started guide, reference, Spring Authorization Server have a piece of code where they declare two beans - UserDetailsService and RegistredClientRepository. I wanted to play around retrieving some tokens from the server. I tried using postman. Within authorization tab I entered the values from the guide:
it answered with:
So then I tried inputting client credentials from RegistredClientRepository entry:
And it worked.
So my question is: what is the purpose of UserDetails and RegistredClient being both available in this case?
And another little bit off-topic question: if I create my own authorization server for client credentials flow between my servers, how does every server know that token belongs to legitimate server and not to some attacker who can just register with needed clientId if there's an opportunity? How can resource server actually verify that token owner is the server it trusts?

Generally in oauth2, a "client" is an application which users might use to interface with some service - for example something like an App people can install on their phones or a web application.
Most oauth2 implementations have "scopes" (basically defined sets of access rights). Clients (client applications) are registered with some metadata (name, author, ...), a set of scopes they might use and some details to improve security - like "where is that application hosted" (in form of "which redirect URIs are valid"), client ID and client secret.
Depending on the oauth2 flow chosen, your App needs to prove being that app by some means - e.g. by having a valid combination of client ID and redirect URI or by doing HTTP basic auth with their client ID as username and client secret as password when exchanging a "code" for a "token".
All this was about clients - now about users: they are what you would expect, the users of a service - like you and me are users on Stackoverflow.com
And another little bit off-topic question: if I create my own
authorization server for client credentials flow between my servers,
how does every server know that token belongs to legitimate server and
not to some attacker who can just register with needed clientId if
there's an opportunity? How can resource server actually verify that
token owner is the server it trusts?
for this you could either use a form of signed tokens (look at e.g. JWT) or store the currently valid tokens per user in a database reachable by all your servers - both have pro's and con's, tokens in a database are easier to revoke, while signed tokens don't require you to store any state in a database (which can be expensive in big distributed systems)
Update - OP actually wants to do server-to-server authentication, see comments below
Server-to-server authentication can often work very well without any extra authentication server, in cases where your parties a less dynamic - like when you always have "those three servers" and they don't come and go very often.
In such cases, using a simple token is probably better and easier than using an oauth2 stack. Each server could just have a list of randomly generated strings in its config file, let's call this "the set of valid tokens" and also knows which token to send when communicating with a specific other server. When a request comes in, the server checks if the given token is in its set of valid tokens - done.

Related

Web app security architecture

I have a Java Spring driven REST API server connecting with PostgreSQL database and a Spring Web Server in Java that is serving content from the REST API to the client using JavaScript (now browsers, but in the future also mobile apps).
I've read a number of articles and topics how one can secure a REST API, but I haven't been able to make a final decision yet. I don't want to have Basic Authorization, because it doesn't make sense as I would need to store credentials in JavaScript that can be easily accessed and read by anyone entering the webpage and developer console. I'd like not to show any credentials to the end user so I can't keep them on the client's side.
I've read a lot about JWT and almost decided to implement it, but I've heard it has some drawbacks and haven't been so sure since then if it's the option I would like to choose. I know there is also oAuth 1.0 or oAuth 2.0 but I don't know if I want to have something this complicated. I would also like to store hashed user credentials in my own database in order not to be depended to any other credential providers like social media or Google.
Now I'm making another layer on my web server as a proxy hoping that it will allow me to authenticate user on this proxy level using Spring Security and having some kind or cookies or something to authenticate, but I'm not so sure if its doable this way and it increases the respond time, adds complexity and needs me to write controller methods for these endpoints. My architecture now is of the following:
Client (browser) -> Webserver -> REST API server -> db
I've also denied all external connections and allowed only localhost access to REST API on tomcat level so that I'd have to implement the security level only on the web server allowing free information transit between the webserver and REST API as it is not reachable anyway.
Web server and REST API are on the same server running as Tomcat instances.
I'm also not so sure if this kind of architecture will allow me to authenticate mobile app clients through the web server.
I would be very grateful for any piece of advice you would have for me in this matter. I'm not so experienced in security, so I'm a bit lost what I should do. Does this kind of architecture any sense or should I simply ask REST API directly from any type of clients, be it a webpage or a mobile app from different IPs and secure Rest API only? And if I want to secure some subpages of my webpage or parts of mobile app should that be an completely other layer?
Thank you for your help.
You have already gone through OAuth, JWT tokens etc. If you don't want to use them,then you can create your own token based authentication system.(say 'TokenHandler').
How this TokenHandler will work ?
TokenHandler will be like a gateway server i.e your every REST API request will route through this server application. So you will address your confusion of mobile and web application call with a authToken in header. Main responsibility of this server applciation is to accept the token and validate against the database where all token details are maintain. This DB will have information regarding timestamp when token was last used to validate, to decide your validation rule .
How Token will get generated ?
Token can be any random 64 digit alphanumeric string and will be generated and updated in DB during every single login activity. Login webservice returns this token in response body.
What can be rules for validation ?
It can be depending on your business logic. I preferred to keep active session window of 15 mins. Means if you access the webservice you will get active window of 15 more minutes. If you didn't access any service for 15 consecutive minutes then from 16th Minute you will need to login again to access further calls. This part can change according to requirements.
How client side will handle this ?
Client side will store this token and pass this token with every request call. Token Handler will validate and redirects it's request to the application server . So your one token handler can be used to server authentication of multiple applcation servers. This you can achieve by application end point identifer.
I will like to discuss further if you have any questions or suggestions .
Use API Gateway Architecture Pattern for your use case -
http://microservices.io/patterns/apigateway.html .
The API Gateway (The webserver in your question) can act as single entry point for all desktop/mobile clients. You can use either session cookies or jwts to authenticate clients at gateway.
With respect to authentication between gateway and micro services, and between micro services, i would suggest mutual ssl - https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication. If you are using spring boot, this might help - http://www.opencodez.com/java/implement-2-way-authentication-using-ssl.htm
The problem with IP white-listing approach is that - it's not well suitable for cloud architecture as the IPs might change with every server reboot. Even if you are using dedicated IPs, you should be careful to secure the communication with SSL/TLS, else attackers can easily sniff your traffic.

Can / should I refresh an OAuth2 token with every request in spring security

We use the username-password grant to connect our JS client to our REST server. In a way the token returned by oauth/token is our session, as it allows access to the backend for a limited time.
We would like to refresh that session/token every time we make a request to the backend using the token.
I know there is this refresh token issued by the server and I could use it to refresh my token after it has expired.
The thing is: I don't want to make it the client responsiblity to catch token expired exception and re-authenticate or schedule a refresh prior to token expiration. I want the token to refresh itself until it is not used any more for a limited amount of time - just like a session. (I also wouldn't like it to issue a refresh request with every "data" request, though I think I remember reading, a refresh token is only valid once..?!)
Is there a way to do that in spring security or will I have to build some custom implementation of the token store or whatever part I choose?
Since I can't really find an answer (hence the post) I'm thinking: Maybe it is not wise to do this, though I can't think why. If I can steal the token, I can steal the refresh token as well. So I guess I don't really see the point in having a refresh token in the first place..
EDIT
In response to Luke Taylor's answer I'll clearify our use case.
We have a REST server that holds application data like persons. but also provides access to our content management and allows clients to post to facebook. It encapsulates application logic and data storage
We have a fully fledged client application already in place that has its own security layer and justs accesses the data on our REST server via client credentials flow. Who can do what is decided on the client side
We have several medium and small applications like a contact app on facebook that access the data on the REST server also using client credentials
We are now developing a client application using only javascript that will access the REST layer to do all the stuff the big client application does but also needs to provide a means to authenticate individual users and allow multi tenancy. Therefore this new client application uses the username-password grant to authenticate and method level security to authorize the users
So we have a REST server that needs to provide complete access to our trusted application that does its own security stuff and that same server needs to provide access for users of our new multi tenancy javascript client application. In production we will have several REST servers each with its own database but the core will always be the same, so in theory one server should be able to handle all.
I want the token to refresh itself until it is not used any more for a limited amount of time - just like a session
This doesn't really make sense (in an OAuth2 context). The access token is issued by the authorization server, which decides how long it is valid for. It is "used" at a resource server, which may be completely separate from the authorization server, so there is no facility in OAuth2 to connect usage with the lifetime of the token. It would in theory be possible to hack something together which made this work, but it sounds like a bad idea.
If I can steal the token, I can steal the refresh token as well. So I guess I don't really see the point in having a refresh token in the first place..
The access token is used repeatedly and sent by the client to servers other than the authorization server. The refresh token is retained by the client and only sent back to the authorization server. A client also has to authenticate to successfully use a refresh token, so the client id and secret would also have to be compromised.
It's not really clear from your question why you are using OAuth2. You should probably expand your question to clarify this. If there is only one client and a REST server, why not just use something like BASIC auth over HTTPS?
Also, is the client a browser-based app? If so, the username/password grant isn't really suitable for use in an untrusted client.

Single Sign On [SSO] across different domains using Java

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

OAuth + spring security for internal REST communication

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.

JAX-WS, Authentication and Authorization - How to?

What is the best way to do authentication and authorization in web services?
I am developing a set of web services, requiring role based access control.
Using metro - SOAP, simple java without EJBs.
I want to Authenticate the user just one time, using username and
password, to be matched against a data base. In the subsequent calls.
I would like to use some kind of session management. Could be some
session id, retrieved to the client at login, to be presented in all
calls.
So Far:
Read authentication using a database - but I want application level validation;
Read application authentication with jax-ws - but i don't want to do the authentication mechanism every time;
I think I can use a SOAP Handler, to intercept all the messages, and do the authorization control in the hander, using some session identifier token, that comes with the message, that can be matched against an identifier saved in the data base, in the login web method.
EDIT:
I still have some questions:
How to know the name of the web method being called?
What kind of token should I use?
How to pass this token between calls?
EDIT 2
Because of #ag112 answer:
I'm using Glassfish.
I use WS-Policy and WS-Security to encrypt and sign the messages. Using Mutual Certificate Authentication. I would like to complement this message level security between applications, with the authentication and authorization for the users also in message level.
I am just developing the services, and I don't know almost nothing the clients, just that they could be created in different languages.
At this point I think the most important thing is to do what ever I need to do to authenticate and authentication the users, I the most easy way to be implemented for the client applications.
#Luis: Here are my inputs.
Well exact solution for your problem depends upon kind of web service clients you expect, do you have control over web service client system, your app server etc.....but assuming you don't have any control over web service client, for you it is just a SOAP message over HTTP transport, here is probable solution.
You can of course performs session management & authentication at message level or transport level. It means either you can have session token and auth token information in SOAP message or you can use standard HTTP Session and HTTP authentication mechanism.
Of course transport level solution is much simpler and industry wide standard in case if transport layer is HTTP. For message level, ws specifications like ws-security can be used.
Your each web service request is simple HTTP GET/POST identified by a unique HTTP URI.
Typically in jax-ws metro environment, WSServlet is one which entry servlet for any web service call and which eventually delegates the call to right service provider implementation class. Since you application is going to be deployed in web server, you can exploit all session and authentication facilities provided by J2ee web container.
Since you are looking for role-based access control, I would use standard <web-resource-collection> in web.xml to specify which role you would like to have in case of particular HTTP URI. You can use standard JAAS login module which can do authentication and populates the JAAS subject with role. If user name/password are provided in SOAP XML, JAAS login module can also search/parse SOAP XML to retrieve those information. JAAS/app server will automatically create auth token and store it as cookie so that each subsequent request need not to go through authentication process again. This is all J2ee standard. You can find plenty of help on internet on this. Please let me know your app server so that I can provide you additional details.
If you still want to use SOAP message level session management, authentication & authorization process, then to provide you more details, may I know more details about your client side.
EDIT1:
Well based on your further inputs, here is my more thoughts:
Message security namely encryption and signature needs to happen each message travels between server and client. where as message authentication- you intend to do once and give a session token/auth token to client for subsequent calls.
Question still remains: if you put a unique session Identifier in SOAP response of first time authentication, do you expect client to parse SOAP response XML and ensure that client should send you session identifier each time in subsequent SOAP requests.
OR
You want to keep session management transparent to client and for client it needs to send username/password token first time and subsequent calls need not require any username/password token. In this case you would need to rely on transport based session management for e.g. HTTP cookies
Now what is the best for you depends upon your use case. Can you tell me what is expected use case flow? how another system (web service client) makes more than one service call to your system? Is another system user driven/some background process? What is exact need that you want only first service call to go through authentication process not subsequent calls?
PS: Glassfish server provides a way of configuring message authentication provider which automatically enables/disables message level authentication.
EDIT2:
I understand you do not want to store user credentials in client app and web service server need those user credentials.
OAuth is open standard protocol which allows site A to access user's private data on site B. Ultimate idea is site A gets auth token which has specific expiry time. So Token containing encrypted from of user credentials or jsession id help you avoid need of re-authentication. You only need to decide where you want to keep token at client app side
You can keep token as cookie if transport is HTTP protocol.
Having said that ofcourse passing user credentials each time seems bit easier and straight forward.
You can also go for OpenEJB.
It used JAAS with WS-Security.
I hope the link is useful.
After all the help, I create this answer to simplify, and summarize all the ideas that was discussed.
The questions has 2 requisites:
Message level security;
One time authentication.
With ag112 help, this is hard to do, or to elegant in any way. So here are to conclusions:
For message level security send the user
credentials every time (place it in SOAP header);
For one time authentication use transport level security, and do a
session management.
I prefer the first one, because the message level was the biggest requisite.
As had no answers, following #unhillbilly advise, I answer my own question, with the progress so far:
How to know the name of the web method
being called;
Using a SOAP handler, finding the name of the first element in the body.
What kind of token should I use;
I decide to use a 128 bits token, representing each session. The Webservices, continue to be session-less, the key is just for authorizations purposes.
How to pass this token between calls.
For the login web method the result has the token, in each subsequent calls, the token is a parameter.
is there a better answer?

Categories

Resources