How to use 2 legged oauth on Google Admin Directory API - google-api

I am trying to write code to get all user accounts in our Google Apps domain using Google Admin Directory API with 2 Legged OAuth. Unfortunately, I can hardly find any documents or sample code for directory API. I tried the code below:
AdminService adminService = new AdminService();
Google.Apis.Authentication.OAuth2LeggedAuthenticator authenticator= new Google.Apis.Authentication.OAuth2LeggedAuthenticator(mydomainName, domainConsumerSecret, adminId, mydomainName);
UsersResource usrRes = new UsersResource(adminService, authenticator);
UsersResource.ListRequest listReq = usrRes.List();
Google.Apis.Admin.directory_v1.Data.Users allUsers = listReq .Fetch();
foreach (Google.Apis.Admin.directory_v1.Data.User usr in allUsers.UsersValue)
{ ... }
But I got the 401 unauthorized error.
Then I tried the low level way using the old GData Lib.
Google.GData.Client.OAuth2LeggedAuthenticator authenticator = new OAuth2LeggedAuthenticator("MyAPP", mydomainName, domainConsumerSecret,adminId, mydomainName, "HMAC-SHA1");
HttpWebRequest request = authenticator.CreateHttpWebRequest("GET", new Uri("https://www.googleapis.com/admin/directory/v1/users?domain=mydomain.com"));
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
the above code got the same 401 error.
Based on the source code of Directory API, I think 2LO is supported. However, I just cannot make it work. Anyone can help to point out my problem? Thanks.
Another question: Is the userid (xoauth_requestor_id parameter) necessary for 2LO directory API request? I know this parameter is required for other APIs when using 2LO, but not clear if it is required for the Directory and Provisioning API.
BTW: I would like to construct the 2LO HTTP requests from scratch without using any lib, but I haven't started this yet. I need to make sure that 2LO works on the Directory API requests.

If anyone else stumbles across this, Google deprecated the Provisioning API about a month before the original post. I recently had the same problem when trying to authorize API access to my Google Apps domain using the Admin Directory API. After finally figuring it out, I decided to document it, and I'm actually in the midst of putting together a series on how to make some sense out of Google Apps Directory API and OAuth 2.0... Keep in mind that Google now strongly encourages the use of OAuth 2.0, so 2LO is a thing of the past, and the above "fix" may no longer be relevant.
In case folks don't want to click the link, I would recommend using Google's API Explorer to find out how a successful POST/GET request is formulated using specific APIs. This saved me heaps of time. Also, be forewarned, if you're trying to use the directory.users.list API and have thousands of accounts in the domain, it will take a very long time to retrieve the users. I would suggest starting with the directory.users.get API to retrieve a specific user and check out what a successful API request/response looks like.

Related

Yahoo OAuth 2.0 `bearer_token_not_over_ssl` - explain?

I'm using the OAuth 2.0 spec for retrieving fantasy football data in the same way this site is using it: http://yfantasysandbox.herokuapp.com/resource/user/game_teams (github repo: https://github.com/whatadewitt/yfsapi)
After retrieving my access_token and refresh_token, I'm trying retrieve the user teams resource and getting this 401 error for no apparent reason
{
"lang": "en-US",
"description": "Please provide valid credentials. OAuth oauth_problem=\"bearer_token_not_over_ssl\", realm=\"yahooapis.com\""
}
It had been working for a few days and it all stopped working suddenly without me having changed anything. Please let me know if the spec has changed. I'm using the https protocol for each of my API requests and am sure to get new access_tokens if needed. My callbackUrl is also using https if that helps.
Its working perfectly now. Looks like it was a disruption in service with the API and not anything fundamental. Good luck this season!
Another possible explanation is that the urls you are passing are http, not https. I was getting this issue, too, until I updated all of my requests to use https.

Google Authentication using django-rest-framework and python-social-auth

Question in short: Login with DRF, python-social-auth and Angularjs works with Facebook but not Google.
I'm building a django app that needs to enable users to signup/login via Facebook and Google in addition to locally stored email/password combo. It works as follows:
For both signup and login, Angularjs initiates FB and google apis (FB.init and gapi.auth2.init) with their respective app_ids. All js libraries required for this are included in the pages.
Based on user's selection, both pages let user to log in using Facebook or google or let them enter their email/password combo.
All required info including their access_token is collected via FB or Google's API.
When user submits the form after filling up all relevant details (signup requires them to enter some additional data), the data including the access_token is sent to the server by an AJAX request.
At the server side, class based views, LoginView and SignUpView, accepts the requests and processes them. Email-based signup/login is directly handled by the code. Google/FB based signup/login is passed to python-social-auth's do_auth function for authentication.
When provider chosen is facebook, this works fine. When, it's Google (Tried both google-oauth2 and google-plus), do_auth eventually raises a 403 Forbidden error. When the related url, https://googleapis.com/plus/v1/people/me?access_token=ACCESS_TOKEN&alt=json is copied to the browser, it shows an error message:
Daily Limit for Unauthenticated Use Exceeded. Continued use requires
signup
I've made sure of the following things:
Enabled Google+ API in the google developer console for the corresponding app
From the google developer console, added http://localhost:5001 to javascript origin field and http://localhost:5001/social/complete to redirect uri field (Latter field is filled up later. Same result with or without it.)
Generated key and copied client_id and client_secret to settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY and settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET. Double checked their accuracy.
Added 'social.backends.google.GoogleOAuth2' to settings.AUTHENTICATION_BACKENDS. Tried placing here both GoogleOAuth2 and GooglePlus together and separately.
Tried all these in 2-3 with PLUS also, instead of OAUTH2. Still the same result.
Tried again after setting, settings.SOCIAL_AUTH_USE_DEPRECATED_API as True. This also fails but the error is now 401.
What to do next to get this working with Google authentication too? Gone through many other similar questions here and issues reported in Github.
Here's the relevant code:
class SignUpView(CreateAPIView):
def create(self, request, *args, **kwargs):
provider = request.data['provider']
strategy = load_strategy(request)
backend = load_backend(strategy=strategy, name=provider, redirect_uri=None)
token = request.data['access_token']
try:
user = backend.do_auth(token, user=None, **data)
except AuthAlreadyAssociated:
pass
I've recently struggled with similar problem, but my situation was a little bit different because I'm using django-rest-framework-social-oauth2.
First of all I've noticed you enabled Google+ API, but:
Added 'social.backends.google.GoogleOAuth2' to settings.AUTHENTICATION_BACKENDS.
Try change your settings to (this is described in python social auth docs) :
AUTHENTICATION_BACKENDS = (
...
'social_core.backends.google.GooglePlusAuth',
)
SOCIAL_AUTH_GOOGLE_PLUS_KEY = '...'
SOCIAL_AUTH_GOOGLE_PLUS_SECRET = '...'
Another thing that can be useful for you is google oauth playground

Correct way to use a Google Apps Marketplace service account to connect to Gmail IMAP and other services

One of the features of our Marketplace app makes use of accessing the user's Gmail account via IMAP. We are using the google-api-java-client and google-oauth-java-client libraries and code similar to this example in the java-gmail-imap project as follows:
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_ID)
.setServiceAccountScopes(Arrays.asList(GMAIL_SCOPE))
.setServiceAccountPrivateKey(PRIVATE_KEY)
.setServiceAccountUser(emailAddress)
.build();
credential.refreshToken();
We are then using code based on the examples at https://code.google.com/p/google-mail-oauth2-tools to make the IMAP connection e.g.
IMAPStore imapStore = OAuth2Authenticator.connectToImap("imap.googlemail.com",
993, emailAddress, credential.getAccessToken(), false);
The majority of the time this appears to work correctly, however we are seeing that for a small but significant number of requests the call to Google made by refreshToken() fails with an HTTP 500 error and an HTML response where the JSON would normally be returned e.g.
<p class="large"><b>500.</b> <ins>That's an error.</ins></p>
<p class="large">The server could not process your request.
<ins>That's all we know.</ins></p>
We were advised by a developer advocate at Google that we refresh tokens are not supported for service accounts and we should be using an approach like in this example.
However, it seems like without the call to refreshToken then accessToken is not populated on the credential object and then this results in a NullPointerException when we call OAuth2Authenticator.connectToImap
From the source for GoogleCredential it did seem like executeRefreshToken() is overridden to handle service accounts i.e. instead of performing a refresh it simply requests a new token, and then this bit of code in Credential then handles populating the access token:
TokenResponse tokenResponse = executeRefreshToken();
if (tokenResponse != null) {
setFromTokenResponse(tokenResponse); ....
We were unsure whether we need to enclose our call to refreshToken() in a retry loop to work around the intermittent 500 errors or whether we need to make other changes to our code to follow the recommended approach for this scenario.
Can anyone advise?
I use the java-gmail-imap example code in production (but it is only used to display an inbox in our University portal, there isn't much interaction that would require me to reuse the same refresh token for instance).
Depending on your usage, I wonder if in your case some kind of throttling is coming into play (I've read in places that Gmail can occasionally throttle access).
Elsewhere I've seen Google APIs talk about making retries using an exponential backoff algorithm.
You have to be a little careful when comparing the usage of OAuth 2.0 with the other Google Service APIs and Gmail. Gmail is special in that it uses XOAUTH2. That said I've seen other Google API's that appear to need the refreshToken call. The documentation is a bit unclear and says things like "Refresh the access token, if necessary" (as you say it doesn't seem to work without this step but I haven't done any experimentation with re-using refresh tokens via credential.setRefreshToken(String refreshToken)).
I'd be interested to hear how you get on.

Spring Social .NET OAuth confusion

I had originally posted a question about what API to use in regards to making a SharePoint 2010 timer job able to access the twitter API and chose the Spring Social .NET api and have run into another roadblock.
I cannot get the OAuth handshake or 'dance' to work.
I have the consumer key and secret linked to my account, as well as an access token and secret, but any time I try to initialize a TwitterServiceProvider object, any time I attempt to query I get a 401 error.
The console/mvc and wp7.1 examples provided dont give much insight how I can get this code (which should run with no human involvement) to work.
Does anyone have any good resources regarding this?
Thanks in advance
If you already have access token value and secret, you can do something like that:
ITwitter twitter = new TwitterTemplate("consumerKey", "consumerSecret", "accessTokenValue", "accessTokenSecret");
// twitterApi.UserOperations.GetUserProfile();
that is equivalent to :
TwitterServiceProvider serviceProvider = new TwitterServiceProvider("consumerKey", "consumerSecret");
ITwitter twitterApi = serviceProvider.GetApi("accessTokenValue", "accessTokenSecret");
// twitterApi.UserOperations.GetUserProfile();
How do you get the access token secret and value?

Using Ruby to authenticate to Azure (HTTP Header authentication)?

Since the Google Search API has been deprecated, I'd like to use the Bing Search API (now a Windows Azure API) in my Ruby apps.
However, Azure has a strange authentication pattern where you build a query URI, paste it into a browser, pass the key into the password box of the standard HTTP authentication box, and make POST to see the results. I assume this generates a signature and passes it in the header somehow. I'd like to do the complete process in Ruby and skip the browser portion if possible.
I found one example in the source of an obscure Windows Azure storage gem, but I can't figure out how tthey're building the signature and make the call. Is there a simple way to do basic HTTP auth in Ruby?
I went ahead and used Faraday's built in basic authentication scheme like so:
connection = Faraday.new "http://api.something.com/1/dudez"
connection.basic_auth "username" "password"
connection.get
I want to recommend the RestClient gem for this. I've used it with great success for GET'ing and POST'ing across domains. If you really have to act like a browser to implement the API, you can always use Capybara.
I'm sorry I haven't tried the Azure API myself, or I would give an example. :)
I recall doing this previously with another Azure API but am unable to find the code.
Look here for the details of the signature process:
http://msdn.microsoft.com/en-us/library/windowsazure/ee395415.aspx
I'm unable to find immediately if the Azure API uses the SharedSignature method
The way to sign a request to Windows Azure blob storage thru the REST API is described here: http://msdn.microsoft.com/en-us/library/dd179428.aspx.
Basically, you don't authenticate by simply adding some credentials in a HTTP header, you have to sign your request with the secret key that is associated to your storage account.

Resources