Introduction
I am trying to implement cross domain authentication. The problem that I am currently facing relates to sharing the session between two domains.
Sadly, I cannot make changes to the architecture as the websites are old monoliths.
Current setup
Our current setup consists of the following:
A first web site that supports authentication. Let's call it Site1.com.
A REST API that manages the authentication.
A second website that does not support authentication. Lets call it site2.com.
Site1.com and the Authentication API reside under the same domain as shown in the diagram here above.
How the authentication works
The authentication is simple. site1.com submits credentials to auth.site1.com and on successful authentication, auth.site.com return a secure cookie.
The change
We would like to add authentication to site2.com. As the diagram below illustrates.
However, this has proven challenging as third party cookies have been disabled on Safari. Therefore the browser is not forwarding auth.site1.com cookies while the customer is on site2.com.
We ended up redirecting traffic using our gateway to overcome this problem. The gateway is presented by yellow circle in the diagram listed here below.
The current problem
Now the two websites support authentication. However, the cross domain authentication is not working. I cannot figure out how to implement this part properly. Any help will be really appreciated.
Analyzing how Google and YouTube cross domain authentication works has led me to the partial solutions listed here below. However, I cannot figure out how it performs Cross Domain SSO on the latest Safari browsers? Any indications will be really appreciated.
Partial solution 1:
Use the SameParty attribute to declare my two websites as belonging to the same party and allow cookie sharing between this.
The solution will not need traffic redirection through the gateway. However, Safari and Firefox do not support it the cookie attribute.
Partial solution 2:
I have looked into performing Silent token acquisition using an iframe. Sadly, this solution does not work with recent safari browsers according to Microsoft:
Silent token acquisition no longer works when third-party cookies are
blocked - the application embedded in the iframe must switch to using
popups to access the user's session as it can't navigate to the login
page.
Other solutions
I have read on toolkit.org's blog about the Storage Access API. However, I am not sure if this will solve my problem. Also this solution might degrade the security.
Related
In web system, when some URL is protected, user is redirected to dedicated auth-page, and after login is (in convenient case) redirected back.
I understand that with mail.google.com and accounts.google.com the reason is huge google infrastructure, and may be different developer groups responsible for accounts and mail. And if I want to make user authenticate using Google, I become a part of it.
But in a average web app I can just do like hasAuth() ? renderProtected() : renderLoginDialog() without any redirects.
Tutorial for react router is showing example with redirects, and materials for server-side frameworks is about to do the same.
Is there any practical benefits (like security) of redirect based solution, or it's just following the trend from the giants?
This is a common implementation of Single sign-on - SSO. You basically sign in once in a dedicated server, and then you can access multiple applications which are not related without signing in again. For example, after sighing in to your google account you can access all google applications (gmail, drive, calendar ...)
I'm trying to figure out, how to use OAuth 2.0 to access Google APIs from my web app. The problem is, that the protocol require developer to register redirect_uri (URL of page receiving access token). But my application can be distributed to many customers and can be hosted on endless number of servers. There is no way to know redirect_uri beforehand.
Google offers another option for installed applications, but I cannot use this variant neither. Auth server returns access code in window title and this information cannot be accessed from javascript of our page (JS cannot access content of window opened using window.open(); if that content comes from different server).
To conclude:
Cannot use method for web applications, because I don't know all URLs where will our app run in the future.
Cannot use method for installed applications, because window title is not accessible from our JavaScript code.
Is there any recommendation, how to use Google's OAuth 2.0 from distributable web application running on a lots of servers? Thank you.
Are you sure you cannot access the window title? If your app is opening the window, it should be able to access it. It should be possible to do this in a similar way you would do it in a mobile app.
If all attempts fail, you could set up a proxy server (that has a known redirect URI) and hands out the Google tokens to all your clients. Or better each of the apps could have its own proxy server - the server it was downloaded from. But then if each OAuth client can only have one redirect URI, each app would have to be a separate OAuth client.
My company is re-writing its e-commerce site as a single page application using the new Web API / SPA features in MVC 4. We're not sure about the best way how to handle authentication.
Specific questions:
How do we handle both encrypted and non-encrypted communication? Clearly, we need to use HTTPS for the login, account, and checkout AJAX, but we'd like to use HTTP for browsing the catalog in order to avoid expensive SSL handshakes that would slow the whole site down. Is this even possible for a SPA, or are we stuck with HTTPS for everything?
What sort of authentication should we use? Primarily our site will be accessed from a web browser, so cookies may be fine. But down the road, we may want to make a custom iPhone app. Is Basic Authentication, OpenId, or OAUTH preferable? If so, why?
If we go with Forms Auth and cookies, will the redirect issue be fixed for the release of MVC 4, or do I have to use the haack?
If we go with Basic Authentication, how do you do persistent sessions, so that users don't have to log in every time they go to the page again.
Which authentication methods are well supported by ASP.NET MVC 4. It'd be ideal not to have to write a lot of specialized code.
Thanks in advance
1. How do we handle both encrypted and non-encrypted communication? Are we stuck with one protocol, https, with a spa?
You are not stuck with one protocol. With a spa you can use ajax to communicate over http or https, whichever one you choose at any given time. I would use https for anytime your are sending sensitive information like a persons name or their birthdate or login credentials.
Once a user logins to your site over https then your server can set a forms authentication cookie for that user. This cookie should be an encrypted value that ties their session to the server. You must be aware that if the rest of your site is using http then you have the risk of this cookie being passed over the wire in plain text. Even though the contents of the cookie can be encrypted, using an encryption algorithm of your choosing, a malicious person can steal this cookie and jack your user's session.
This might not be a big deal to you though if they are only allowed to browse the site and create a shopping cart. Once the user is ready to checkout then you should re-authenticate the user, over https, as a sort of double check to make sure they are not a malicious user. Amazon does this.
2. What sort of authentication should we use?
Well, that's all a matter of what features do you want your site to have.
OAuth is for exposing webservices which you can allow other sites to call with delegated access. What this means is that if you have a user who wants another site (site x) to be able to access features on your site for their profile. The site x can redirect the user to an oauth endpoint on your site which will authenticate the user. Your oauth endpoint will ask the user if its okay that certain features are shared with site x and if the user agrees a token will be generated. The user passes this token to site x where site x will make server to server calls to your site. Site x will present the token in the calls so the calls to your services will be a delegated access call. OAuth is a way of provisioning other sites to make delegated access to your services. I hope i was able to explain that clearly.. I'm not always good at this.
OpenID is not a very secure way of handling authentication its more of a convenience so that users don't have to be hassled with registering an account with your site. Because OpenID is completely open you are trusting another provider to validate your users. If the third party provider's user store is compromised then your users are compromised also. It's an example of a voucher system where you are basically saying I will trust who you say you are, if you can have an OpenID provider vouch for you.
Another solution is WS-Federation. WS-Federation is if you have multiple sites and you want to have 1 authentication provider that you trust. This authentication provider can be yours and basically all your sites say if you want access to my site then you have to first be authenticated with my authentication provider. This authentication provider can live on a seperate domain and can choose any authentication mechanism it chooses. You are trusting that this auth provider will do its best job to manage your users accounts.
WS-Federation can be overkill though if you only want authentication on your site and don't have multiple sites. In that case I would just recommend doing Forms Authentication and this should be simple enough to do. There are lots of examples of how to do this and microsoft provides many solutions for how to do this. You should look into creating a custom membership provider.
Once a user has been authenticated with your site you should create a forms authentication cookie. This cookie ties the user to their session on the server. This applies to all the scenarios listed above. MVC 4 supports all the scenarios listed above also.
Thanks, and feel free to ask more questions if I wasn't clear enough.
** EDIT 12/1/2017 **
Coming back to this question years later I have learned that relying on cookies for REST based APIs is not a good idea. You don't want to create a session on your web application because it makes your app harder to scale. So, if you need authentication then use HTTPS with some form of authentication (BASIC, DIGEST, Token Based, etc..). So, your SPA client appl will set the Authorization header on every http request and then your web server app will re-authenticate every request.
The main downside of using ASP.NET's form based security is that it assumes you're want a 401 web page when your authentication fails (useless when you're doing an AJAX call) and it's really designed around doing redirects which kind breaks the whole SPA pattern. You can hack around it but it's not designed for the purpose you're using it.
This toolkit may provide an alternative to ASP.NET'as form model.
Not yet sure how mature it is ...
http://www.fluentsecurity.net
Feedback welcome.
I just started working with webapi myself so don't consider my answer authorative. I'm not a security expert though I should be. I ran into the same questions as you did and found, as you did, that there is no authorative answer though - within mvc webapi at any rate. Looking at other webapi specs may give you some inspiration.
The simplest way I came across was of course using SSL. That let's you get away with sending credentials in clear text in the header. Doesn't break rest.
My api will employ SSL all the way but I wanted to double up anyway. So I'm sending an encrypted key in the querystring for all my requests. Pretty much the way cookieless authentication works for a non api asp site, but mvc doesn't play with it so I've rolled my own solution.
On a mobile site, the user would log in, be redirected, to the app with the encrypted key encoded into the js. So he'll initially have a cookiebased auth for the site, and be responsible for it's protection, password saving etc.
Another api consumer would get a more permanent "secret" from a dev site yet to be made and use that to check out a key.
Normally mvc authentication is stateless, meaning the ticket is never invalidated server side. If you controll the client you can just ignore invalidate cookie requests if the server logs you out, and just keep on reusing the ticket. Eventuelly you might want to keep track of your tickets server side, but it's not stateless, doubt if it's restfull, and by consequence scalability taket a hit. But authentication is pretty important so...
I've recently started working on a game project for mobiles for which I want to maintain user accounts.
Instead of writing my own user accounts layer, I thought I'd allow people to authenticate with Google/Facebook/Twitter etc. accounts. Examining the delegated authentication schemes supported by each of these providers like OAuth/OpenID, it seems like there must be a browser for logging in any of the providers. Can anyone suggest workarounds or straightforward ways to authenticate without having to open a browser.
If that's not possible, how are applications like Google Talk logging in without opening a browser?
The browser is simply speaking HTTP (over TCP). You can create an ASP.NET web service or a WCF web service which also speaks HTTP, which will follow the same sequence of HTTP actions.
I have a portal application that loads external content (widgets) via an iframe. Users login to CAS via the portal itself. There are a few portal APIs, though, that need to be called from that external content. What information do I have to pass from the portal to the widgets that the widgets can use to make these calls without being rejected by CAS?
UPDATE
The more I investigate, the more I think that my question boils down to how CAS actually does what it's supposed to do. In other words, how can I go from one site where I've authenticated to another and tell it that I've already done the authentication thing. What's the mechanism behind that and how can I employ in in a web context.
The portal scenario you describe is exactly what CAS' proxy ticketing was designed for. We use it with an iframe-based web portal system and it works fine.
The CAS proxy ticketing mechanism allows a client (your portal) to dish out service tickets to other clients (the widgets loaded in your portal's iframes). This saves your users a trip through the CAS server for each widget that their browser loads. Proxing is also useful if you're trying to use CAS for web service authentication (i.e. when one web service needs to connect to another CAS-protected web service).
Note though that for your purpose proxy ticketing isn't actually necessary. Your portal-iframe setup should work without it. But without proxy ticketing, each widget will have to go through the CAS server as it loads. At the very least this would slow down load times.
A while back I wrote a guide for setting up CAS proxy ticketing for RubyCAS-Client. The instructions are specific to the Ruby client, but they should give you a good overview of how CAS proxying works. Admittedly the implementation is a bit complicated -- mostly due to the "Proxy Granting Ticket" negotiation process:
http://rubycas-client.rubyforge.org/files/README_txt.html
(scroll down to the "How to act as a CAS proxy" section about 2/3rd down)
It looks like I may be asking CAS to do more than it's capable of doing. I've been thinking of it as an SSO engine where a given session can be passed around so that authentication only happens once. Instead, it seems that CAS is primary geared to be a centralized auth service (yes, I see the irony that this is what the acronym actually stands for). By handing authentication requests off to a central server, a single cookie can be read by that server. Stateless connections like APIs, then, cannot be validated this way.
It looks like CAS' proxy tickets may offer some hope, but I'm not ready to venture down that path just yet.