Cannot get App Engine to authenticate

54 views
Skip to first unread message

Paddy Foran

unread,
Jun 12, 2010, 9:25:56 PM6/12/10
to Signpost users
I'm trying to authenticate to an App Engine site using OAuth with
SignPost and Apache's HttpClient. Here's the method in question:

private void goToLink(String url) {
try {
String host = settings.getString("host", DEF_HOST);
Log.i("android2cloud", "host: "+host);
consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY,
CONSUMER_SECRET);
String access_token = settings.getString("token", "error");
String access_secret = settings.getString("secret", "error");
Toast.makeText(this, "post-setting host: " + host + " | token: " +
access_token + " | secret: " + access_secret,
Toast.LENGTH_LONG).show();
consumer.setTokenWithSecret(access_token, access_secret);
String target = host+"/links/add";
HttpPost request = new HttpPost(target);
StringEntity entity = new StringEntity(url);
request.setEntity(entity);
DefaultHttpClient httpClient = new DefaultHttpClient();
consumer.setMessageSigner(new HmacSha1MessageSigner());
consumer.sign(request);
Toast.makeText(this, "Signed!", Toast.LENGTH_LONG).show();
String response = httpClient.execute(request, new
BasicResponseHandler());
Toast.makeText(this, response, Toast.LENGTH_LONG).show();
Log.i("android2cloud", response);
} catch (Exception e) {
Log.e("android2cloud", e.getMessage());
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
}
}

However, upon sending the request, all I get is a login page.

Any thoughts?

Paddy Foran

unread,
Jun 14, 2010, 10:57:24 AM6/14/10
to Signpost users
Upon further inspection, it seems that App Engine only supports Query
String Signing. And I keep getting the UnsupportedOperationException
when I try to query string sign my HttpClient request (read somewhere
that wasn't supported, for one reason or another, and can't figure out
how to fix it).

Paddy Foran

unread,
Jun 14, 2010, 11:18:24 AM6/14/10
to Signpost users
OK, now I'm just making myself look stupid. I finally managed to get the OAuth parameters into the URL, but now it's still ignoring them.

Here's a request from signpost (doesn't work):  - - [14/Jun/2010:08:07:53 -0700] "POST /links/add?oauth_signature=ElF67F0754VbuHFKtTnUy%2Fuhoz4%3D&oauth_token=1%2Fkn3wvWK70_1Pd6RlXUjS6ejcn65KC2DVGTL9bA2NpkU&oauth_consumer_key=anonymous&oauth_version=1.0&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1276528066&oauth_nonce=5594525461063691083 HTTP/1.1" 302 368 - "Apache-HttpClient/UNAVAILABLE (java 1.4),gzip(gfe)"

Here's a request from another source (works): - foran.paddy [14/Jun/2010:08:07:39 -0700] "GET /links/get?oauth_consumer_key=anonymous&oauth_nonce=EHF1z&oauth_signature=40M%2B40hs%2Bi3ydGtttGBlSsP6Y%2Bo%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1276528057&oauth_token=1%2FWqo2GFihmvjsCs2fDBmj3fagjly_x7Z-5Lh9P9kfbdk HTTP/1.1" 200 176 - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.70 Safari/533.4,gzip(gfe)"

Any ideas or help on this would be greatly appreciated.

Thanks,
Paddy Foran
Adolescent Education/English major
Class of 2012
Buffalo Improv Troupe President


--
You received this message because you are subscribed to the Google Groups "Signpost users" group.
To post to this group, send email to signpos...@googlegroups.com.
To unsubscribe from this group, send email to signpost-user...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/signpost-users?hl=en.


matthias

unread,
Jun 16, 2010, 3:28:09 AM6/16/10
to Signpost users
DO NOT use DefaultOAuth* implementations on Android, that won't work
(Apache Harmony's HTTP implementation is broken). When using Apache
Commons HTTP, you should use the respective CommonsHttpOAuth* classes.
Try that and see if it helps.

On Jun 14, 5:18 pm, Paddy Foran <foran.pa...@gmail.com> wrote:
> OK, now I'm just making myself look stupid. I finally managed to get the
> OAuth parameters into the URL, but now it's still ignoring them.
>
> Here's a request from signpost (doesn't work):  - - [14/Jun/2010:08:07:53
> -0700] "POST
> /links/add?oauth_signature=ElF67F0754VbuHFKtTnUy%2Fuhoz4%3D&oauth_token=1%2Fkn3wvWK70_1Pd6RlXUjS6ejcn65KC2DVGTL9bA2NpkU&oauth_consumer_key=anonymous&oauth_version=1.0&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1276528066&oauth_nonce=5594525461063691083
> HTTP/1.1" 302 368 - "Apache-HttpClient/UNAVAILABLE (java 1.4),gzip(gfe)"
>
> Here's a request from another source (works): - foran.paddy
> [14/Jun/2010:08:07:39 -0700] "GET
> /links/get?oauth_consumer_key=anonymous&oauth_nonce=EHF1z&oauth_signature=40M%2B40hs%2Bi3ydGtttGBlSsP6Y%2Bo%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1276528057&oauth_token=1%2FWqo2GFihmvjsCs2fDBmj3fagjly_x7Z-5Lh9P9kfbdk
> HTTP/1.1" 200 176 - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US)
> AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.70
> Safari/533.4,gzip(gfe)"
>
> Any ideas or help on this would be greatly appreciated.
>
> Thanks,
> Paddy Foran
> Adolescent Education/English major
> Class of 2012
> Buffalo Improv Troupe President
>
> > signpost-user...@googlegroups.com<signpost-users%2Bunsu...@googlegroups.com>
> > .

Paddy Foran

unread,
Jun 16, 2010, 10:13:25 AM6/16/10
to signpos...@googlegroups.com
Matthias,

No dice. :(

Here's the new, updated method:

private void goToLink(String url) {
try {
   String host = settings.getString("host", DEF_HOST);
   Log.i("android2cloud", "host: "+host);
consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
String access_token = settings.getString("token", "error");
String access_secret = settings.getString("secret", "error");
consumer.setTokenWithSecret(access_token, access_secret);
String target = host+"/links/add";
HttpPost request = new HttpPost(target);
List<NameValuePair> data = new ArrayList<NameValuePair>(1);
data.add(new BasicNameValuePair("link", url));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(data);
request.setEntity(entity);
DefaultHttpClient httpClient = new DefaultHttpClient();
consumer.setMessageSigner(new HmacSha1MessageSigner());
consumer.setSigningStrategy(new QueryStringSigningStrategy());
String newTarget = consumer.sign(target);
HttpPost newRequest = new HttpPost(newTarget);
newRequest.setEntity(entity);
Log.i("android2cloud", url);
Toast.makeText(this, "Signed!", Toast.LENGTH_LONG).show();
String response = httpClient.execute(newRequest, new BasicResponseHandler());
Toast.makeText(this, response, Toast.LENGTH_LONG).show();
Log.i("android2cloud", response);
} catch (Exception e) {
Log.e("android2cloud", e.getMessage());
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
}
}

Thanks for your help with this.

Thanks,
Paddy Foran
Adolescent Education/English major
Class of 2012
Buffalo Improv Troupe President


To unsubscribe from this group, send email to signpost-user...@googlegroups.com.

Matthias Käppler

unread,
Jun 16, 2010, 10:25:56 AM6/16/10
to signpos...@googlegroups.com
ah I'm sorry, I was a little to hasty with that (but it's still valid).

At a second glance, I see a couple issues with your code. First,
QueryStringSigningStrategy, you cannot use that to sign requests. Or
to quote from that class' documentation: ;-)

"Writes to a URL query string. Note that this currently ONLY works
when signing a URL directly, not with HTTP request objects."

so, you can use it to "sign" a URI string to produce clickable, signed
URLs, but it doesn't work on an existing request object

that's because often you cannot change the URI for a request object
that has already been created (Apache commons HTTP requests don't
allow that for instance). I think there's a ticket to create a
workaround for this, but currently just don't use it unless you're
creating a signed URL.

that being said, what you could do is use Signpost to the sign the URL
first, then use that signed URL to create your request object (and
don't sign that again).

Just curious, why do you want to use the URL to carry the signature?
That's a pretty uncommon thing to do, just use the HTTP Authorization
header (which is the default) and you wouldn't even run into this
problem.

Another remark: You can remove the call to setMessageSigner().
HMAC-SHA1 is the default.

Yet another remark: I believe your code is still wrong even when
changing the above things, since you seem to sign the request /before/
adding more parameters to it (using the UrlEncodedFormEntity), or am I
misunderstanding that? The OAuth signature must contain ALL request
parameters, otherwise authentication will fail.

Does that make sense?

Cheers,
Matthias

2010/6/16 Paddy Foran <foran...@gmail.com>:

--
PLEASE NOTE OUR NEW ADDRESS!
-------------------------------------------------------

Matthias Käppler
Software Developer

Qype GmbH
Großer Burstah 50-52
20457 Hamburg
Telephone: +49 (0)40 - 219 019 2 - 260
Skype: m_kaeppler
Email: matt...@qype.com

Managing Director: Ian Brotherston
Amtsgericht Hamburg
HRB 95913

This e-mail and its attachments may contain confidential and/or
privileged information. If you are not the intended recipient (or have
received this e-mail in error) please notify the sender immediately
and destroy this e-mail and its attachments. Any unauthorized copying,
disclosure or distribution of this e-mail and its attachments is
strictly forbidden. This notice also applies to future messages.

Paddy Foran

unread,
Jun 16, 2010, 10:36:00 AM6/16/10
to signpos...@googlegroups.com
Matthias,

It does make sense, thanks.

I had noticed the issue with QueryStringSigningStrategy (I promise, I've been Googling and reading documentation for days. I'm trying to fix it the best I can, I seem to just be failing). My only issue is that Google App Engine does not seem to support the HTTP Authorization Header, from what documentation I can find. Which means I have to carry it in the URL header.

That being said, I actually have the workaround implemented in my code. I'm using two different request objects:

String newTarget = consumer.sign(target); // target is the URL as a string. newTarget is the new signed URL as a String
HttpPost newRequest = new HttpPost(newTarget); // make a new request using the signed URL
newRequest.setEntity(entity); // add the data to the request (which can't be signed)
String response = httpClient.execute(newRequest, new BasicResponseHandler()); // execute the request

Sorry for the confusion- I know my code isn't very clean right now, I've been hacking and mutilating it for days, trying to get something to work.

Any insight you could offer on this would be wonderful. Thanks for all your help.


Thanks,
Paddy Foran
Adolescent Education/English major
Class of 2012
Buffalo Improv Troupe President


2010/6/16 Matthias Käppler <m.kae...@googlemail.com>

Matthias Käppler

unread,
Jun 16, 2010, 10:46:50 AM6/16/10
to signpos...@googlegroups.com
try this (I removed the log output and stuff):

consumer = new CommonsHttpOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
String access_token = settings.getString("token", "error");
String access_secret = settings.getString("secret", "error");
consumer.setTokenWithSecret(access_token, access_secret);

DefaultHttpClient httpClient = new DefaultHttpClient();

// replace the POST entity stuff with a simple URL query string
String target = OAuth.addQueryParameters(host + "/links/add", "link", url);

// sign the above URL
consumer.setSigningStrategy(new QueryStringSigningStrategy());
target = consumer.sign(target)

// send the request


HttpPost request = new HttpPost(target);

httpClient.execute(request)


this will carry all parameters in the URL, but the app server probably
won't care.


HTH,

Paddy Foran

unread,
Jun 16, 2010, 10:55:27 AM6/16/10
to signpos...@googlegroups.com
Still getting the login screen, meaning it isn't authenticating... :-/

I'm not sure if this is an App Engine thing or a SignPost thing. Would it help to see the Chrome extension code I have successfully authenticating, or no?

Matthias Käppler

unread,
Jun 16, 2010, 11:22:44 AM6/16/10
to signpos...@googlegroups.com
to be honest, I've never worked with AppEngine before so I'm probably
not much help if it's something AppEngine specific. Are you sure you
pass all the parameters it requires and stuff? go ahead and post the
code, but I can't promise anything.

2010/6/16 Paddy Foran <foran...@gmail.com>:

Paddy Foran

unread,
Jun 16, 2010, 11:30:39 AM6/16/10
to signpos...@googlegroups.com
On looking through the JavaScript (I used a library for that, as well) I found that there's an Authorization Header generating function, as well.

I'm not familiar enough with OAuth to know, but is it possible App Engine wants a query string signature AND an Auth header signature?

Matthias Käppler

unread,
Jun 16, 2010, 11:35:16 AM6/16/10
to signpos...@googlegroups.com
no, that wouldn't make sense. Did you try using just the Auth header?
that would mean preparing your request entirely, then calling sign()
once (without any custom settings such as different signing strategy
or whatever) and sending it.

2010/6/16 Paddy Foran <foran...@gmail.com>:

Paddy Foran

unread,
Jun 16, 2010, 11:38:09 AM6/16/10
to signpos...@googlegroups.com
Yeah, I tried that originally, before I started with all the QueryString nonsense.

I'm not sure what gives. I can tell, from the (limited) logs I'm given, that the QueryString method is sending every parameter as the working Javascript is, it's just not authenticating for some unknown reason.

I'm going to ask around on the App Engine discussion list, and see if anyone over there has any idea what's going on, and I'm going to try fiddling randomly with my code some more. Maybe I can get this to work out of sheer luck.

At least I feel better, knowing I'm not doing anything obvious and stupid.

Matthias Käppler

unread,
Jun 16, 2010, 11:46:37 AM6/16/10
to signpos...@googlegroups.com
sorry to be of not much help here, but good luck anyway (I surely
spent too many hours in my life debugging OAuth apps)...

cheers,

Paddy Foran

unread,
Jun 16, 2010, 11:48:32 AM6/16/10
to signpos...@googlegroups.com
Out of curiosity, is there any (relatively simple way) I can get SignPost to display the headers it's sending?

Matthias Käppler

unread,
Jun 16, 2010, 11:50:47 AM6/16/10
to signpos...@googlegroups.com
it will print debug output when run using the -Ddebug flag, I think I
also added the Auth header to that output, so you may want to give
that a try.

2010/6/16 Paddy Foran <foran...@gmail.com>:

Paddy Foran

unread,
Jun 16, 2010, 11:52:48 AM6/16/10
to signpos...@googlegroups.com
I guess I'm just a little confused; how do I run a library with flags?

Matthias Käppler

unread,
Jun 16, 2010, 12:13:22 PM6/16/10
to signpos...@googlegroups.com
ah damn, I forgot you're running on Android. Well usually you would
launch the JVM with that flag (as in `java YourClass -Ddebug`), but I
believe the Android emulator doesn't allow you to pass system
properties to Dalvik on the command line (at least I'm not aware of
any way to do so).

But what you can try is doing it in program code, before running any
Signpost code:

System.setProperty("debug", true);

I didn't actually try that, but it should do the job.

2010/6/16 Paddy Foran <foran...@gmail.com>:

Paddy Foran

unread,
Jun 16, 2010, 1:56:48 PM6/16/10
to signpos...@googlegroups.com
I've managed to get my provider to actually give me a helpful error message, through tweaking the code on that end. This is what I'm getting:

exception InvalidOAuthParametersError()

The client provided OAuth parameters with the request, but they are invalid.


When using the code Matthias provided above.

Am I right in assuming this is just OAuth complaining that all the parameters are in the URL? Or is it getting pissy that my access key and secret are wrong?

Matthias Käppler

unread,
Jun 16, 2010, 3:51:23 PM6/16/10
to signpos...@googlegroups.com
good question. Is that all it says, or did it give any insight into
which parameters are wrong?

Paddy Foran

unread,
Jun 16, 2010, 4:18:59 PM6/16/10
to signpos...@googlegroups.com
It does not, unfortunately. However, doing some further research, I've accidentally stumbled onto a better solution: using the phone's built-in accounts system. http://blog.notdot.net/2010/05/Authenticating-against-App-Engine-from-an-Android-app

Thanks for all your help. :)

Matthias Käppler

unread,
Jun 16, 2010, 4:31:39 PM6/16/10
to signpos...@googlegroups.com
that sounds reasonable :-)

2010/6/16 Paddy Foran <foran...@gmail.com>:

Reply all
Reply to author
Forward
0 new messages