Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing Google API Java Client on Android, a POST request does not seem to authenticate with Google App Engine app using OAuth
    primarykey
    data
    text
    <p>I have an Android client that needs to authenticate with a python Google App Engine app using OAuth. I followed <a href="http://fabiouechi.blogspot.com/2011/11/using-google-oauth-java-client-to.html" rel="nofollow">this article</a>.</p> <p>And was able to successfully do so using an HTTP Get Request. The Android client uses the package com.google.api.client to accomplish this:</p> <pre><code>OAuthHmacSigner _signer; HttpTransport TRANSPORT = new NetHttpTransport(); _signer = new OAuthHmacSigner(); _signer.clientSharedSecret = CONSUMER_SECRET; // STEP1: get a request token OAuthGetTemporaryToken requestToken = new OAuthGetTemporaryToken(REQUEST_TOKEN_URL); requestToken.consumerKey = CONSUMER_KEY; requestToken.transport = TRANSPORT; requestToken.signer = _signer; requestToken.callback = "http://my_app_specific_callback"; requestTokenResponse = requestToken.execute(); OAuthAuthorizeTemporaryTokenUrl authorizeUrl = new OAuthAuthorizeTemporaryTokenUrl(AUTHORIZE_URL); authorizeUrl.temporaryToken = requestTokenResponse.token; // at this point, redirect the user using a WebView to the URL string returned by authorizeUrl.build(). Continue below once the user has granted request. // STEP2: get an access token _signer.tokenSharedSecret = requestTokenResponse.tokenSecret; OAuthGetAccessToken accessToken = new OAuthGetAccessToken(ACCESS_TOKEN_URL); accessToken.consumerKey = CONSUMER_KEY; accessToken.signer = _signer; accessToken.transport = TRANSPORT; accessToken.temporaryToken = requestTokenResponse.token; accessTokenResponse = accessToken.execute(); // STEP3: use the access token acquired above to access a protected resource _signer.tokenSharedSecret = accessTokenResponse.tokenSecret; OAuthParameters parameters = new OAuthParameters(); parameters.consumerKey = CONSUMER_KEY; parameters.token = accessTokenResponse.token; parameters.signer = _signer; HttpRequestFactory factory = TRANSPORT.createRequestFactory(parameters); HttpRequest req = factory.buildGetRequest(new GenericUrl(PROTECTED_URL_GET_USER_EMAIL)); com.google.api.client.http.HttpResponse resp = req.execute(); </code></pre> <p>In the above code snippet, all the 3 steps work just fine. And on my Google App Engine server, I inspected the GET request made to the PROTECTED_URL_GET_USER_EMAIL, and it contained a proper authentication HTTP Header:</p> <pre><code>'Authorization': 'OAuth oauth_consumer_key="shiprack-test1.appspot.com", oauth_nonce="...", oauth_signature="...", oauth_signature_method="HMAC-SHA1", oauth_timestamp="...", oauth_token="..."' </code></pre> <p>Using the oauth python package on GAE (google.appengine.api.oauth), my server is able to authenticate the user and determine the user's email address (oauth.get_current_user()).</p> <p>However, the problem is when I convert the PROTECTED_URL_GET_USER_EMAIL to an HTTP Post request. This is how I do that:</p> <pre><code>Map&lt;String, String&gt; paramsMap = new HashMap&lt;String, String&gt;(); paramsMap.put("param1", "value1") paramsMap.put("param2", "value2") HttpRequest req = _httpRequestFactory.buildPostRequest(new GenericUrl(url), new UrlEncodedContent(paramsMap)); req.setFollowRedirects(true); com.google.api.client.http.HttpResponse resp = req.execute(); </code></pre> <p>But now, on the GAE python server side, I'm not able to determine the current user. The HTTP Headers contain the same OAuth Authentication headers (with a different nonce, timestamp and signature, but the same oauth token). The "param1" and "param2" are in the HTTP Payload. Perhaps my POST request is not constructed properly?</p> <p>I used <a href="http://ikaisays.com/2011/05/26/setting-up-an-oauth-provider-on-google-app-engine/" rel="nofollow">Ikai Lan's</a> (Google App Engine support team) code for a python client to authenticate against my GAE server. And this worked too... the original client with the GET request, and even when I modified it to use a POST request. I noticed though that with the POST request, the oauth parameters were included as URL encoded values in the HTTP payload instead of the in the HTTP header. Is this a requirement for Oauth-signed HTTP post requests?</p> <p>Thanks in advance!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. COI found out that not all HTTP Post requests signed by an oauth signature fail. Only those that have url encoded form data with app specific key/value pairs. Empty HTTP Post requests (with the Oauth parameters embedded in the HTTP headers) work just fine, as do HTTP Get requests.
      singulars
    2. COMore updates: Any HTTP PUT request that has URL Encoded data does not work. If I encode application/json, for example, the GAE server is able to determine the authenticated user from the oauth Authentication HTTP headers that my Android client app sends (using the google client java api). Also, I expected the OAuthHmacSigner class to automatically add the oauth parameters as URL Encoded payload data if I provided app-specific payload data that was also URL Encoded. Oauth spec indicates that these parameters must be alphabetically listed. But this did not happen.
      singulars
    3. COFor anyone trying to do this - encoding app-specific data as application/json, and signing it with oauth credentials, here's a good post on how to ensure your json formatting is legit: http://www.bennadel.com/blog/557-JSON-Unterminated-String-Literal-Error.htm
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload