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

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.

Related

Elixir Phoenix Absinthe GraphQL API authentication in both web and mobile app's

I'm working on an Absinthe GraphQL API for my app. I'm still learning the procedure(so please go easy on me).
I've a Absinthe/GraphQL MyAppWeb.schema.ex file in which I use for my queries and mutations. My question is how do I use this API for authenticating the user on both Mobile and Web app?
How do set a cookie(httpOnly & secure) in my web app and access/refresh tokens in a single Absinthe API to serve my website and mobile app. Basically what I'm trying to learn is how do I authenticate the user based on specific platform.
If my question sounds bit confusing, I would be happy to provide more information related to my question. I would really be grateful if someone could explain the procedure, I've been very stuck on this for a while.
I would avoid using authentication mechanisms provided by absinthe(if there are any). Depending on what front-end you are using, I would go with JSON API authentication. The flow on server goes the following way:
Create a endpoint for login that will receive a user and password and will return a refresh token.
Create a endpoint for exchanging refresh token for access token.
Use a library like guardian to generate your refresh/access tokens.
Create a phoenix plug for authentication that will check your tokens, guardian has some built-in plugs for this.
Now on device you have to implement:
Ability to save refresh and access token on device.
Have a global handler for injecting access token on authorized requests.
Have a global handler for case when access token is expired. (you usually check if your request returns Unauthorized, then you should request a new access token from the server using your refresh token)
This seems like a crude implementation, however I would advise in implementing your system instead of using a black box library that you have no idea how it works under the hood.

ASP Identity OAuth token - Should I use ValidateClientAuthentication() and Secret in mobile app flow?

I have a mobile app which talks to an ASP WebAPI on the back-end.
I've implemented the token flow authentication (with the help of Taiseer's guide).
Still there is one concept I can't grasp my mind around: CleintId and ClientSecret.
From what I understand the client secret (along with client id) is meant to
block access to the end point in my API that produces tokens. This way the end point is protected from malicious users trying to poke around the API and try to gain some information by invoking it with various inputs.
Meaning, only clients which hold the secret can start an authenticaon flow. And in my case, I have only one client which is a mobile app, and it's secret is stored in a secure place (KeyChain for iOs). But I've read that those key chains can be easily dumped and dissect for the secret.
So the conclusion I came up with, is that I can get rid of the whole client secret logic, mainly leaving ValidateClientAuthentication() blank:
public async override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return;
}
And to me it dose not seem like a security hole, but just a thin layer in the flow that is gone now. Because, again, the client secret can be easily revealed by any malicious user holding a mobile device with the app installed, and once he gets it this layer of security is useless.
Are those assumptions are incorrect ?
Can I leave the ValidateClientAuthentication() method blank ?
As you already figured out, mobile applications cannot keep their credentials private because they can be extracted from the application binaries. Not to mention that requests can be easily intercepted using a proxy server and a traffic analyzer like Fiddler or Wireshark.
With the authorization code flow (1) or the resource owner password credentials grant, client authentication is not mandatory if the client cannot safely store its credentials and thus cannot be considered as a "confidential" application (see https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3 and https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2).
For non-confidential applications, it's safe to call context.Validated().
Personally, I try to avoid the resource owner password credentials grant as much as possible as it clearly defeats the purpose of OAuth2: keeping your password confidential and giving constrained authorizations. If your app is fully trusted, it shouldn't be a problem, though.
In practice, using the authorization code flow without enforcing client authentication is extremely rare, as it's simpler to use the implicit flow with mobile client applications, that offers a similar security level in this case (not to mention that it avoids a second roundtrip to the token endpoint).

How to use 2 legged oauth on Google Admin Directory 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.

Protect Web API from unauthorized applications

I am working on a web page that uses a lot of AJAX to communicate with the server. The server, in turn, has an extensive REST/JSON API exposing the different operations called by the web client.
This web site is used by both anonymous and authenticated users. As you might expect, the web service calls issued by authenticated users require authentication, and are thus protected from unauthorized users or applications.
However, the web site has a lot of features that require no authentication, and some of these make use of anonymous web services. The only way I am using to prevent outsiders from calling this web services is by using a CSRF token. I know, the CSRF token is not very useful in this regard... with some time in hand, you can figure out how to consume the web services even if they use a CSRF token.
Of course, you can use a CAPTCHA to prevent applications or bots from autonomously using your web service. However, any human will be able to use it.
Sharing a secret key between client and server, on the other side, would be useless. This, because of the ability of any outsider to read it from the web page source code.
I would like to make these web services as difficult to invoke as posible to any 3rd party application. What would you do besides using the CSRF token? It sounds a little stupid, but hey, maybe it is stupid and I am just losing my time.
Note: given this application uses a browser and not an "executable" as the client, this question is irrelevant to the discussion. I cannot use a secret between server and client (not to my knowledge, at least)
I would take a few steps.
Force https on the site. Automatically redirect any incoming http requests to https ones (the RequireHttps attribute is handy for this)
Each page needs to (securely, hence the https) send a one-time use token to the client, to be used for the page. The script running on the client can hold this in the page memory. Any request coming back sends a hashed & salted response, along with the nonce salt. The server can repeat the steps with the saved token + salt and hash to confirm the request. (much like explunit's answer above)
(It's worth noting that the secure request from a client isn't being authenticated from a user account, merely a token sent with the full page.)
The definition for one-time could either be session or page load, depending on your security vs convenience preference. Tokens should be long and expired fairly quickly to frustrate attackers.
The SSL + Hash(token + nonce) should be enough for your needs.
This is interesting. Below is a crazy suggestion. Remember, your question is also equally crazy.
Your website, once opened through a browser, should generate a long polling connection (Comet programing). This will create a unique session between the browser and the server. When ur JS is making the ajax call, send some token (unique token every time) to the server through the long polling thread. Let the AJAX also send the same token. At the server, get the AJAX token and check whether you have a similar token in you long polling session. If yes, fulfill the request. Any coder can break this. But, it won't be easy. Chances are the freeboarders won't even see these second piece of comet code. You can implement the comet code in such a way it is not easy to detect or understand. When they call ur service, send a 'Service Unavailable' message. They will be confused. Also make the comet code https.
You can also check how long that long polling thread is open. If the session was just opened and you get a ajax call right away, you can assume it is a 3rd party call. It depends on ur website flow. If ur Ajax call happens after 1 second of page load, you can check for that pattern on server side.
Anyone coding for your public api, will have 1 to 2 secret checks that they wouldn't even know and even if they know, they might be discouraged by all the extra coding they have to do.
You might have an easier problem than the one described in the linked question since you don't need to distribute a binary to the users. Even if your app is open source, the HMAC/signature key (in the "Request Signatures" part of that answer) can be controlled by an environment/configuration setting.
To summarize:
The secret key is not actually sent between client and server. Rather, it's used to sign the requests
Be sure that the requests include some unique/random element (your CSRF key probably suffices) so that two requests for the same API data are not identical.
Sign the request with the secret key and append the signature to the request. You linked to a PHP question but not clear if what language you're using. In .Net I would use a HMAC class such as HMACSHA256.
On the API server-side use the same HMAC object to verify that the request was signed with the same secret key.
Maybe you could use counters to keep track of conversations. Only the Server and Clients will be able to predict the next iteration in a conversation. This way, I think, you can prevent third party applications to impersonate someone (Just an idea though).
At the beginning, they start talking at some iteration (i=0, for example).
Every time the client requests something, the counter is incremented by some number in both the server side and the client (i=i+some_number).
And, after a few minutes of no communication, they both know they have to reset the counter (i=0).
This is just an idea based on the concept of RSA and also placing Fraud Detection on your system. The Risk from Authorized users is minimal however they can attempt to make anonymous calls to your web-service too.
For UN-Authorised users : For each web-service call , generate a token say using RSA which changes after some time(can be configured say 30 min). This way prediction of code is minimized. I have not heard of RSA collision till now. Send this token back to the user for his browser session. For further security , we might want to attach a session id with RSA token. Since session ids are unique new anonymous calls would require new session id.
Calls can be tracked using Auditing mechanism. Also per-web service there can be a different RSA setup. How the Algorithm for Fraud Detection would work is a challenge by itself.
For Authorized Users :
Every user should be tracked by his IP Address using Header block. The RSA token principle can be applied.
The solution is very vague but worth considering.

Creating a local Token cache using the Geneva Framework

Haven't seen many Geneva related questions yet, I have posted this question in the Geneva Forum as well...
I'm working on a scenario where we have a win forms app with a wide installbase, which will be issuing frequent calls to various services hosted by us centrally throughout it's operation.
The services are all using the Geneva Framework and all clients are expected to call our STS first to be issued with a token to allow access to the services.
Out of the box, using the ws2007FederationHttpBinding, the app can be configured to retrieve a token from the STS before each service call, but obviously this is not the most efficient way as we're almost duplicating the effort of calling the services.
Alternatively, I have implemented the code required to retrieve the token "manually" from the app, and then pass the same pre-retrieved token when calling operations on the services (based on the WSTrustClient sample and helpon the forum); that works well and so we do have a solution,but I believeit's not very elegant as it requires building the WCF channel in code, moving away from the wonderful WCF configuration.
I much prefer the ws2007FederationHttpBinding approach where by the client simply calls the service like any other WCF service, without knowing anything about Geneva, and the bindings takes care of the token exchange.
Then someone (Jon Simpson) gave me [what I think is] a great idea - add a service, hosted in the app itself to cache locally retrieved tokens.
The local cache service would implement the same contract as the STS; when receiveing a request it would check to see if a cahced token exists, and if so would return it, otherwise it would call the 'real' STS, retrive a new token, cache it and return it.
The client app could then still use ws2007FederationHttpBinding, but instead of having the STS as the issuer it would have the local cache;
This way I think we can achieve the best of both worlds - caching of tokens without the service-sepcific custom code; our cache should be able to handle tokens for all RPs.
I have created a very simple prototype to see if it works, and - somewhat not surprising unfortunately - I am slightly stuck -
My local service (currently a console app) gets the request, and - first time around - calls the STS to retrieve the token, caches it and succesfully returns it to the client which, subsequently, uses it to call the RP. all works well.
Second time around, however, my local cahce service tries to use the same token again, but the client side fails with a MessageSecurityException -
"Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security."
Is there something preventing the same token to be used more than once? I doubt it because when I reused the token as per the WSTrustClient sample it worked well; what am I missing? is my idea possible? a good one?
Here's the (very basic, at this stage) main code bits of the local cache -
static LocalTokenCache.STS.Trust13IssueResponse cachedResponse = null;
public LocalTokenCache.STS.Trust13IssueResponse Trust13Issue(LocalTokenCache.STS.Trust13IssueRequest request)
{
if (TokenCache.cachedResponse == null)
{
Console.WriteLine("cached token not found, calling STS");
//create proxy for real STS
STS.WSTrust13SyncClient sts = new LocalTokenCache.STS.WSTrust13SyncClient();
//set credentials for sts
sts.ClientCredentials.UserName.UserName = "Yossi";
sts.ClientCredentials.UserName.Password = "p#ssw0rd";
//call issue on real sts
STS.RequestSecurityTokenResponseCollectionType stsResponse = sts.Trust13Issue(request.RequestSecurityToken);
//create result object - this is a container type for the response returned and is what we need to return;
TokenCache.cachedResponse = new LocalTokenCache.STS.Trust13IssueResponse();
//assign sts response to return value...
TokenCache.cachedResponse.RequestSecurityTokenResponseCollection = stsResponse;
}
else
{
}
//...and reutn
return TokenCache.cachedResponse;
This is almost embarrassing, but thanks to Dominick Baier on the forum I no now realise I've missed a huge point (I knew it didn't make sense! honestly! :-) ) -
A token gets retrieved once per service proxy, assuming it hadn't expired, and so all I needed to do is to reuse the same proxy, which I planned to do anyway, but, rather stupidly, didn't on my prototype.
In addition - I found a very interesting sample on the MSDN WCF samples - Durable Issued Token Provider, which, if I understand it correctly, uses a custom endpoint behaviour on the client side to implement token caching, which is very elegant.
I will still look at this approach as we have several services and so we could achieve even more efficiency by re-using the same token between their proxies.
So - two solutions, pretty much infornt of my eyes; hope my stupidity helps someone at some point!
I've provided a complete sample for caching the token here: http://blogs.technet.com/b/meamcs/archive/2011/11/20/caching-sts-security-token-with-an-active-web-client.aspx

Resources