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
Related
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.
I'm currently working on a project, where the developer before me implemented the login into an intern tool via google Oauth 2.0
He does that, by just grabbing the user domain, after authenticating with google and checks if it is "ourCompany.com".
If yes, he renders the page, if not, he redirects the user to the login.
(So basically he does one oauth request per page view.)
I'm pretty new to Oauth 2.0 but as far as I understand it, this is not, how it should be used?
He wants to use Oauth, because his idea is to organize all our employees over google groups/organizations and thus have a central place to give and take permissions. (Which I have to implement now.)
He said I should "just also get the groups on each request" and that's it.
(Which I tried btw. as a "quick win" but couldn't manage to get them from google yet, not sure If it is even intended)
My understanding of how this should work is the following:
The user is redirected to the google Oauth 2.0 service with a scope to get his groups/organizations.
We get back an access Token, which I then would use to ask the google API for the users groups/organizations.
Based on these informations I would then set the users rights in our application itself. (For example The user is in a google group "author", then I would give him the author role in our application)
The user then gets logged in via a "normal" PHP session, which takes over for the rest of the application, instead of always asking the Oauth service.
Does this approach make sense or is my colleague right with his implementation? The only benefits I see in his solution is, that we get "real time" information, if the user still is in a group or not.
But from what I've read about Oauth 2.0 so far, his implementation does not feel right for me, on the other hand I don't feel secure enough at this topic to say it's wrong.
So any explanations/opinions would be very welcome.
Additional informations about the project:
We use Laravel 5.4
I thought about using the "socialite" plugin (https://github.com/laravel/socialite) and for permissions (https://github.com/spatie/laravel-permission)
If the intended user groups in your application are the same as the Google groups configured for your domain, then I think it's OK to use the Google domain groups. If not, you could use new groups (possibly with some prefix like myApp-group1), but you could end up with many groups if multiple applications does it.
There is also a question who can modify the Google domain groups. Is it the same person/role who would have the right to modify permissions in your application?
I would consider creating a separate access management for the application if:
There is a chance of people outside of your company using the application.
You needed to modify existing Google groups (if there are some) just to make them fit your application.
It looks like you can read user's groups by Google Directory API with an access token containing scope https://www.googleapis.com/auth/admin.directory.group.member.readonly. But I have no experience with it.
I think it's common to use LDAP (or MS Active Directory) as an access management for in-company applications, so the idea of using Google groups is not strange.
The auth sequence you described looks correct.
I'm using several social providers on my site, including Google. I would like to ask for password to Google account each time user requests one of my actions. This is for security reasons.
With Facebook, we can send auth_type=reauthenticate parameter. Is there something like this in Google API?
I'm not looking for refreshing tokens, I need to make sure user types his password at any state: whether already authenticated or not.
I read your posts and I can relate to your frustration on this matter (including some of poor responses inline above).
You want to be able to prompt users to reauthenticate with Google in order to prove that the user behind the computer is indeed the account holder. Having required similar functionality myself, I've concluded that they do not implement it. This creates a problem of trust for an application that relies on a Google login for access, but also provides some destructive functionality which should require a reaffirmation of the identity of the user. Wish I had better news for you.
Having implemented this feature with Facebook's API, I was certain Google would provide similar since it's so essential to security, however they don't.
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.
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.