We are building an SaaS app, let's call it http://mysaasapp.com. When users sign up, they access their instance using a subdomain name http://myinstance.mysaasapp.com or a custom domain name http://instance.mycompany.com and so on.
We are looking at integrating with other services (Facebook, twitter, etc) so that our users can link to accounts on those services within their instance. Twitter is very lenient when it comes to OAuth redirect callbacks (the callback/redirect URL can be set by us when we make the OAuth request). Facebook, however, is not so leninent, the callback/redirect domain is set within the App's configuration on facebook.com
When users use a custom domain name on their instance, they can opt to make the subdomain (http://myinstance.mysaasapp.com) on our site inactive. This means we can't set the callback domain for OAuth to be mysaasapp.com and expect it to work.
The solution would be to use an OAuth proxy (http://proxy.mysaasapp.com). We have used HybridAuth previously, and we believe we should be able to easily turn it into a OAuth proxy.
Having said that:
Should we use the OAuth proxy to only proxy Auth requests? Once we get the access tokens, should we continue proxying the request through the proxy or should we just connect to the provider directly from our instance? In other words, are there any OAuth secured APIs that restrict API calls (after authentication) to certain defined domains?
How should I secure the OAuth proxy so that requests can only originate from instances of our app and responses can only go to instances of our app?
So here's what I ended up doing.
I created a very simple web app which is built around HybridAuth. This webapp would be hosted at oauth.mydomain.com.
What happens is that when the user at his own instance wants to connect to a provider such as Facebook, the app instance does a server to server connection to oauth.mydomain.com by posting the provider type and a few other information. The proxy returns a token.
We then redirect the user to oauth.mydomain.com while passing the token as a get parameter. oauth.mydomain.com invalidates the token and stores the information in the user's session.
The user then proceeds to authenticate with the provider. When this is successful, oauth.mydomain.com POSTs the consumer tokens and keys back to the instance at a special endpoint.
When posting is complete, we redirect them back to the page they were on at theirdomain.com
I have decided not to proxy all requests (only auth requests are proxied) because this is a simple method and providers (at least the ones I have looked at) only implemented domain restrictions during the auth process.
Related
I'm trying to create a simple SSO system in PHP for two domains which are thematically connected.
So I was wondering if it is possible to store a signed JWT token containing user username from domain A to the local storage. And then to verify the JWT using the same secret key from a domain B which would lead to a successfull authentication.
I've search google for some answers and I found some of them containing a middle authentication domain, which would take care of authentication. But I would like just to link the two domains I have.
Thanks.
Cross-origin data storage access from domain B to domain A is not allowed by same-origin policy
Access to data stored in the browser such as localStorage and IndexedDB are separated by origin. Each origin gets its own separate storage, and JavaScript in one origin cannot read from or write to the storage belonging to another origin.
The usual solution is to have a central domain for authentication ( could be A or B) and work with redirections among domains sending the JWT or share the authentication token across domains using an iframe. See details here
OpenId, OAuth and SAML protocol works with redirections, and for example Google web suite has their apps connected trough iframes (Additionally google is an openid-connect provider)
There's no reason why you can't do this. A JWT isn't really anything special, it's simply a token much like a session ID token. The difference between a JWT and any other token is that it can contain a payload of data.
What you're describing is essentially the password grant of OAuth 2.0. Your SSO system is the authorisation server which can authenticate users and supply them with an access token. The access token can actually be a JWT in this case too. The users (resource oners) can then use their access tokens to access resource servers (your other, related domains), those resource servers can verify that the access token is valid and allow or deny requests.
I use the following library when implementing OAuth 2.0 in PHP: https://oauth2.thephpleague.com/ - there's some good information in the docs too.
I've worked on several websites few years ago and I want to be up-to-date with "the new web" so I'm working on a website using Laravel and Lumen to practice.
I have an architecture like that:
An API using Lumen (with databases: users data, user preferences, …)
A website (without database, this part just ask to the API some data and allow the user to be connected to his account)
Currently everything in my API is public: retrieving users, deleting accounts, searching users, etc.
The problem is that I don't know how to allow situations like that:
Allow my website to execute actions calling the API (call private routes on my API)
I would like to have some routes public on my API (the easiest part, it's done actually)
I would like to allow external users to call my API if they have a valid token (Google analytics, Bugsnag like services)
I'm thinking about services like Google analytics, Bugsnag, …: this services ask the user to put a token/key in Javascript. Is it a problem if someone take the token and use it on his personal website and/or in a mobile application?
I've read about o-auth 2, is it the place to start?
Thanks!
I suggest you to try for:
Allow my website to execute actions calling the API (call private routes on my API)
JWT Authentification (JSON Web Tokens).
How do JSON Web Tokens work?
In authentication, when the user successfully logs in using his credentials, a JSON Web Token will be returned and must be saved locally (typically in local storage, but cookies can be also used), instead of the traditional approach of creating a session in the server and returning a cookie. Read more about jwt
Use this JWT-AUTH for connection jwt mechanism with lumen/laravel.
I would like to allow external users to call my API if they have a
valid token (Google analytics, Bugsnag like services)
For that task I suggest you to use OAuth 2.0 protocol
I'm building a very typical web app product. It will likely have corresponding mobile apps in the future. I'm building it from the ground up with a REST API, which is secured using OAuth2. I've got OAuth2 working, and I'm able to connect successfully using various grant types.
What I'm a little confused about is what grant types to use for the actual web app. Here's what I had in mind:
Public API access
Before a user logs into the web app, some API access is required for things like user registration and password resets. I was thinking of using the client_credientials grant type. A simple client id and secret validation in return for an access token.
However, it seems totally unnecessary to request an access to token for every single public request or even for each session. It seems to make more sense to just generate ONE access token that my web app will always use.
Yet, this seems to go against how OAuth is designed to work. For example, access tokens expire. What is the right way of doing this?
Private user API access
Next, for a user to login to the web app I was planning on using the password grant type (resource owner password credentials). This approach allows me to save the user_id with the access token—so I know which user is logged in. Further, by using scopes I can restrict access within the API.
I plan to save the access token within the PHP session. As long as the PHP session is active they will remain logged into the web app.
Is this an appropriate design for user login?
For Public API Access:
One method is to skip tokens all together and just use Basic HTTP Authentication for API access. You could accept Client Credentials for this, and limit what clients can do using client-specific scopes. Github offers HTTP Basic authentication using user credentials for all their API calls.
For Private user API Access:
This is an interesting question because it begins to breech the line between Authentication and Authorization. OAuth is used for Authorization, so logging in users becomes dicy. Session management, for example, is something not covered by the OAuth2.0 spec.
However, this is a common use of OAuth2.0 anyway. You can use the password grant type, or any other grant type for that matter, to obtain an access token. A major downside is they have to trust your application with their password (Not a big deal for your own app, but for 3rd parties not so much). Also, being logged in one place does not necessarily mean being logged in somewhere else (rather than SSO, you have "linked accounts", so the sessions are managed separately). One way around this is to ALWAYS send users to the oauth authorize endpoint, and if their session is active on the OAuth2.0 Provider side, reroute them back to the client app with an access token or authorization code. This way, if the session is active with the OAuth2.0 provider, the client can immediately log them in.
I have recently implemented the SSO functionality for a Google Apps Marketplace app we are developing. In simple words: it provides a way to retrieve the Google Apps' user's email and log him in in your website, without the need of authorization on his end. You just need the consumer key and consumer secret, provided by Google to the app during installation on your domain (the installing user also authorizes (a one time action) any other permissions you request in the Manifest file).
Now I have somehow managed to get the SSO user login working using JanRain's OpenID PHP library and adding Google Apps as provider using the PHP Extensions for Google Apps OpenID Discovery.
However, after logging in, I need to implement a functionality that will retrieve all users in a given Google Apps domain. I've already did that using oAuth2 authentication and the following Directory API. However, this requires the existense of a consumer key, consumer secret and a redirect URL (that must be registered in the Google API console).
Is there a way to remove this convenience and instead allow our users to directly be able to get their Google Apps domain's users, using the existing SSO authentication we made in the background while logging him in? Otherwise, it will be too much hassle for the user to register the app at the Google API console, enter the correct redirect URL and set it up in our website and then he will be able to get his domain's users.
Regular users cannot use the Directory API, you'll need to authenticate as an admin user to make Directory API calls.
Depending on your needs though for accessing all users, you may be able to get by with requesting access to the user's Contacts scope and grabbing a copy of the full Global Address List which contains information on all non-hidden domain users as well as non-hidden groups and shared contacts.
Twitter'll phase out HTTP basic authentication by August 2010. In the link my scenarios are from Desktop Applications. Basically my client should tweet new posts on a website.
This would be incredibly simple with HTTP basic auth, because I can store and use my account's username and password in the app to authenticate.
However, with OAUTH I can get final credentials by two means:
Callback method. You are redirected to Twitter, (login if isn't), click allow access, get redirection back to your callback URL.
PIN mode. You get a link to open, (login if isn't), click allow access, receive PIN code. Use this PIN code to authenticate your app.
Do I understand correctly that PIN codes also expire? How is it possible, given a username and password just to tweet from a client application? How can a server side script log in with the username/password and click allow access? All scenarios I could google up are for a web application to authenticate via twitter where the user is in front of the browser to walk through the redirect.
All scenarios I could google up are for a web application to authenticate via twitter where the user is in front of the browser to walk through the redirect.
The user has to be there to authorise you the first time (just as they'd have to provide you a username and password), but the resulting access token does not expire and can be reused (unless the user deauthorises your application, that is).
Store the access token - it's as good as a username/password. Better, actually - if they change their password, your access remains.
The PIN does expire under OAuth 1.0a. Using the verification code returned requires use of the temporary request token in the initial authorization request.
OAuth 2.0 defines more flows - one of which uses a direct login/password mechanism. It's up to Twitter to determine which flows they decide to implement. You can also embed a user-agent in the app.
Desktop apps suffered from a really bad user-experience with OAuth 1.0 which led to 2.0. It's doable, but painful. You can request XAuth access if you need to from Twitter as well. It's almost the same as basic auth.