Bitbucket API OAuth not redirecting properly - oauth

I'm trying to set up Bitbucket OAuth for my site but for some reason Bitbucket is not properly redirecting back to my site. I've created an OAuth key and secret and I'm using the Guzzle OAuth plugin in my Silex application.
First I request a temporary token via the oauth/request_token endpoint. Using that token I redirect to oauth/authenticate endpoint:
$app->get(
'/auth/bitbucket',
function () use ($app) {
$client = new Client('https://bitbucket.org/api/1.0');
$oauth = new OauthPlugin(
array(
'consumer_key' => $app['bitbucket.key'],
'consumer_secret' => $app['bitbucket.secret'],
'signature_method' => 'HMAC-SHA1',
'callback' => urlencode('http://mysite.local/auth/bitbucket/callback')
)
);
$client->addSubscriber($oauth);
$response = $client->post('oauth/request_token')->send();
parse_str($response->getBody(), $result);
return $app->redirect(sprintf('https://bitbucket.org/api/1.0/oauth/authenticate?oauth_token=%s', $result['oauth_token']));
}
);
This will bring up the page on the Bitbucket site where the user can grant or deny access to their account. After I click "Grant access" Bitbucket should redirect back to the callback url that was specified earlier but instead it will append my callback url to the Bitbucket url like this:
https://bitbucket.org/api/1.0/oauth/http%3A%2F%2Fmysite.local%2Fauth%2Fbitbucket%2Fcallback?oauth_verifier=xxxxxxxxxx&oauth_token=xxxxxxxxxxxxxxxxxx
This obviously results in a Bitbucket 404 page. Does anyone have an idea why the redirect to my callback url is not working properly?

According to documentation, when requesting token from bitbucket's API, you MUST have those parameters when sending POST request to https://bitbucket.org/api/1.0/oauth/request_token:
oauth_consumer_key
oauth_nonce
oauth_signature
oauth_signature_method
oauth_timestamp
oauth_callback
Also, don't urlencode your callback URL. Replace this:
'callback' => urlencode('http://mysite.local/auth/bitbucket/callback')
With this:
'callback' => 'http://mysite.local/auth/bitbucket/callback'
When you are sending POST request, you do not need to encode any of parameters.
Indeed, as you mentioned in comment, documentation does show encoded parameters in example, as in:
https://bitbucket.org/api/1.0/oauth/request_token?oauth_version=1.0&oauth_nonce=7f2325b3c36bd49afa0a33044d7c6930&oauth_timestamp=1366243208&oauth_consumer_key=HUpRcDUduZrepL6sYJ&oauth_callback=http%3A%2F%2Flocal%3Fdump&oauth_signature_method=HMAC-SHA1&oauth_signature=qZyTwVA48RzmtCHvN9mYWmlmSVU%3D
Issue you have is not wrong documentation, but misunderstanding of POST method. Also check Wikipedia page. Unlike GET where parameters are passed in URL, POST request method stores it's data in body. That allows us to send any data type, arbitrarily long.
Data that is passed in body of request is automatically encoded as in this example (copied from Wikipedia page):
Name=Jonathan+Doe&Age=23&Formula=a+%2B+b+%3D%3D+13%25%21
Looks similar to GET method when you encode data manually, right? However, if you urlencode data in POST request you actually end up with double encoded data, which is cause of problems in your case.
I really think that some basic knowledge of HTTP methods and Internet protocols is required before playing with any API.
Also, check some HTTP traffic monitor (debugger), like free Fiddler. It will allow you to see all HTTP data that is sent from your browser, essentially enabling you to learn by own examples.

I'm not sure how your framework works, but the callback parameter may be url encoded by the framework before the request is made. Since you also url encode it, your url is url encoded twice. Bitbucket will decode it once, leaving it with a url encoded url, which won't have the scheme set (http in this case), and your browser won't know it is an absolute URL, and will thus navigate to somewhere inside Bitbucket (as you observe). Try removing the extra url encode and see if that helps.

Related

PHP Twilio RequestValidator returning false on all endpoints

So I really don't know what the problem is here, I've tried many things, but I can't get the Twilio request hashes to match up. Let me explain.
I decided to implement an instance of Twilio's RequestValidator to ensure the requests were coming from Twilio. But after following the tutorial here: https://www.twilio.com/docs/usage/security?code-sample=code-validate-signature-of-request-1&code-language=PHP&code-sdk-version=5.x
The validator is only returning false. Here is the code that I used:
$url = 'https://example.com/api/endpoint/to/endpoint/';
$request_params = $_REQUEST;
$twilio_validator = new RequestValidator('myauthtoken');
if (!$twilio_validator->validate($_SERVER['HTTP_X_TWILIO_SIGNATURE'], $url, $request_params)) {
throw new CallException('Not from Twilio');
}
Even though the URL is an example, that is exactly how I have the actual URL formatted...no port, basic auth, or fragment. Just the protocol, domain, and path with a trailing "/". In addition, the URL is the exact VoiceURL I set when I set up this Twilio App (this is calling the VoiceURL to one of my Twilio Apps).
My auth token is the auth token for my whole account
The request params is where I'm sure I'm messing something up. Twilio is making a GET request to this endpoint, and I tried using the $_GET superglobal as well, to no avail. I'm using $_REQUEST here because of this issue: https://github.com/twilio/twilio-php/issues/510 and because I thought it would be the best choice. I have also tried using file_get_contents('php://input') to the exact same problem (the hashes not matching, ultimately).
I even forked and opened a PR on the PHP SDK to update the class a little bit, just to see if I could learn any more...so I know the class and it's methods pretty well...I just don't see my issue.
What am I doing wrong here to make it so that the RequestValidator isn't validating that the requests from Twilio are coming from Twilio?
So after a lot of research and working with Twilio help, I figured out the answer to my question.
When Twilio is making a GET request to my server, you aren't supposed to pass the GET parameters as the third parameter to the validate method on the RequestValidator class. When Twilio is making a GET request to your server, validating actually needs to look like this:
// this is the interesting part...you don't even set the pathname on the domain...
// EVEN IF YOU THE PATHNAME IS SET IN YOUR VOICE URL.
// This is because of the different way the RequestValidator handles GET and POST params
$domain = 'https://example.com'; // make sure to add no trailing '/'
// setting up the RequestValidator
$twilio_validator = new RequestValidator('myauthtoken');
// figuring out if the request is from twilio
$is_from_twilio = $twilio_validator->validate(
// the signature header that Twilio sends
$_SERVER['HTTP_X_TWILIO_SIGNATURE'],
// The domain name CONCATENATED to the Request URI. $_SERVER['REQUEST_URI'] holds everything that comes after the domain name in a URL (pathname, query parameters, and fragment)
$domain.$_SERVER['REQUEST_URI']
// if the request is a get request, as mine are, there is no need for the third parameter
);
// resolving the response
if (!$is_from_twilio) {
echo 'Not from Twilio';
exit;
}
Refer to the comments in the code for a more in depth discussion on the code at work here..

passing request params in twitter call back url

I am working on a CustomerEngagement solution that is integrated with twitter. Looking for suggestion with implementation.
I have configured multiple twitter-apps with a call back URL for each twitter-app (same callback URL), pointing to the same end point in CustomerEngagement application.
I have 2 java methods written, 1 for responding to CRC challenge by twitter(authentication) and 1 for actually receiving the tweet from twitter.
I would like to configure multiple twitter-apps to be served/used by the same single instance of the CustomerEngagement-application from the same endpoint
However, the CustomerEngagement application should have a hint about which twitter-app is responsible for posting the tweet to the application, so that CRC response to twitter can be generated accordingly.
Can I pass a different request parameter in each call back URL of different twitter-apps to identify the app?
I already see a conversation on the same
https://twittercommunity.com/t/callback-url-with-fixed-query-string-parameters/107821
however, can some one please elaborate on how to achieve this ? I am assuming that this a 2 step process where registering the call back URL ( along with request parameter ) happens to be step 1, followed by setp 2 in which the call back by twitter having the request parameter registered in step 1 is passed !
Thanks in Advance!!
Say your configured callback_url is xyz.com/social/
append the query strings params when parsing the callback_url
tweepy
import tweepy
auth = tweepy.OAuthHandler(consumer_key, consumer_secret, 'xyz.com/social/?var=val')
url = auth.get_authorization_url()
You get an authorization URL that redirects to a twitter login page. After login, it returns
xyz.com/social/?var=val&oauth_token=****$oauth_verifier=***

Adding a query parameter to the Instagram auth redirect_uri doesn't work?

Steps to reproduce
Register a redirect_uri in the client: http://example.com/publisher/auth
Direct a user to the /oauth/authorize endpoint with the redirect_uri including a query parameter:
https://api.instagram.com/oauth/authorize/?client_id=xxx&redirect_uri=http%3A%2F%2Fexample.com%2Fpublisher%2Fauth%3FinviteId%3D00001000-cf33-11e4-9f26-8789dd0b3e01&response_type=code&scope=basic&type=web_server
For reference, those query parameters are:
client_id=xxx
redirect_uri=http%3A%2F%2Fexample.com%2Fpublisher%2Fauth%3FinviteId%3D00001000-cf33-11e4-9f26-8789dd0b3e01
response_type=code
scope=basic
type=web_server
Authenticate an instagram user and allow the app.
The user is redirected back to the correct redirect_uri.
Use the code query parameter from the redirected URI to post to Instagram's /oauth/access_token endpoint.
Expected behavior
The endpoint responds with 200 and an access token.
ACTUAL behavior
The endpoint responds with:
code=400
error_type = 'OAuthException'
error_message = 'Redirect URI doesn't match original redirect URI'
What I've Investigated So Far
To confirm that this is a problem with Instagram, I checked the API docs which very clearly state that adding query parameters to the redirect URI should be possible. I also tried varying only that query parameter. For example, when replaced with this /oauth/authorize URL I get the expected behavior:
https://api.instagram.com/oauth/authorize/?type=web_server&client_id=xxx&redirect_uri=http%3A%2F%2Fexample.com%2Fpublisher%2Fauth&response_type=code&scope=basic
For reference, those query parameters are:
client_id=xxx
redirect_uri=http%3A%2F%2Fexample.com%2Fpublisher%2Fauth
response_type=code
scope=basic
type=web_server
Notes
This question is actually a duplicate of another question which actually didn't really turn out to be a question, and which never got any answers.
I have submitted a bug with Instagram, but I wanted to see if anyone had found this or come up with a workaround.
Had the same issue today. To get the custom data passed between requests you must include it as state param. My authorize request url looked something like this:
https://www.instagram.com/oauth/authorize?client_id=SOME_CLIENT_ID&response_type=code&redirect_uri=http://example.com/auth/InstagramRedirect/&state=855C0114-F860-420A-AEB1-A276644FCCEA
Notice the & and state=...
You have to provide the redirect_uri with your extra search params as the last parameter:
https://www.instagram.com/oauth/authorize/?client_id=be1b911b487f4919b9c2fb7df0c4142c&type=web_server&response_type=code&scope=basic&redirect_uri=https://wpwifidemo.alepo.net/instagram/joinus/?inviteId=00001000-cf33-11e4-9f26-8789dd0b3e01
User will be redirected to:
https://wpwifidemo.alepo.net/instagram/joinus/?inviteId=00001000-cf33-11e4-9f26-8789dd0b3e01&code=CODE
It might be too late reply for this question. But i faced the same issue today & got this question already posted and solution for passing parameters to authentication URL is as follows.
It seems that your extra parameter is type=web_server , taking that into consideration, your URL for getting for code should be as follows
https://www.instagram.com/oauth/authorize/?client_id=be1b911b487f4919b9c2fb7df0c4142c&redirect_uri=https://wpwifidemo.alepo.net/instagram/joinus/?type=web_server&response_type=code&scope=basic
And then while calling the accessToken API append your redirect_uri parameter with your passed parameter (not the same configured in the app).
e.g.
redirect_uri=http%3A%2F%2Fexample.com%2Fpublisher%2Fauth%3FinviteId%3D00001000-cf33-11e4-9f26-8789dd0b3e01?type=web_server

Sending extra parameters to twitter's oauth/authorize

I want to send some extra parameters to twitter's oauth/authorize endpoint (along withoauth_token) and get them back as it is in the callback request (along with oauth_token and oauth_verifier).
For example:
request(extra parameter - app_name):
https://api.twitter.com/oauth/authorize?oauth_token=FxHxpekZK8VVfNRr38i2WKJskIZY3Hj7&app_name=myTwitterApp
callback request should be(extra parameter returned as it is - app_name):
http://www.example.com?oauth_token=FxHxpekZK8VVfNRr38i2WKJskIZY3Hj7&oauth_verifier=Vq0yq2LRUBybevnjGvXyUOBPWH9Ew9DY&app_name=myTwitterApp
Please let me know if this doable in twitter as it is in Google and Facebook.
Asked this question on twittercommunity and got the answer. The trick was to add the extra parameters in the callback url itself while obtaining the request token.

Twitter oauth_callback parameter being ignored!

I'm trying to get Twitter authentication working on my ASP.NET site. When you create the app on the Twitter website, you have to specify a callback URL, which for sake of argument, I have set to http://mydomain.com
I've read the oAuth 1.0a spec, and to override this callback URL with your own custom one you have to send the oauth_callback parameter in the request_token phase (url-encoded of course).
So my request URL looks like this:
http://twitter.com/oauth/request_token?oauth_callback=http%3A%2F%2Fmydomain.com%2Ftwittercallback
Supposedly, if all goes to plan, in your response data, you are supposed to receive a new parameter of oauth_callback_confirmed=true in addition to your token and token secret parameters.
However, my response comes through as:
oauth_token=MYTOKEN&oauth_token_secret=MYTOKENSECRET
I know I haven't given you guys the greatest amount to go on, but I'm at my wits end as to why I am not receiving the oauth_callback_confirmed parameter. Without this, my application keeps defaulting back to the callback URL hard-coded on the Twitter website. Please if anyone could help me out, I will be eternally grateful!
Thanks,
A.
I've read the oAuth 1.0a spec, and to
override this callback URL with your
own custom one you have to send the
oauth_callback parameter in the
request_token phase (url-encoded of
course).
So my request URL looks like this:
http://twitter.com/oauth/request_token?oauth_callback=http%3A%2F%2Fmydomain.com%2Ftwittercallback
just because YOU read the spec doesn't mean that TWITTER read it. :P
kidding - this is essentially correct - but the way twitter likes to receive this data is a little different (and not well documented).
the way i've found to get the oauth_callback to confirm is as follows: specify the oauth_callback in the parameters of the request function, NOT within the URL.
python example (using oauth2):
''' Create our client.'''
client = oauth.Client(consumer)
''' do the request '''
resp, content = client.request(request_token_url,"POST",body=urllib.urlencode({'oauth_callback':callbackURL}))
''' note that it's called "body" in this particular OAuth function for Client but in OAuth Request object it's called "parameters." YMMV depending on programming language/ library of course. '''
this is ALSO the only way i've managed to get an oauth verifier back. supposedly one should not have to specify the callback URL every time, since we provide it in app settings...but experience seems to indicate otherwise.
finally, please be aware that at leg 3 you have to do the same thing AGAIN - this time including the oauth_verifier as well as the callback URL in the parameters.
hope this helps - can't begin to tell you how much effort i put into figuring this out.
good luck!
J
I've used this guide to set up my PC to be used as the callback location. Basically you set up your hosts file in a certain way, clear your cache and add a couple of Firefox registry values. At the end when you are debugging an oauth call the redirect comes back to your local PC.
As I said it worked for me.
<?php
// oauth-php example
$token = OAuthRequester::requestRequestToken(
$consumer_key,
$user_id,
array('oauth_callback'=> urlencode($callback_uri))
);
?>

Resources