So, I have multiple projects, api, etc... And i'd like to have a central sign-in system. So I turn to SSO and the openId PKCE flow.
Let's say I want to use some cloud solution to save time and money - hypothetically, let's say AWS cognito, for its good integration with aws product.
Now let's say my cloud solution is still pretty much half backed in many regards compared to the competition and to my needs, for example we could imagine the hosted ui of the oauth sso login page cannot be properly customized or even translated, which is a no-go.
Now, we can imagine that we understand oauth PKCE code grant flow, and that we build a small server, or a couple of lambdas, to proxy the oauth implementation so that we can build an alternative front. The server would :
make the inital authorize request with the code_challenge provided by the client application, get a state - or in the case of cognito a csrf token - and return that to our "custom login font".
The "custom login front" could call our server with the csrf, the login and the password, and our server in turn would call the login endpoint of the oauth cloud solution, and check if the response is a redirect to our callback with the code provided - grab that code and return it to the login front for it to finally do the redirect after a nice loader has finished moving.
Would it be bad to do such thing, especially knowing that the login POST request to our oauth cloud solution might have to set a dishonest "HOST" header for the request to pass if we cannot host the login front and server on the same domain as our oauth cloud solution ?
And, finally, am I making sense at all ?
Related
I have been researching oauth2 for a while now and haven't come up with the perfect solution and wanted to see if anyone else has done this before. Currently I have two applications inside of one code base. The only thing these applications share is authentication. What I am looking to do is to create a third application for the oauth2 server. Then I want to separate the existing applications into two applications. Trying to follow how Google handles their oauth stuff. So the domains would be something like this.
http://accounts.domain.com
http://app1.domain.com
http://app2.domain.com
I found some good information in these two posts about doorkeeper and devise. Currently I am using devise so that makes that part easier.
https://dev.mikamai.com/2015/02/11/oauth2-on-rails/
https://dev.mikamai.com/2015/03/02/oauth2-on-rails-the-client-application/
So each of these applications app1 and app2 will have API's that the use will need to be authenticated against.
So I have the following questions.
If app1 needs to validate with accounts sub domain does that mean from an API perspective I need to call the oauth2 server application on each request? That seems like a lot of overhead. Is this the way that Google does it or do they have some trick?
Would app1 and app2 each be responsible for their own session timeout? What happens if app1 session is valid but the user deleted their accounts directly by going to the auth2 server application?
If app1 and app2 are responsible for session then would they also want to call back to accounts oauth2 server to validate the user still exists?
I'm trying to flush all of this out and haven't found a good example of how this would work when the oauth clients are actually API's plus they are web apps too. Maybe I am over thinking it too and that making the extra call for each API request is the way.
Any help or tutorial on this would be greatly appreciated.
The OAuth 2.0 Authorization Framework provides five grant techniques:
Authorization code grant
Implicit grant
Resource owner credentials grant
Client credentials grant
Refresh token grant
I believe our discussion is about Client credentials grant (I think google uses it generally).
Let's try to understand this flow chart:
So, here in the step [E]:
Steps (C) and (D) repeat until the access token expires. If the
client knows the access token expired, it skips to step (G);
otherwise, it makes another protected resource request.
It means it actually does not hits Authorization Server on each request. It only hits authorization server when client found that token is expired. So, if our deletes itself, it makes the token expired!
Maybe these document could help you more:
https://www.rfc-editor.org/rfc/rfc6749
https://alexbilbie.com/guide-to-oauth-2-grants/
Cheers!
I apologies in advance for incorrect use of oauth terms.
I have 4 "parties" as follows (intentionally not using oauth terms where possible):
End-user in a browser (javascript)
Our website (aspnet)
Our web api (aspnet)
Our auth server (aspnet utilising identityserver 4)
My usage scenario is that we only want the API to be called by a browser that has requested a page from the website first. Whilst the API doesn't release sensitive information, we would like to introduce a layer of complexity with regards to the API being spammed.
Our end user's will not be logged in.
I imagine such a flow being akin:
Browser requests a certain page from the website (one that will likely lead to js making an api call)
Website requests token from auth server
Auth server verifies token request came from website (the server itself)
Auth server returns a token to the website
Website returns page including the access token
Browser is able to make a request to api using token
Although convoluted, I believe this is at least similar to the Client Access Grant flow?
These tokens could then be throttled either by website or auth server.
Yes, I'm aware that this doesn't protect the api from numerous other vectors, but it does eliminate the simplest of cases which is all we're looking to achieve for now. I'll add, I didn't define this requirement, I'm simply trying to find a way to achieve it utilising techs out there instead of making the mistake of rolling anything of my own.
Could someone confirm/deny that there is an oauth flow I could use here? Any sample projects using the given flow and IdentityServer?
IdentityServer3 / non-aspnet[core/5] examples are fine, I can translate.
What you describe is the Client Credentials Grant where your website (client) gets an access token from identityserver (auth server). That access token can then be used to call endpoints on your web API (resource server).
The token is a bearer token and can be used by anyone who has it, so if you are comfortable with your website passing it back to a browser on an HTTP response, then it will work just fine.
I'm not sure what you mean by throttling the tokens - once minted they are valid for their lifetime. I guess you can keep the time-to-live very short to achieve the single usage you want though.
At my company we are developing several web applications that uses a REST API server.
First a little introduction.
The app provides the ability to manage users through the REST API and allows the users to login to the app.
Right now the REST API is for internal use only because we plan to develop more apps and communicate to the REST API as the central point of data access. We are handling the REST API authentication with a "Resource Owner Password Credentials Grant" implementation for the internal apps.
What we need is a Single-Sign on service for all the apps, we want a user to login to an app and if he/she access to another of our apps he/she will be already loged in.
We have been experimenting with the CAS protocol, with the CASino library specifically and it works great.
The problem is we don't know how to handle the flow between the apps, the REST API and the SSO service, also I don't know if there is a better choice regarding SSO services.
My questions are...
How we could handle the flow between the apps, the REST API and the
SSO service, because the REST API should be stateless it should not
communicate to the SSO service? or is there a way to communicate the
REST API to the SSO service?
Is there a better choice to implement a Single-Sign on service,
maybe OAth or OpenID and are this options suitable for REST APIs?
Thanks in advance!
Your REST API will have to talk to the SSO server to validate the Access Token, unless all the information it needs is encrypted inside the Access Token. Not sure what you mean by "flow between the apps", you should have all apps talking to a central SSO server.
When a user wants to create an account on WebApp1, the account should be created on the SSO server, either by redirecting them there or if you need a differently styled signup form for each web app, then via an AJAX call to the SSO server's REST API. I would recommend the latter as redirecting is more difficult to debug and it can make a bad user experience.
Make sure the messaging is clear, i.e. not "Sign up for a WebApp1 account", but "Sign up for a MyCompany account to get access to WebApp1".
OAuth 2.0 is very popular and people have more experience with it, so it's easier to get help or integrate with apps created by others.
The doorkeeper gem is a good server library.
OAuth 2.0 is normally used when the SSO server doesn't trust the client apps (e.g. Facebook, Twitter), but it can be implemented in such a way to skip the client authorization step (where the user is asked to approve the client app), and you can use the Resource Owner Password Credentials Grant via a REST API.
CAS is easier than OAuth. It is fairly easy to implement the basic endpoints and that way you can customize it as you wish.
I worked on a CAS-based server with a custom implementation (not sure if it was even really CAS-compliant). The authentication was done with Devise (I don't recommend Devise if you're going to customise it a lot, make your own in this case). The original flow was that the user went to the website, clicked Login/Register and then was redirected to the SSO server and after the user logged in, redirected back with a one-time ticket that the website's backend exchanged to an access token via a REST API call.
Then we added a REST API that was called from each website with AJAX. You send the username/password/captcha/etc and get back an auth token, which the site sends to its own backend. The SSO REST API can also set a cookie on its own domain, so that if the user visit another of our web apps it makes a call on pageload to check if the user is logged in. This way you're automatically logged in on every webapp without the redirect mess.
All tokens issued + the associated user info were sent to a fast Node.js app that would save them to Redis, and the app backends would call this app to validate the access tokens really fast, without putting load to the SSO Rails app.
I am working on a AngularJS web app and I am trying to implement single sign on. I had a nice implementation using Identity server and authorization server with implicit flow and oAuth tokens, however I need a mechanism to sign the user out of all apps they are signed into.
I am currently redirecting the user to authorization server, this then redirects the user to identity server. The user logs on and it shown a consent screen, a Json web token is then sent to the app via the query string and is put into local storage. This token is attached to the Authorization header which the web api (that is on a different domain) receives and either allows or denies the request.
The problem is oAuth has no way of singing a user out of all apps. I have now looked at WS-Federation using Json web tokens but this approach still appears to use cookies which I would like to avoid as the api and client app are on different domains.
Does Thinktecture Identity Server have any way to do this and if so are there any examples I could take a look at.
Thanks
As you already said - OAuth2 is not an authentication protocol and hence does not have the concept of (single) signout.
Firstly thanks for your time. I have a serious concern about Live Connect's OAuth2 API.
I follows this, and using DotNetOpenAuth to implement/integrate LiveId authentication/authorization for our federated identity & access management system.
http://msdn.microsoft.com/en-us/library/live/hh243647.aspx#authcodegrant
Everything is working fine for quite a long time. But now I'm having a serious trouble when fixing the replay attack issue for LiveId login module. Let's take a look at the Authorization code grant flow from the above article.
"*4. The user agent calls the client with the redirection URI, which includes an authorization code and any local state that was provided by the client. For example: ...Callback.htm?code=AUTHORIZATION_CODE.
5. The client requests an access token from the authorization server's token endpoint by using its client credentials for authentication, and includes the authorization code that was received in the previous step. The client includes the redirection URI that was used to obtain the authorization code for verification.*"
Right after the step 4, Live Connect OAuth2 server returns to my callback endpoint with the authorization code & state, like the following:
https://ssss.myapp.com:443/liveid/consume.idp?code=406dd558-0cda-50cc-bd37-d964ec29fbb3&state=uvygsnd3gba0jwi315kdyccs
Problem is, that authorization code could be used more than once. So it leads to the serious replay attack issue, like the following scenario:
User A when logging in to my application, chose LiveId to sign-in, then he's redirected to LiveId login page. He then logged in, Live Connect OAuth2 server returned to the callback endpoint with the code=xxx&state=yyy...user A then used this authorization code to obtain the access token...
User B when logging in to my application, chose LiveId to sign-in, he then logged in at LiveId's login page. Live Connect OAuth2 server now return with code=kkk&state=ggg
If I this time, use some tools like Webscarab to capture the response/request, then change the return from OAuth2 server to code=xxx&state=ggg (the old authorization code was given to user A, not B). Then after that, requesting for access token using this replay authorization code was going through smoothly. And guess what? I received again the ACCESS TOKEN which was given to user A before...and finally, user B can logging into my application as user A.
Please be noticed that, applying the same replay attacking like above for Google OAuth2 server, I received bad request error from the server, Google OAuth2 authorization code never could be used more than once. And the code flow or exactly, the implementation for Google login & LiveId login are exactly the same.
I used DotNetOpenAuth.OAuth2.WebServerClient to implement the OAuth2 authenticating flow for both of Google & LiveId. Again, exactly the same code, but Google OAuth2 server returned "bad request" when authorization code is reused, but LiveId returned the old access token of the previous user.
This is a serious security problem. Hope you guys have some ideas on this.
Or hopefully I'm wrong on some points. Please point it out.
Thanks very much in advance,
Phuc Le.
The OAuth 2 spec is quite clear here:
If an authorization code is used more than once, the authorization server MUST deny the request and SHOULD revoke (when possible) all tokens previously issued based on that authorization code.
This is for the exact reasons you mentioned above.
In your case, you should notify your provider of this issue.
Meanwhile, you could implement a cache of used authorization codes on client side and check for already issued codes. Note thate this could also produce false positives in the occasion that the provider randomly generated the same code for two different users (which might be quite unlikely, depending on the implementation).