Trouble making authenticated calls to Bitbucket API via OAuth - oauth

I'm trying to make authenticated calls to the Bitbucket REST API, with Oauth authentication. I've successfully retrieved an oauth_token and an oauth_token_secret (although they are the same as the request_token and request_token_secret, which seems strange but not outside of the spec). When I make an API call to another endpoint, I get a 401 (not authenticated). I've tried using header authentication and/or passing the oauth_token and oauth_token_secret as HTTP params with the sane result.
Here's the code:
account_name_url = 'https://api.bitbucket.org/1.0/user'
feedback_oauth_hook = OAuthHook(
access_token='REDACTED',
access_token_secret='ALSO_REDACTED',
consumer_key=CLIENT_ID,
consumer_secret=CLIENT_SECRET,
header_auth=True
)
params = {
'access_token': auth_tokens['access_token'],
'access_token_secret': auth_tokens['access_secret']
}
response = requests.get(account_name_url, data=params, hooks={'pre_request': feedback_oauth_hook})

import oauth2 #pip install oauth2
accessToken = oauth2.Token(OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
consumer_key = YOUR_COMSUMER_KEY
consumer_secret = YOUR_CONSUMER_SECRET
consumer = oauth2.Consumer(consumer_key, consumer_secret)
client = oauth2.Client(consumer, accessToken)
api_url = "https://api.bitbucket.org/1.0/user"
resp, content = client.request(api_url, "GET")
print resp, content
The above python code works for me.
I print the request info, notice that it contains oauth_version=1.0 which is required.
I tried removing it, then 401 was returned. I think BitBucket should document this.

Related

Google OAUTH using django get access token

I'm struggling to retrieve access token using django.
I want to get access token from users using oAuth.
This is what I have setup so far.
class GoogleExhangeViewSet(viewsets.ViewSet):
queryset = User.objects.all()
#list_route(
methods=["GET"])
def auth(self,request,pk=None):
client_id = ''
client_secret = ''
flow = OAuth2WebServerFlow(client_id=client_id,
client_secret=client_secret,
scope='https://www.googleapis.com/auth/calendar',
redirect_uri='http://localhost:8001/api/googleAuth/complete')
auth_uri = flow.step1_get_authorize_url()
return HttpResponseRedirect(auth_uri)
def complete(self, request, pk=None):
client_id = ''
client_secret = ''
host = Site.objects.get_current().name
flow = OAuth2WebServerFlow(client_id=client_id,
client_secret=client_secret,
scope='https://www.googleapis.com/auth/calendar',
redirect_uri='http://localhost')
credentials = flow.step2_exchange(request.GET.get('code'))
return Response(status=200,data=credentials.access_token)
under urls.py I have
api_router.register(r'api/googleAuth', GoogleExhangeViewSet)
This is the error I get with the following code
As seen in your error, you are encountering a redirect_uri_mismatchBad Request if you are using a wrong redirect uri. From this link, the redirect_uri_mismatch will be thrown if it was not matched between auth and token requests.
Additional references:
Google oAuth2 redirect_uri_mismatch in token access
Google OAuth 2.0 redirect_uri_mismatch error
Here's a tutorial if you want to use an Access Token to authenticate users against Django’s authentication system.
You need a fully-functional OAuth2 provider which is able to release access tokens: just follow the steps in the part 1 of the tutorial. To enable OAuth2 token authentication you need a middleware that checks for tokens inside requests and a custom authentication backend which takes care of token verification.

OAuth1 Authentication in RestSharp for Twitter API GET and POST methods

Using Postman I'm successfully able to query and create tailored audiences using the Twitter API, using Postman's OAuth 1.0 Authorization. However when trying to do the same with RestSharp I get an Unauthorized error.
"UNAUTHORIZED_ACCESS" - "This request is not properly authenticated".
My GET request authenticates fine, but the POST request fails.
_twitterRestClient = new RestClient("https://ads-api.twitter.com/1")
{
Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, AccessToken, AccessSecret)
};
var restRequest1 = new RestRequest(string.Format("/accounts/{0}/tailored_audiences", TwitterAccountId), Method.GET);
//this works and gives me a list of my tailored audiences
var response1 = _twitterRestClient.Execute(restRequest1);
var restRequest2 = new RestRequest(string.Format("/accounts/{0}/tailored_audiences?name=SampleAudience2&list_type=EMAIL", TwitterAccountId), Method.POST);
// this results in an "Unauthorized" status code , and the message {\"code\":\"UNAUTHORIZED_ACCESS\",\"message\":\"This request is not properly authenticated\"}
var response2 = _twitterRestClient.Execute(restRequest2);
Turns out this is due to a quirk in RestSharp OAuth1 implementation. I think its related to this issue - https://www.bountysource.com/issues/30416961-oauth1-not-specifing-parameter-type . Part of creating an OAuth1 signature involves gathering all the parameters in the request and other details and then hashing it all. It looks like when the HTTP Method is a POST, then RestSharp is not expecting parameters in the querystring (which makes sense), its expecting them in the post body. Anyhow if you add parameters explicitly then they are picked up and the OAuth1 signing works. (Turns out the twitter API works if these params are in the post body, so I didn't need to explicitly add them to the query string). Updated code that now works:
_twitterRestClient = new RestClient("https://ads-api.twitter.com/1")
{
Authenticator = OAuth1Authenticator.ForProtectedResource(ConsumerKey, ConsumerSecret, AccessToken, AccessSecret)
};
var restRequest1 = new RestRequest(string.Format("/accounts/{0}/tailored_audiences", TwitterAccountId), Method.GET);
var response1 = _twitterRestClient.Execute(restRequest1);
var restRequest2 = new RestRequest(string.Format("/accounts/{0}/tailored_audiences", TwitterAccountId), Method.POST);
restRequest2.AddParameter("name", "SampleAudience2");
restRequest2.AddParameter("list_type", "EMAIL");
var response2 = _twitterRestClient.Execute(restRequest2);

How do I sign access token request withings oauth 1.0

I am currently working on connecting the withings api via web and have been able to automate getting token secret and getting the userId from the callback function inside auth, however when trying to implement step 3 (generating token) I always get signing error. Here is the base logic please help if possible.
nonce = getNonce(32);
date = Math.round((new Date()).getTime() / 1000.0);
var requestSig = oauthSign.hmacsign(
'GET',
'https://oauth.withings.com/account/access_token',
{oauth_consumer_key: <myconsumerkey>,
oauth_nonce: nonce,
oauth_signature_method: 'HMAC-SHA1',
oauth_timestamp: date.toString(),
oauth_token: oauth_token,
oauth_version: '1.0'
}, newSecret);
var hey = encodeURIComponent(requestSig);
var permanentTokensLink = "https://oauth.withings.com/account/access_token?oauth_consumer_key=<myconsumerkey>&oauth_nonce="+nonce+"&oauth_signature="+hey+"&oauth_signature_method=HMAC-SHA1&oauth_timestamp="+date+"&oauth_token="+oauth_token+"&oauth_version=1.0";
return {link:permanentTokensLink, newSecret: newSecret, tokensecret: oauth_token_secret, dataObj: dataObj, token: oauth_token};
newSecrect is a consumersercret&tokensecret, and permanentTokensLink is where I should be able to click to to get the access key and secret. Why is this not working?
I was missing an oauth verifier in the signing params and inside the link I was creating, and the secret should have been broken up into two parts (consumer-secret, token-secret) to be used correctly by the npm package hmacsign.

Issue exchanging LInkedIn javascript token to rest oauth token

I am using the article located at https://developer-programs.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens to exchange my Javascript access token to a REST OAuth token.
After following the directions here, no matter what I seem to do, I only get a 400 Bad Request response back.
The flow I use for Facebook and want to recreate with LinkedIn is; front end authenticates to LinkedIn and passes an access token to my API, the API then gets all necessary user information and passes my own bearer token back to the client, et voila.
Unfortunately LinkedIn doesn't play so nicely with this, and I need to convert my token to an OAuth token from its Javascript token.
I pass the cookie LinkedIn gives me to my API, it looks something like the below (where OAuthBase is http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs)
access_token: "oxmKI9aU4RCfksdegZ3obZGHK-vo6Q4-4FSQk"
member_id: "AmjWCF7ExN"
signature: "t8KEbLjJ+r6uM42tUwfJm5yWp70="
signature_method: "HMAC-SHA1"
signature_order: ["access_token","member_id"]
signature_version: "1"
I then am attempting to make a call to https://api.linkedin.com/uas/oauth/accessToken to do the actual exchange. My code for this is:
public async Task<IHttpActionResult> ConvertLinkedInToken(LinkedInCovertTokenObject val)
{
string normalizeduri;
string normalizedparams;
OAuthBase o = new OAuthBase();
string signature = o.GenerateSignature(new Uri("https://api.linkedin.com/uas/oauth/accessToken"), Startup.linkedInAuthOptions.ClientId, Startup.linkedInAuthOptions.ClientSecret, val.access_token, null, "POST", o.GenerateTimeStamp(), o.GenerateNonce(), out normalizeduri, out normalizedparams);
var client = new HttpClient();
var uri = new Uri("https://api.linkedin.com/uas/oauth/accessToken?" +
"oauth_consumer_key=" + Startup.linkedInAuthOptions.ClientId +
"&xoauth_oauth2_access_token=" + val.access_token +
"&signature_method=HMAC-SHA1" +
"&signature=" + signature
);
var response = await client.GetAsync(uri);
return Ok();
}
No matter how I play around all I get back from LinkedIn is a 400 Bad Request without any other useful information.
1) How can I convert LinkedIn JS token to Rest OAuth token in my c# api
This is how I achieved that:
On the frontend:
IN.User.authorize(function(){
// here you can find oauth token
var oauth_token = IN.ENV.auth.oauth_token;
// send this token to your API endpoint
});
On your API (curl example), of course replace OAUTH_TOKEN with token received on the frontend.
curl -X GET \
'https://api.linkedin.com/v1/people/~:
(id,firstName,lastName,siteStandardProfileRequest,picture-url,email-
address)?format=json' \
-H 'oauth_token: OAUTH_TOKEN'
You are looking at old documentation from LinkedIn. Starting from 12th May, LinkedIn has started rolling out new changes in their API which includes authentication. In my knowledge, LinkedIn is not using OAuth anymore, and you need OAuth2.0 henceforth for authentication. You should check this link for more information:
https://developer.linkedin.com/docs/signin-with-linkedin

how to get user information from Withings api on grails

I'm trying to get user information from Withings Api, i've already success login into Withings with Oauth using Scribe library(Java). But there is a problem when i sent request to get user information follow Withings Api document it always return result with error code.
I've tried some way but it didn't work. Can someone help me to solve this problem.
Withings Api http://www.withings.com/en/api#documentation
First i call withings action in WithingsController.groovy to get authentication.
After authenticate success server return access token, in withingsCallback action i get user information.
Result return when get user information is result code of Withings Api
{"status":2554}
This is my code
WithingsService.groovy
def getAuthDetails(callbackUrl) {
if (!authService) {
authService = new ServiceBuilder()
.provider(WithingsApi.class)
.apiKey( grailsApplication.config.oauth.withings.key as String )
.apiSecret( grailsApplication.config.oauth.withings.secret as String )
.callback( callbackUrl as String )
.build();
}
Token requestToken = authService.getRequestToken();
[ authUrl : authService.getAuthorizationUrl(requestToken), requestToken : requestToken ]
}
def getWithingsUserInformation(Token accessToken,String userId){
String url = 'http://wbsapi.withings.net/user?action=getbyuserid&userid='+userId;
OAuthRequest request = new OAuthRequest( Verb.POST, url )
authService.signRequest(accessToken, request)
Response response = request.send()
return response
}
def getAccessToken( params, requestToken ){
requestToken = requestToken as Token
Verifier verifier = new Verifier( params.oauth_verifier )
authService.getAccessToken(requestToken, verifier);
}
WithingsController.groovy
def withings() {
def authInfo = withingsService.getAuthDetails(createLink(action: 'withingsCallback', controller: 'withings', absolute: 'true'))
if (authInfo.requestToken)
{
session["withings_requestToken"] = authInfo.requestToken
}
}
def withingsCallback(){
def accessToken = withingsService.getAccessToken(params, session["withings_requestToken"])
session["withings_accessToken"] = accessToken
if(accessToken) {
def profile
String userId = params.userid
profile = withingsService.getWithingsUserInformation(accessToken,userId)
}
}
Unless I'm missing something, it looks like you are not redirecting your user to get the "access token". After you get a request token:
you then generate a authentication url
redirect the user to this authentication url
they will authenticate
if authentication is successful, provider will call your callback with access token
So your withings action should include:
def withings() {
def authInfo = withingsService.getAuthDetails(createLink(action: ....
if (authInfo.requestToken)
{
session["withings_requestToken"] = authInfo.requestToken
}
//are you missing this?
redirect(authInfo.authUrl)
}
If you're using some type of http debugging/logging, check for the following request after your withings action.
https://oauth.withings.com/account/authorize?
oauth_callback=http%3A%2F%2Fexample.com%2Fget_access_token
&oauth_consumer_key=c331c571585e7c518c78656f41582e96fc1c2b926cf77648223dd76424b52b
&oauth_nonce=369f9ceb2f285ac637c9a7e9e98019bd
&oauth_signature=OR9J9iEl%2F2yGOXP2wk5c2%2BWtYvU%3D
&oauth_signature_method=HMAC-SHA1
&oauth_timestamp=1311778988
&oauth_token=5bb105d2292ff43ec9c0f633fee9033045ed4643e9871b80ce586dc1bf945
&oauth_version=1.0
Though this is unrelated to the question initially asked, I thought I would post here since this was a common stopping ground for me reaching a Withings 2554 error.
If updating to the newest version of Withings Api for access token authentication, the current version of the Withings Api will now also cause this 2554 status code if you do not attach action: requesttoken to the access token request body.
Additionally, when pulling apart the response, make sure to drill into the body of the payload, since the latest version of the Withings access token api delivers its payload contents differently. This may be a no brainer for those implementing from scratch, but if you are using an oauth library, most of this behavior is abstracted by the library, and it likely won't be anticipating the payload structure to contain the body field.
more info here: https://developer.withings.com/api-reference#operation/oauth2-getaccesstoken

Resources