MapMyFitness API OAuth questions - ios

I am having some issues with MapMyFitness API. MapMyFitness uses OAuth 1.0
I am able to successfully get a temporary Authorization token/temporary secret Token combination from calling 3.1/oauth/request_token
After that, I am able to successfully direct the user to the Authorization page and get a redirect callback with a authorization verifier.
After that, I am, unfortunately, getting errors when trying to call 3.1/oauth/access_token. (HTTP error 401)
First of all, MMF documentation (http://api.mapmyfitness.com/3.1/oauth/access_token?doc) states: Exchange a request token and an authorization verifier for an access token. However, the list of input arguments in the documentation contains no mention of oauth_verifier. Should oauth_verifier that I have received with the redirect callback be passed to access_token call as an argument?
Secondly, it appears to me that perhaps I am not creating the signature correctly. For the 3.1/oauth/request_token call the key to generate the signature is 'XXX&' where XXX is the Consumer Secret Key assigned to my app by MapMyFitness. This works fine. For the 3.1/oauth/access_token call, I am using 'XXX&YYY' as a signature key where XXX is the Consumer Secret Key assigned to my app by MapMyFitness and YYY is the temporary Secret Token returned to me by the server during the 3.1/oauth/request_token call. Is that correct?
I would greatly appreciate any suggestions.

OK, I got it working. First of all, oauth_verifier DOES need to be included as part of parameters. For some reason, Map My Fitness does not include it in its list of required parameters, but it has to be there. Secondly - very important - according to OAuth 1.0 documentation, all parameters need to be in alphabetical order when creating the signature - otherwise there will be a signature mismatch and you'll get HTTP 401 error. Once I sorted my parameters in alphabetical order, I was able to exchange temporary MapMyFitness credentials to permanent ones.

Related

ETrade api - invalid Consumer key and/or session token

When I attempt to make a request to Etrade's Account List endpoint in sandbox (https://apisb.etrade.com/v1/accounts/list), I am getting an HTTP 401 - "Unauthorized request - invalid Consumer key and/or session token".
I don't understand why this request is not working, since I am successfully calling the Get Access Token API, retrieving the oauth_token and oauth_token_secret and using them to sign and make the request to Account List.
To add to my confusion, I downloaded the official Etrade Python Client, put a breakpoint right before the account list is called, and confirmed that my code is generating the exact same oauth_signature given the same request parameters.
Furthermore, I actually copied all of the request parameters generated by the official Python client and pasted them into my web browser, and am still getting the same "Unauthorized request - invalid Consumer key and/or session token" response.
To illustrate, here is a breakpoint I put in the official Python client (I've replaced the first four letters of sensitive keys with "123a"):
Breakpoint 1 at /Users/me/Downloads/EtradePythonClient/venv/lib/python3.9/site-packages/rauth/session.py:210
(Pdb) c
> /Users/me/Downloads/EtradePythonClient/venv/lib/python3.9/site-packages/rauth/session.py(210)request()
-> return super(OAuth1Session, self).request(method, url, **req_kwargs)
(Pdb) pprint.pprint(oauth_params)
{'oauth_consumer_key': '123a01814e407344bc2b385f3954679b',
'oauth_nonce': '8230791e8c0253518a6b2dec8120b643fde93745',
'oauth_signature': '123apxtEaUJmlvKFWv7zz+lfNk4=',
'oauth_signature_method': 'HMAC-SHA1',
'oauth_timestamp': 1614559929,
'oauth_token': '123aMSpwaaWItBDgXQ/Te4M9363WSULWFdeHkh18B8s=',
'oauth_version': '1.0'}
(Pdb) url
'https://apisb.etrade.com/v1/accounts/list.json'
(Pdb) method
'GET'
Using the above, I constructed the following URL and pasted it into my web browser:
https://apisb.etrade.com/v1/accounts/list.json?oauth_consumer_key=123a01814e407344bc2b385f3954679b&oauth_nonce=8230791e8c0253518a6b2dec8120b643fde93745&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1614559929&oauth_token=123aMSpwaaWItBDgXQ/Te4M9363WSULWFdeHkh18B8s=&oauth_version=1.0&oauth_signature=123apxtEaUJmlvKFWv7zz+lfNk4=
but I get an HTTP 401 response - "Unauthorized request - invalid Consumer key and/or session token".
And yet, the request works in the official Python client (as long as I don't try it in my browser first, otherwise I will get a 'Error: oauth_problem=nonce_used' error in the Python client).
One thing I noticed is that the official Python client adds the oauth_version=1.0 parameter, but my requests are still failing whether or not I include that parameter and sign with it.
I also noticed the official Python client adds a .json to the url, but again I am still getting the unauthorized error whether or not I include .json.
I've also tried sending the OAuth parameters as an HTTP Header instead of as URL parameters, but I still get the same error.
I'm also rfc3986-encoding (percent-encoding) the URL parameters in my request, which is working for the Get Access Token request but not the Account List request.
Note that I am using the following URLs for request token, access token, and API for sandbox:
https://apisb.etrade.com/oauth/request_token
https://us.etrade.com/e/t/etws/authorize?key=${oauth_consumer_key}&token=${state.oauth_token}
https://apisb.etrade.com/oauth/access_token
https://apisb.etrade.com/v1/accounts/list
What else I can try to debug this?
Figured it out:
The problem was that, since I'm sending my requests from a web browser (a Chrome extension), my request was including a Cookie, which was causing the API to produce a session error.
I am using the Fetch API.
Setting {"credentials": "omit"} in the init parameter omits the Cookie header and solves the issue.

How to request access token from Battle.net OAuth with authorization code?

I have a hobby project in mind to use battle.net login. I'm wondering how I can obtain the access token from the API after receiving the authorization code.
This is Oauth flow question rather than a battle.net question.
Currently I can successfully authorize the user for my app which is registered in dev.battle.net and then I try to use the authorization code returned from the battle.net login to obtain the access token by sending a request to https://<region>.battle.net/oauth/token.
However I keep receiving this error:
{
"error": "unauthorized",
"error_description": "An Authentication object was not found in the SecurityContext"
}
I use postman extension to send post requests to that uri. I authenticate my request with my client id and secret. I pass redirect_uri (https://localhost), granty_type (authorization_code), code(the code returned from the previous authorization step). However I keep getting the error above.
I couldn't find much about battle.net online. There are other oauth related help articles but couldn't really find my way.
Wondering if you can help me with this easy stuff. I'm just wondering what I'm skipping here.
Here is the documentation:
https://dev.battle.net/docs/read/oauth
https://localhost is added in my mashery dev account's app settings.
Me again, I resolved this problem after trying almost every combination in the universe:)
Steps to apply:
Don't use the same authorization token for different access token trials, they are not valid
Always use https on every domain you test including localhost, you
redirect_uri must be https as well.
You must use the "basic authentication" in the header of your POST request while requesting the token from the authorization code you obtained from the previous step.
This is one of the most important ones: For requesting token, Pass redirect_uri, client key and secret as POST form parameters to the authenticated request. This is interesting because it's already an authenticated request; why would i need to pass my secret again? Anyways, that's how it works.
Here are the full text:
http://hakanu.net/oauth/2017/01/26/complete-guide-of-battle-net-oauth-api-and-login-button/
This is working prototype:
https://owmatch.me
Thanks.

Google's OpenID Connect says: OAuth 2 parameters can only have a single value: client_id

As part of the OpenID Connect (OAuth2 for Login), my application is supposed to request an access token, given a one-time authorization code, via the endpoint https://www.googleapis.com/oauth2/v3/token. According to documentation, this request needs 5 parameters passed to it, client_id among them. That is exactly what my application does, using the Perl module Net::OAuth2.
Everything has been working fine for several months, but today I was notified that it stopped working. No updates were made to the application code nor the libraries used by it.
The message my application now receives from the server when calling the token endpoint is this, in a 400 error response:
OAuth 2 parameters can only have a single value: client_id
A Google search suggests nobody has ever seen this message before, or lived to tell the tale. There doesn't seem to be a general issue with Google's OpenID Connect (other services based on it are working flawlessly), and the imminent shutdown of the old login protocol doesn't seem relevant.
More testing: removing all parameters except client_id causes this error message:
Required parameter is missing: grant_type
Supplying only client_id and grant_type produces the original error message again.
Does anyone have an idea what's going on here?
Google changed this behavior few days ago, so any OAuth2 library using Basic Auth headers AND body request parameters will start to see messages like
OAuth 2 parameters can only have a single value: client_id
or
OAuth 2 parameters can only have a single value: client_secret
So, you must now do NOT use both (the Auth headers and body request parameters) at the same time to send credentials to Google.
And according RFC 6749, the preferable way to send credentials is through Auth headers (thanks #JanKrüger for alert me about this).
Got the same error. It seems the problem is that NET::OAuth2 sets the authorization header when exchanging authorization code for access token. If you remove this header everything works fine.
Check the get_access_token method in Net::OAuth2::Profile::WebServer module. The authorization header includes client_id:client_secret base64-encoded string. Apparently Google now treats this duplication as an error.
The right way of fixing this is to set the secrets_in_params parameter when creating Net::OAuth2::Profile::WebServer object. Look in the Net::OAuth2::Profile documentation for more details.

LinkedIn API: The token used in the OAuth request has been revoked

I am getting the following error when I use the linkedin V1 API:
response body: {
"errorCode": 0,
"message": "[unauthorized]. The token used in the OAuth request has been revoked. 75--5cfb9cdb-3c9c-47c2-b3f8-XXXXXXXX",
"requestId": "I2GQ0ZMWIE",
"status": 401,
"timestamp": 1408976297742
}
I am using this guide here, I am doing exactly what this person is doing but I get a different result:
https://github.com/PrincessPolymath/LinkedIn-OAuth-Sample-Client
I have no idea why I get The token used in the OAuth request has been revoked. for an error. The HTTP request is identical. Could it be something with my bundle ID?
I cannot find anything from linkedin on the matter. Why don't linkedin have normal error-code lookups like other API's.
Here are some photos of the two request objects, one from the example and one from mine.
I'm taking a guess here based on my understanding of the problem you're describing, have not tested this. I'm also assuming you got your credentials right...
You should checkout this answer by Kamyar Mohager (#39), he explains how to bypass this error:
When obtaining access token, error occurs if:
POST https://www.linkedin.com/uas/oauth2/accessToken
Body:
{
grant_type=authorization_code,
code={auth-code},
redirect_uri={uri},
client_id={id},
client_secret={secret}
}
The error WON'T occur if you obtain the access token by passing the params as query params:
POST https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code&code={auth-code}&redirect_uri={uri}&client_id={id}&client_secret={secret}
Error clearly states that the user is authorized to make a call using the token which you are using.
"message": "[unauthorized]. The token used in the OAuth request has been revoked. 75--5cfb9cdb-3c9c-47c2-b3f8-XXXXXXXX",
In the two photos which you pasted above I can see that your request object has different values "tokenKey and tokenSecret" parameters than the example request object, which is correct as your request should have the token information which received from LinkedIn.
But the thing which I don't understand is why both the request objects have same values for "consumeKey & consumerSecret" parameters. I think you need to use your "consumerKey & consumerSecret" with your "tokenkey & tokensecret" to make this OAuth call. "consumer" and "token" detail combination should match then only you will be allowed to make the successful oauth call.
I guess you saw this error because you used your token with some other consumer key.
One more thing I can see that you are passing the "verifier" in your request object hence I want to know are you making a call to get the "access token" which is a 3rd leg of oauth. If yes then there could be scenario that "requestToken" is getting expired before you are making this "access_token" call as "requestToken" is actually a "temporary token" and expires quickly.
HTH...
The issue was code re-use.
As stated in the comments for the API, the API will give you a token and secret upon the first request. This only happens during authentication and then the token and secret can basically be thrown away, and the one issues at developer.linkedin can be used.
I fixed this by constructing my own request object rather than relying on the old HTTPRequestBody in the oAuth process.

OAuth 2.0 for MVC - How does the RequestToken work?

I'm working with OAuth 2.0 for MVC, found here: http://community.codesmithtools.com/CodeSmith_Community/b/tdupont/archive/2011/03/18/oauth-2-0-for-mvc-two-legged-implementation.aspx
For anyone who's worked with this - I'm confused about the RequestToken. There is a controller implemented that lets you get a request token, which expires in 5 minutes, and you pass that token back in to get an AccessToken. But it never checks the request token for validity - it seems like you can pass in any access token you want to. What is the idea for the RequestToken here - are you supposed to create your own method of storing, referencing, and then deleting that token for those 5 minutes?
Thanks,
Andy
This is all about how OAuth works in conjunction with your application Id, application secret key and valid domains for your application. Here is the process in general
Your application sends a request to the OAuth provider using your application Id and secret along with a callback (return Url).
The OAuth provider gets the request, checks your application Id and secret and validates that the callback url is from a domain that you have specified for your application.
2a. If the callback url is not from a domain that you have specified, then the request is rejected with error.
2b If the callback url is from your domain, it returns a temporary request key to your server.
Given that you received a request key, you send that back to the OAuth provider to get the actual access token for the user.
Now, as to why the request key step is in place, this is to prevent and help protect 'bad people' from attempting to use your application id to falsely authenticate other users. By sending the request token to you (a callback URL that you have approved), the OAuth provider has confidence that the request actually came from your servers.
You most certainly could send any string back instead of the request token, but you would quickly get an error back from the OAuth provider as that request token does not correspond to any existing authentication request from any known application.
Lastly, I am not clear on what you mean by 'validating the request token'? You did not generate the token not probably do not have insight into the algorithm to generate the request token. Given that, I am not sure how you would validate this. If you are concerned about validating the first step, take a look at the Facebook OAuth process. In there, they recommend sending a request key as part of your return Url(as a query string parameter). That request key will come back to your application which you could then use as a validation that, indeed, this is a response to a request that you made. How you store and track that request key is up to you (session, database). In the PHP samples, they use a 'state' variable to track a unique/arbitrary string: Facebook OAuth Server Side Login Example (in PHP)

Resources