Single sign-on - implementation for 3 domains - php

My company has 3 applications on 3 different domains. Next thing we would like to do is to implement a single sign-on solution, so when a user is already authenticated in one app, they don't need to authenticate again in the others.
I know about OAuth2, but I don't feel confident when it comes to fully grasping its idea. Additionally, I got the impression that OAuth2 would be an overkill in our case, because the 3 application are all ours, so they're not really "third parties" to each other - they're trusted and they're all developed by us. We also don't really need a full API approach, which would be passing an access_token with every request that requires auth-access.
I see the process simply:
User comes in. First, check if they are already authenticated on one of the 3 domains.
If the user is not authenticated yet, redirect them to login
page and employ the successful login attempt to "mark" the user as
authenticated across all 3 platforms.
If the user is already authenticated on one of the 3 platforms,
simply provide the requested resource without the need to log in.
I could put a big "HOW?" after the first two points, so... How would we go about it to achieve just what we need?
I've been looking for examples online. Most of them deal with the one scenario of first page visit, in which the user is asked to log in, so the application can get an access_token to communicate on behalf of the user. That's cool, but I'm really interested in is the case that comes later, when the same user visits another affiliated domain.
I understand this is a theoretical "how-to" problem, but still I would be very grateful for any suggestions or resources that could shed some light on the kind of implementation we could (or should) use.

We started using Central Authentication Service at my company to great success. See this for a great sequence diagram for SSO in CAS. CAS supports several protocols OOTB including SAML and OAuth2, and also supports several user databases OOTB. We're using LDAP to store and authenticate users.
To answer your question, after login with the SSO provider, your client gets a cookie with a "ticket-granting ticket" (TGT). When they try to access any secure resource, they're redirected to the login page again, but if they already have that TGT, the SSO provider immediately redirects back to the secure resource with a "service ticket" (ST) in a query parameter. The ST is used by the server to validate that the user is authenticated with CAS, and it can even get attributes about the user (things like roles, name, phone number, etc.). The server then should start a session with the client so that that redirect handshake only happens the first time the client tries to access the secure resource.
CAS has a PHP client.

Related

Creating a Multi Tenancy / Saas and having trouble desiging the database for users

I'm building an SAAS with a single database. Tenant in this case is called site.
I want to achieve what Stackexchange does where it has a global login as well as a stackoverflow/softwareengineering/etc login. I'm not sure how to store users. A user can have many sites and sites can have many users. The problem with designing a JoinTable is that the user roles are stored in the User table (im using Symfony3.4). I want separate roles per site/tenant.
Another problem I'm trying to figure out is how to go about logging in. I'm using oAuth2 and to login in I sinply call {{url}}/oauth/v2/token?grant_type=password&client_id=client_id&client_secret=client_secret&username=admin&password=pass. How should I make the user log in to a specific tenant/site? Do I add site_id to the query parameters?
Thanks for reading.
This question is very broad, so I'll take a stab at it.
If you are building out a network of sites, each site would ideally have it's own database. This will ensure sandboxing and the ability to easily migrate a site to it's own infrastructure if needed due to scaling or security concerns.
When dealing with user authentication, it sounds like you'll want a single secure user store that acts as the oauth2 server and each of the sites act as a Oauth client. You'll want to use the Authorization Code flow grant type in OAuth.
Essentially, a user visits Site A. Site A sees they are not logged in via the site's session. It redirects to your OAuth server which shows a login (think of the google login). Since Site A also passed in a callback url, once you've signed in, the OAuth server knows where to redirect the user, along with the valid token information. Then Site A takes that token and exchanges it for an access token on the server-side so now you've got authentication data on Site A.
If you are going to implement your own OAuth handshaking, you should utilize an existing server/client library. For PHP, you can look at the League OAuth server library, or use Laravel Passport, if you're using Laravel. There are other similar packages for other frameworks out there.

Integrating SSO across differents Domains using WebService?

i have 3 différents domains domain-a.com and domain-b.com also domaine-c.com
and i want to use SSO, if you log in to one of these domains you have access to all other domains.
1 - using cookies is impossible because we can't share the same cookie with differents domains
2 - i'm thinking about using webservice, but i'm not good in that so i'm wondering if it's a good solution
If you have any suggestion or recommandation or any thing Please i need you.
You can't share cookies but you don't need to.
Let's say your SSO runs on sso.domain.com
You want to log in on a.domain.com:
Make an XMLHTTPRequest request to sso.domain.com to check if you have a session.
If you have a session and are logged in you get a login token back.
You pass the token to application A with an XMLHTTPRequest. It sends a request to sso.domain.com to verify the token and get the user credentials.
You are now logged in on a.domain.com
This setup requires Cross-Site-Resource-Sharing to be enabled on the sso domain. The CORS implementation allows you to do the login process under water, no redirect is required.
Your an indepth look at CORS see: http://fritsvancampen.wordpress.com/2013/02/03/cross-site-origin-requests-aka-cross-origin-resource-sharing/
I use SimpleSAMLPHP.. (https://simplesamlphp.org/)
This allows me to make a single place I can ask if users a logged in. The whole thing uses SAML2 which is a secure markup language(http://en.wikipedia.org/wiki/SAML_2.0).
It can be a steep learning curve to make it work but its very safe and everything is encrypted using certificates. The nice thing is that you can use all the IDP's(identity providers) you can think of. This means you can implement facebook, google etc. log-in's as well as custom log-in's.
Another great thing is that it provides SLO(single logout) as well. This will trigger log-out's in all the applications that are currently logged on..

Reusing OAuth Access Tokens

On my site, I intend to offer users the ability to authenticate via OAuth. I don’t want to ask them to first register with me and then connect an external account; I want to offer single sign on.
I believe we’re supposed to reuse Access Tokens; certainly within sessions and even between them.
Google goes so far as to say they’ll limit the number of access tokens to 10 per user per application. (Apparently Google still supports OAuth1, but recommends Auth2 now) 10 is a pretty small number.
Using cookies (like this) seems like a good plan for identifying a user between sessions, but I’m having trouble with the scenario where a user has deleted cookies or connects from a new machine.
How do I know who the user is before I’ve requested another Access Token for them? Request tokens do not contain the userid, right?
Thanks
You will have to maintain your own user accounts anyway, no matter which protocol and which provider you choose. A token (or a URL in the case of OpenID) that you get from a provider is unique for a given user and you are supposed to associate it with your internal user account and recognize user by it.
If you don't want to provide any registration UI it's okay: just get the token, retrieve all the user info you need from the provider and store all this somewhere in your database. You will also have to issue and recognize your own cookie for your users, or else they'll be forced to go through provider auth every time they visit your site.

One-time login tokens for third-party access to a resource

We have a website (foo.com) that does online training. A user logs in, then completes their training.
We've agreed to allow another company (bar.com) to send their clients through our training. One of the requirements is that their users should not need to create a separate login account on our site.
Here is my initial plan of attack:
When a user logs into bar.com (the other company's website), their backend will make a secure HTTPS request to foo.com (our website) requesting a one-time access token specifically for that user. For example, they may request the following URL:
https://foo.com/api/request_token.php?user=bob&pass=A1B2C3D4E5F6
This requests access to bob's account. The 'pass' component is a shared passkey known by foo.com and bar.com that is used to verify that the request is legitimate.
foo.com will respond with a one-time access token (for example, 0123456789ABCDEFG) which is stored into a database along with the user's id (bob).
bar.com will present a hyperlink to the user that links back to the online training at foo.com. Something like this:
https://foo.com/api/login.php?user=bob&token=0123456789ABCDEFG
When the user clicks on the link, foo.com checks the token in the database and (if it has not expired) removes it from the table of valid tokens and creates a session variable indicating that bob is now logged in, then redirects him to the training.
What I'd like to know is, where are the security holes and how can I mitigate them? I know that the URL will be encrypted, and I know that an entry will show up in my server log, but it's a one-time token, so I'm not worried about that. I can imagine someone brute-forcing different tokens, so I've included the user name in the second login url that the user clicks on so that the token will only work with that specific account.
But what I'm really worried about is what I don't know. And I don't understand much about the security issues here.
(Please note that this only covers an existing user who is attempting to log in. I will use another method to actually create the user account on foo.com)
I am coding in PHP.
What you're looking for is known as single-sign-on (SSO). There are a number of different industry-standard protocols for achieving this, but what you're basically doing is having another entity authenticate the user and provide that information to you in a way that you can verify that something you trust (their authentication system, whatever it is) has issued it.
The most standard way of doing this is SAML (Security Assertion Markup Language). This is a protocol where the third-party would authenticate to their system and it would generate a SAML Assertion that basically says who the user is (and other information, should that be required). The assertion is digitally signed so you can verify who issued it. This requires that you and the third-party exchange keys (in the form of certificates) and come to an understanding about what your assertions will contain, etc (typically expressed in SAML metadata that is exchanged between the Identity Provider and the Service Provider).
There are a number of SAML implementations/references out there for many platforms, including PHP. If you want to do this right, and securely, that is what you should investigate and pursue.

OpenSocial authentication from external application

I'm working on a web project that isn't all that dissimilar in principal to power.com, where I am attempting to unify several different social networking sites under a single website, allowing users to register once with the system, and then add as many of their individual social networking accounts (Facebook, MySpace, Orkut, etc) as the system is built to handle, allowing them to browse their respective profile information in a single place.
Simply put, I can't seem to find a way to authenticate arbitrary users into their social network accounts.
I've been poring over the OpenSocial specifications, as well as the OpenSocial PHP client project, but I seem to be missing something, as everything is appearing to be circularly dependent.
My first problem is that, for testing purposes, I have a MySpace consumer key and consumer secret, but whenever I attempt to perform a 3-legged authentication with MySpace, there's no option for logging in as someone else. Plus, it performs an external redirect, which is somewhat undesirable (as a user of this eventual social networking "portal", I'd rather not have to go through that redirection process every time I add a new account).
How would I programmatically authenticate an arbitrary user and allow them access to their account information (preferably without the external redirection)?
Second, the 2-legged authentication requires a userId (usually an arbitrary integer) that identifies the arbitrary user to retrieve information for. However, when I enter my MySpace OpenSocial ID, along with the given consumer key and consumer secret, I am given a 401 Access Denied error. Furthermore, in order to use this ID in the future, it seems that I would need to authenticate the user first...but that authentication appears to require the ID.
I'm pretty convinced that I'm missing something trivial, but for the life of me can't figure out what it is. Help is greatly appreciated!
Technically this isn't my answer, but the developers at OpenSocial have provided me with the following information regarding my question (emphasis mine):
3-legged OAuth is built around the
redirect back to the site you're
authenticating with, and there's no
way to avoid it. It's not the most
convenient experience, but allows
users to share their data with your
website while keeping their passwords
private. Any design which requires
users to enter their MySpace password
into a form on your website is
considered an anti-pattern and should
be avoided. You could potentially
attempt the redirect in a popup window
in order to make the experience a bit
less jarring for the user (currently
the PHP client doesn't make this that
easy, but if you followed up at
opensocial-client-libraries#googlegroups.com
someone could help you work through
that process).
With regard to not being able to
change the user, what I believe
MySpace is doing in your case is
checking for a MySpace cookie and
pre-populating your account
information. If you were a user
visiting the site and not logged into
MySpace, you should get a full
username/login box combination. There
should also be a button or link
somewhere to say "I'm not this user"
and log in with other credentials.
As for 2-legged, you would need to
have the application associated with
the consumer key/secret installed on
the profile of any user whose data you
wish to access. 2-legged is mostly
intended for developers who are
currently running a social gadget on a
container and wish to access social
data for their application users out
of band with a gadget render. In this
case, the application server would
already have the user's OpenSocial ID
(from a signed makeRequest) and the
user would already have the app
installed on their MySpace profile).
Most of this is covered
in http://wiki.opensocial.org/index.php?title=OAuth_Use_Casesif
you want more information.
Essentially, this makes any use of 2-legged authentication on an external application impossible; 2-legged was explicitly designed not to be used in this sort of situation. Furthermore, it seems that power.com is indeed employing the anti-pattern of having users supply their actual Orkut/MySpace/etc credentials, so that explains that bit.
Clearing out my cookies worked to authenticate me through MySpace. However, I followed up with another question about how Orkut authentication would work, since it doesn't seem to support 3-legged auth. Here was the response I received:
Orkut is interested in supporting
this, so you'll be able to allow users
to share their information with your
application "correctly" in the future.
The corresponding two-legged app would
need to forward the current viewer's
OpenSocial ID back to your server,
probably along with an authorization
token you generate yourself so that
you can link a user's session on orkut
with a session on your own server.
Honestly, it's probably not usable
enough to support a standalone login
system.
Essentially, no, Orkut really can't be hooked into an external app (at least, not yet) without resorting to the anti-pattern.
If anyone has any further information on this topic, please feel free to share!
The pattern is also mentioned here http://sites.google.com/site/oauthgoog/2leggedoauth/2opensocialrestapi
Essentially a lot of the mashups would want this feature :
A 3rd party site which DOES NOT have a
gadget wants to get the end-users
permission to access their data at the
social network, for example to
download their friend list, or to get
permission to post to their activity
stream

Categories