Spring Security Oauth2 dynamic redirect uri - spring-security

How do i dynamically specify redirect uri for Oauth2 Authorization code flow in spring security? I have a use case where the application is being accessed by multiple users using 2 to 3 different urls. A user using one particular url has no access to another url. In this case, i want to configure oauth2 so that i can just provide /login or something instead of the entire url

In my case I wanted to be able to login and use my web app from two different urls, one for running the frontend locally from localhost.app.mydomain.com and one real url like app.mydomain.com using Google to login.
Simple solution
To achieve this in Spring Security I registered two different ClientRegistration's with the exact same info, except for the name, registrationId and the redirectUri
From the frontend I can then control which Oauth2 client I use by invoking the different registrationId endpoints which in turn decides which domain I'm logged into and which redirectUri will be used based on if I'm running my frontend locally or not.
It is not truly dynamic but solves the case where you have a limited number or redirect urls that you know on beforehand which can be controlled from the frontend this way.
Dynamic solution
Another more common solution, which I also use in my code, would probably be to pass a state parameter with the call to the oauth client in Spring. That will then get passed on to google and be returned untouched to Spring security from the google login flow. This can have whatever info you want to decided by the frontend and then decoded in the backend and e.g. the SimpleUrlAuthenticationSuccessHandler use this data to setDefaultTargetUrl to this which will cause a redirect to wherever the frontend decided on a successful login.

Related

Make existing form-login application also serve as an oauth2 authorization server?

We had an web application that already using form-login provided by spring-security, say, ERP. Now we are considering make ERP as an oauth2 authorization server to authorize other internal services.
The ERP still serving its business and all access are required to be authorized, but doesn't based on access token so I think it is not an oauth2 client. It does NOT serve as an Resource Server, neither.
I have read many article about how to setup oauth2 authorization server and develop an application using it. According to this comment I feel it is possible to make ERP authorizing other services without explicit setup a standalone authorization server (it's our final goal but not now):
Within the context of OAuth2, we can break things up according to the component you're implementing:
Client app: it's likely that server based OAuth2 Client app already uses HttpSession and therefore it makes sense to use Spring Session and benefit from all the goodies it brings
Resource Server app: since this component provides a stateless API that's authenticated against using an Access Token as a bearer, the HttpSession is not used and therefore Spring Session isn't suitable as well
Authorization Server app: it's highly likely that this already uses HttpSession so similarly like with OAuth2 Client app, it makes sense to use Spring Session and benefit from all the goodies it brings
What I'm going to do is add the #EnableAuthorizationServer into config, but I have no idea what's the next step.
My question is can I convert an existing application into an authorization server while keeping its original service unchanged? Where and How should I start?
I just found it's not that hard to integrate OAuth2 into existing system, below is what I did to make it work.
In short: EnableAuthorizationServer won't break anything exists, but they don't coming from nothing, either.
When I put on the EnableAuthorizationServer, spring-security-oauth2 gives me following endpoing:
/oauth/authorize
/oauth/check_token
/oauth/token
/oauth/confirm_access
/oauth/error
Those endpoints provide necessary functions to make OAuth2 works, and I just need to apply access control onto those endpoints with existing form login mechanism (probable not the check_token one).
Since this system didn't act as resource-server role, the authorization part is done.

How to handle authorization and authentication on SPA with OAuth2?

I am developing an SPA and would like to have SSO.
As I understood so far, OAuth2 with OIDC is the best solution for SPA SSO.
Better than, for example, SAML.
What I didn't understand so far is how to use authorization token in SPA's JS code to handle authorization on various resources of SPA. For example, I would like the users with a role 'buyer' to have access to the shopping history tab, where other users won't have access to.
Should I parse access token obtained from Authorization server in JS code and check whether a user has an appropriate role to see the tab, or should this decision be made on server (API) side, in which case SPA's code would just read the answer from API and based on that customize UI?
In case of the first approach, is there any standard way of doing the checking (in form of some JS library)?
When it comes to authentication, what is the better approach (more secure, etc):
to let SPA (at that point already loaded in the browser) do the authentication flow and based on result let the user use it's protected functionalities. This is pseudo authentication actually since the code is in the user's browser and means the user is authenticating himself to the code in his hands i.e. to himself. Does this authentication make sense at all?
require the user to authenticate himself in order to be able to even load the SPA in his browser. This is probably not SPA architecture then since backend which serves the SPA should be able to create a backchannel with the Authentication server.
According to user description, your application must vary depending on user type. If this is the case I would suggest you to use a backend for authentication and decide application content to be served from the backend. Otherwise, as you have figured out, running authentication on browser and altering user view is not secure.
IMO this not necessarily break SPA architecture. What you are doing is altering what you server based on tokens presented to you. Also, maintaining a session will be required with this approach. And SPA's calls for backend will require to contain this session to obtain contents.
As soon as the User is logged in, you would request for authentication and based on his UserId, and the role he belongs to you should receive all the permissions that User is entitled to.
You convert these permissions into claims and can send them back to UI and use it appropriately to show the features accordingly.
You also enforce same on the server side api to prevent any unauthorized access besides from your UI.

Spring Security OAuth2 - Custom Authentication

We need to expose a REST endpoint to the outside world to be called by an external service which we don't control. The people responsible for this external service seem to be security experts (not), and so instead of using at the very least HTTP Basic Auth or any other real authentication mechanism, they authenticate themselves using a fixed secret. It goes like this:
GET /endpoint?secret=WE_ARE_THE_TRUE_GUYS
As we're already using spring-security-oauth2, we'd like to integrate this authentication flow with our existing flow so that we can specify rules for this endpoint the same way we do for every other enpoint on our ResourceServer, get the same error handling behaviour and etc. How shall we go about implementing a custom authentication filter - or whatever it may be - that will grab the secret parameter from the query string, transform it into some kind of "client credentials" for a pre-configured client on the AuthorizationServer and integrate seamlessly with the rest of the OAuth2 flow?
If you can transform "WE_ARE_THE_TRUE_GUYS" into a valid OAuth2Authentication then all you need is an authentication filter that does that (and sticks it in the SecurityContext). Then the downstream filters and handlers will behave just as if it was a real OAuth2 authentication. If I were you I would put some very tight conditions in that filter to match the request to one that is on the allowed resources from this highly unusual and not very secure authentication channel.

RESTful WCF Data Service Authentication

I'd like to implement a REST api to an existing ASP.NET MVC website. I've managed to set up WCF Data services so that I can browse my data, but now the question is how to handle authentication.
Right now the data service is secured via the site's built in forms authentication, and that's ok when accessing the service from AJAX forms. However, It's not ideal for a RESTful api.
What I would like as an alternative to forms authentication is for the users to simply embed the user name and password into the url to the web service or as request parameters.
For example, if my web service is usually accessible as
http://localhost:1234/api.svc
I'd like to be able to access it using the url
http://localhost:1234/api.svc/{login}/{password}
So, my questions are as follows:
Is this a sane approach?
If yes, how can I implement this?
It seems trivial redirecting GET requests so that the login and password are attached as GET parameters. I also know how to inspect the http context and use those parameters to filter the results. But I am not sure if / how the same approach could be applied to POST, PUT and DELETE requests. Can I use GET parameters in POST, PUT and DELETE requests?
Edit: The question for me how to embed login and password into the web service's URL so that I can perform POST, PUT and DELETE requests against the web service. I do know how to implement authentication once the web service is running and the login / password are contained somewhere in the HTTPContext. Also, I am not looking for ways to implement forms or basic authentication. I know how to do it, but it is not what I am looking for.
In the end I used a threefold approach, either of these authentication methods work fine on my data service:
Basic authentication with the API key as password
Authentication via an API key embedded as request header
URL-based authentication with the API key as path to the API. I implemented this with a proxy ASP.NET MVC controller.
I've not had to use restful via authentication but I do have to ensure that groups of users have the rights to access the rest service. This I do via an MD5 token that gets passed to the web service (this is a normal JSON service, not a WCF wrapper). Basically, I "know" which websites are allowed access to my service, so I give them their own API key (which for simplicity is an MD5 of the domain name. This gets checked incoming by a filter against the urlreferrer and if the MD5 of it matches, then it's a go.
I know this isn't the authentication answer but it's a mid-trust approach that works if you need only a very course level of "authentication".
I'd be interested to see how others do this, though, for other projects that I may need a less course grained approach to authentication.
See if below answers helps you:
your first question:
Is this a sane approach?
If your service is running over https, I dont see any probelm to use this method.
If yes, how can I implement this?
You can use GET parameters in your other methods eg. Here stream is passed in body.
[OperationContract]
[WebInvoke(Method="POST", UriTemplate = "UploadFile/{fileName}/{userToken}")]
string UploadFile(string fileName,string userToken,Stream fileContents);
OData - WCF Data Services Best Practices from TechEd - Meta-Me - Site Home - MSDN Blogs
<system.web.extensions>
<scripting>
<webServices>
<authenticationService enabled="true" />
</webServices>
</scripting>
</system.web.extensions>
How about this?

ASP.NET MVC multi-site SSO using OpenID

I am putting a plan together for a series of sites that will share user account information among them. The idea is that once a user logs in using their OpenID, they can access any of the sites and it will know who they are.
What are the common patterns/best practices that i could employ to achieve this?
If all the sites share a common hostname in their URL then you can set an auth cookie (FormsAuthentication.SetAuthCookie) specifying the path of the cookie to be "/" so that all sites can see the user is logged in.
If the sites are not sharing a common host name, I think the only way to get a truly "once signed in, signed in everywhere [within your ring of web sites]" would be for all authentication to happen at just one site (perhaps one dedicated to authenticating the user) and for the other sites to redirect the user to that site for authentication and then that site would redirect back. In essence, that auth site becomes an identity provider, and almost exactly fills the role of an OpenID Provider (in fact DotNetOpenAuth could be used here for this exact purpose). Since it sounds like your goal is to let the user log in with their OpenID, your OpenID Provider on that one auth site could itself use OpenID to authenticate the user. Your own pure-delegation OpenID Provider could be written such that it always responds immediately to checkid_immediate requests as long as the Realm in the auth request is one of your trusted ring of sites. Thus you could effect single-sign-on across all your sites.
Please consider the following Patterns & Practices on Web Service Security from Microsoft:
Brokered Authentication - http://msdn.microsoft.com/en-us/library/aa480560.aspx
The main topic is - Web Service Security
Scenarios, Patterns, and Implementation Guidance for Web Services Enhancements (WSE) 3.0
http://msdn.microsoft.com/en-us/library/aa480545.aspx
Ultimately theres lots of ways you could do it. I achieved a simple single sign on by building a url with a token from one website pointing to another domain. The encoded & encrypted token contained details to submit back to the previous domain. Upon receiving an incoming request on the second domain, an underlying web service checks that the incoming request's token is valid with the previous domain using a shared private secret, known to both domains.

Resources