i would like to provide a third party user authentication on my app engine app.
the federated login option on appengine is not exactly what I'm looking for and i can't see endpoints
what i want is authenticating users via openid like its done here on stackoverflow.
the first time a user has to authorize the app and the subsequent times it will only need to be logged in or log in again on the third party app and then redirected to my app.
my app is written in python and im using tornado web as a framework. i've seen that tornado has its own auth module i want to check out but i wanted to ask for suggestions before jumping into code.
basically i would like users to be able to log in via facebook, twitter and google.
the facebook authentication seems not to be that hard on graph.facebook.com but its not easy to test
authenticating via twitter looks more difficult to me and i can't find any clear examples.
i would love to hear your experiences/suggestions about it.
What you describe is exactly how federated login with OpenId works on App Engine. Whether or not users get prompted for authorization after the first login is up to the OpenId provider, not the consumer.
Facebook login doesn't use OpenID, and you'd need to implement that yourself, in conjunction with a sessions library to keep track of logged in Facebook users.
Related
This is in relation to my other question about the need to create a Facebook app.
I've been reading a lot about how to best approach login for mobile apps users (iOS and Android) that access my web service running on Google App Engine. I'm still not clear how to best do it as I would like to offer login with both Google and Facebook. The app and the web service does nothing with Facebook or Google other than I would like to piggyback on their login.
Having only login with Google for GAE is very easy and the same goes for using OpenIDConnect. Facebook unfortunately does not support this.
Reading an old question here on SO where someone wanted to do the same as I it looks like the app should do Facebook Login and then get a token that it passes to my backend which needs to be validated by contacting Facebook. Is this how to do it today?
I also found Google Identity Toolkit, which seem to be what I need. However, I do not have a website or just apps. I would need to have the apps do the Facebook login and somehow provide my web service with something so it can validate the login info.
Later on an app user should be able to log in using randomly Facebook, Google and my custom username/password. The app and the web service should know the user is logged in and authorize it to access the REST API.
How do I accomplish this? BTW, I'm using Go on GAE.
I would really appreciate if someone could explain if there are several options how to do this, pros and cons, and provide an overview of the best approach and what needs to be done.
Many thanks for any help with this!
UPDATE
OK, thanks a lot everyone for the help and pointers. I have successfully run the quickstart sample app for iOS for my GAE backend. Basically, created a Facebook app and permissions credentials on my web service on GAE so that the sample iOS app can log in.
A bit of a gap still before I have an authenticated user in the datastore and can authorize successive API calls.
Main open questions at this point:
how to get the gtoken in the iOS app after successful Facebook or Google login?
should I explicitly call an API on my web service to pass in the gtoken or is this somehow automatic with Gitkit API enabled?
Thanks for any help!
UPDATE
To answer #1 and #2 myself, there's a "successful sign-in url" that can be given in the app engine config so the app knows where to call with the gtoken. Then after that it's like explained in the answers.
Looks like you have an app and a backend on GAE.
If you are using google identity toolkit, it will allow you to signin with Facebook, Google, and email/password.
When user successfully signs in to your app using identity toolkit, your server should receive a gtoken. You have two options here:
Pass the gtoken to your app and save it there. When your app makes API calls to your backend, you app should attach the gtoken to every request. Your backend should verify the gtoken(https://developers.google.com/identity/toolkit/web/required-endpoints) for every API that needs authorization.
Verify the gtoken, generate a token that your backend can recognize/identify the user. Then pass the token to your app and everything else is the same as option 1.
If you do not want to use identity toolkit, you can implement facebook login on your app/backend and use facebook token to communicate between your app and backend.
Whatever your decision is, apps that use your API should pass you something that your backend can recognize/authorize the user.
The answer is about using Google Identity Toolkit (GIT). GIT itself is an identity provider, which would be integrated with your apps and backend. The flow works along these lines:
your app requests login via its GIT API
GIT will perform the federated login with Facebook or other 3rd party provider (transparent to your app) and returns a GIT token to the app (representing a unique user from your end-to-end system perspective, i.e. apps plus backend)
the app makes a request to the backend in which it passes the GIT token
the backend verifies the GIT token validity (using this go GIT client API, for example) and from it can extract the identity of the user and thus validate the request
You can find more detailed info about the backend token validation in the backent endpoint doc, look for these sections in particular:
Understanding the Identity Toolkit cookie/token
Getting information for users
Now the actual token validation on the backend may take a few seconds, so it might not be practical to do it for each and every REST request from the app. If so you'd need to somehow:
save the info that the user of that specific app instance is
authenticated in something like a "session" managed between your app and the backend
map a specific REST request received by the backend to a specific such authenticated "session"
But I'm not sure how exactly is this "session" functionality done in the apps+backend context, I didn't write any apps yet.
In my new web application, I want to authenticate users by letting them sign in with their Google, Yahoo, Facebook, or LinkedIn accounts. Does App Engine's "Google+ Sign-In" capability allow this? If not, is there another platform (e.g. Heroku) that would let me write straightforward code that will accomplish this?
BACKGROUND: I can find nothing in the Google+ Sign-In documentation that talks about authenticating with any site other than Google.
However, various pages (this one and this one) show a Google+ Sign-In screen that also has a "Sign In With Facebook" button in screenshots, but it's not clear if this Facebook button is supported by App Engine's Google+ Sign-In API, or was hand-rolled with OAuth2. Same with the "Sign In With Twitter" button.
I believe that, even if OpenID Connect were available, neither Facebook nor Twitter would participate -- except that OpenID Connect is built on OAuth2, which would allow them to participate. However, App Engine has deprecated OAuth2 (see this page). So I am pretty confused about what is possible and what is not.
To support multiple authentication services (e.g. Google, Twitter, FB..) you should go with OAuth2.
One such library that works with GAE (for Java) is pac4j. It lets you authenticate and access users profiles.
I am trying to get the user who is logged in via. SAML Single Sign On.
I have already implemented SAML Single Sign On and it works.
The code I use for programmatic login is :
apps = gdata.apps.service.AppsService(email=username, domain=domain, password=password)
apps.ProgrammaticLogin()
logging.info("current user %s", users.get_current_user())
//Redirect to a Google mail page.
But users.get_current_user() returns None always even though correct username and password is provided. I have crosschecked it by redirecting the page to Google Mail page and it successfully redirects.
I have googled this issue for hours now nothing goes the right way.
Can anyone please guide me what I am doing wrong ?
There are three different things going on here, I just want to make sure are clear for my suggested answer to make sense:
Google App Engine users service: You, as the developer, delegate authentication and authorization responsibility to Google Accounts (or the selected OpenID provider). Google will act as the Identity Provider and you'll act as the Service Provider.
SAML single sign on: Google delegates to you the authentication and authorization responsibility, you'll act as the Identity Provider and Google will act as the Service Provider. You'll be using SAML SSO every time you try to login any Google service using you Google Apps account, that includes Google App Engine applications using the users service.
ClientLogin: It is one of the methods for authenticating to use a Google API by giving username and password. It's deprecated, it's hard to maintain and insecure since you are hard coding the credentials and the app could have access to everything. I'd recommend switching to OAuth instead. In the first two lines of code You are initializing the Google Apps provisioning API with gdata.apps.service.AppsService, if you are not going to retrieve or create users/groups/alias is useless to do that. If you are I'd also recommend switching to the Directory API part of the new AdminSDK
For your particular case I'd suggest checking if there is a current user logged in, if not redirect to the login URL using the GAE users service.
user = users.get_current_user()
if user:
logging.info("current user %s", user.email())
else:
return redirect(users.create_login_url(request.url))
In case you always require that the user is logged in you better set the handler as login: required
The user will be redirected to the SAML SSO page to log in to his Google Account in order to access the GAE app.
I'm coding a Python - Google App Engine application. There are 2 important things this app must do:
Write in user's calendar.
Write in user's profile (working with users in a Google Apps domain)
First operation is easy. If I understood OAuth, this is the classical 3-legged scenario. The scenario for which OAuth was originally developed. The logged user provides credentials to the client (my app) to access the user's data (calendar) on his/her behalf. So, this can be done just with the logged user's credentials.
Second operation is not so easy. It can't be done with just the logged user's credentials. This is a 2-legged OAuth scenario. So, I need to delegate in a Google Apps domain admin's account to access the users's profiles using Google Profiles API (via google data library). So far, I hardcode admin user/password in a json file, and my app loads that file. But that sounds kind of dirty for me.
At the end, my app needs to handle the classical 3-legged OAuth scenario (no problem, just need the logged user's credentials) plus a 2-legged OAuth scenario (need administrator credentials).
Is there any official or more elegant way to handle both scenarios in Google App Engine, working with Google Apps domain, that hardcoding admin credentials?
Many thanks in advance
AFAIK there is no way to authorize a write operation to Google Contacts Data API using 2-legged OAuth.
Google's documentation specifies which APIs are accessible via 2-legged OAuth, but it seems that someone at Google's forgot to specify that some of them are read-only :-S
Some people had the same problem here and here.
I look forward someone at Google to fix this. Until then, harcoding admin-level credentials is the only option I know that it works. I don't like it at all: it's dirty but effective. If someone knows a more elegant zen-level way, please illuminate us!
Having just implemented this, I have a pretty basic question about how authentication and oauth work together. I have a sample web app client (ckclient) that accesses a REST API (commitapi) for managing their commitments. This follows the model of having an app like LinkedIn displaying a user's Tweets (via Twitter) as described in: http://www.slideshare.net/coldfumonkeh/oauth-demystified-hopefully
In my simple app, a user goes to the web app client and asks to see their commitments. I am using Restlet and the user is redirected to a page where they can choose their OpenId provider and login. They are they redirected to a page where they can approve access to their commitment resources. Everything works fine.
But, the web app client doesn't know who the user is! All the authentication is done with the REST API, not with the web app client.
So my first question is... is this a bug or a feature?
My guess at the answer is that this is a "feature" - that is the way Oauth works - you don't WANT the web app client to know the userid/email address stored with the resource server (commitkeeper in my case, Twitter in the slideshare above).
If that is correct, then if I want the web app client to know who the user is, the web app client should provide user authentication. Since I am using Google's UserService on the server side, I also implemented UserService based authentication on the web app client. And now, if the user also does the web app client authentication, then the web app client has the identity of the user. So that is all good.
Combining these two also works - but I can't quite understand why.
On the web app, I login through Google's userService (technically with a GaeAuthenticator, that only uses Google accounts). Now the web app knows who I am and can display my email address.
From the web app, I ask the server for my commitments. The server responds by giving me the login page where I can pick my OpenId provider.
2a. If I pick Google, the UserService seems to know that I have already logged in through the web app and shows me my commitments.
2b. If I pick Yahoo (or something else), I have to authenticate with Yahoo and then I am shown the commitments for that Yahoo user.
This all seems fine to me - except for how does the UserService know that I already logged in? The webclient is at x.appspot.com and the server is at y.appspot.com. Is the answer as simple as the UserService is integrated across all of appspot.com?
In any case, thanks to anyone who can answer these two questions - or just confirm that I am on the right path.
(Note: I am using Google's UserService to create the login urls, my web app client and resource server are on appspot, using Federated Authentication, and all this is Java).
Well, the answer to the first part of the question is "feature" - getting resources from a ResourceServer via OAuth is not supposed to expose any user related information to the web app client.
I will pose a more specific question regarding how the UserService does its magic.