I'm pretty familiar with restAPIs, however this one is giving me a bit of a headache. I'm trying to migrate my OAuth 1.0 tokens into OAuth 2.0 tokens using this documentation https://developer.xero.com/documentation/oauth2/migrate.
The request:
POST https://api.xero.com/oauth/migrate
Content-Type: application/json
Authorization: OAuth oauth_consumer_key="your_consumer_key", oauth_token="your_access_token",
oauth_signature_method="RSA-SHA1", oauth_signature="your_signature", oauth_timestamp="1456175435",
oauth_nonce="83fd12eb-f578-4403-bd55-247b66efa11a", oauth_version="1.0"
Body: {
"scope":"your_oauth_2_scopes + offline_access",
"client_id":"your_app_client_id",
"client_secret":"your_app_client_secret"
}
I'm trying to write a script in GO that will make make the POST request, grab the data and update our database.
Now what I'm confused about is the Authorization Header.
How do I fill in the information required?
More specifically the oauth-signature, oauth-timestamp and oauth_nonce. I have little experience working with OAuth1.0a and would love to understand the flow.
Thanks!
Edit: trying to make use of this library https://godoc.org/github.com/gomodule/oauth1/oauth#example-Client-SetAuthorizationHeader
The OAuth1.0a signature is a set of key-value pairs, signed with your private key. This example migration app should give you an idea of the steps that need to be taken to build up the signature, even though it's not Go: OAuth1.0a => OAuth 2 token migration example.
There's also a Xero GoLang SDK that you can dig into to help with auth code: xerogolang
The nonce is a random single-use string that needs to be the same in your header and in the signature. The timestamp is the current date-time, in seconds since epoch, which also needs to be the same in your header and in the signature.
Related
I'm following step by step guide on Microsoft's site (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#refresh-the-access-token), everything is working correctly but every time I try to refresh the access token, I get this error: AADSTS70000: Provided grant is invalid or malformed. error_codes: 70000.
I've created a Postman collection for testing, also downloaded the official postman collection from the Microsoft's site, everything is working correctly until the access token does not expire. When it expire, trying to refresh the token always lead to an error and I'm pretty stuck with it. I've double and triple checked correspondence between redirect_url, permission, grant, copy/paste errors, waited for the access_token to expire before trying to refresh... I've done almost 100 tests, and every time I'm stuck at the refresh part!
I start with doing the normal call to Microsoft Login API in my browser, and getting the code in query string from the browser (no problems here) (please note that client_id is URL encoded because, in my test environment, client id is an URL due to the configuration of the Drupal portan we're using, I'm truing to recreate the same behaviour in postman)
https://login.microsoftonline.com/{tenant_guid}/oauth2/v2.0/authorize?client_id={myclient_id_urlencoded}&response_type=code&redirect_uri={redirect_uri_urlencoded}&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fuser.read&state=12345
Then with the code in query string, i POST to the token endpoint:
POST /{tenant_guid}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-url-form-urlencoded
cache-control: no-cache
Postman-Token: a0456a8d-6979-491f-b61e-86b5d614c577
client_id={myclient_id_urlencoded}
scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
redirect_uri={redirect_uri_urlencoded}
grant_type=authorization_code
client_secret={client_secret_urlencoded}
code=OAQABAAIAAADCoMpjJXrxTq9VG9te-7FXujKZhF...
I receive back an accesso token (that is working like a charm in accessing https://graph.microsoft.com/v1.0/me for an hour) and a refresh token. I would love to get a new pair of access/refresh token when the original access token expires, using the refresh_token grant_type
POST /tenant_guid/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-url-form-urlencoded
cache-control: no-cache
Postman-Token: 5d71f813-768e-476c-a97f-c109fba3165e
client_id={myclient_id_urlencoded}
scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read
redirect_uri={redirect_uri_urlencoded}
grant_type=refresh_token
cclient_secret={client_secret_urlencoded}
refresh_token=OAQABAAAAAADCoMpjJXrxTq9VG9te-7FX8m6YMg-.....
But no matter if I try before access token expiration or after, closing and reopening postman, I always receive that error back. I've done almost 50 tests (always with the full round of login/authorization to use always a fresh refresh token) with no luck.
Seems like I'm missing something really stupid here because I can't imagine that everybody else is behaving correctly... but really can't find a way out!
So I just got mine working! Here are the required parameters I needed:
client_id = your client id
refresh_token = the refresh token here
grant_type = refresh_token,
client_secret = secret
NOTE: Everything I read told me to URLEncode the values. I found it worked with them UNENCODED - no idea if it will really make a difference or not. Since it is going in the body of the post, which means it is TLS encrypted.
The other important thing was the url I posted to. There seem to be so many examples and none seem to be consistent. I used this format:
https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
The last thing is to be sure you are using the correct app id. In my case I was using the appId for the wrong app and it didnt have consent. Hope this helps. I do wish Microsoft would make a concerted effort to spell out things consistently and think like someone who doesn't do security for a living.
Finally resolved thanks yo the Azure Support.
The problem is the client id: as I supposed before, Microsoft allow you to define another application name, but always want to use the GUID client id to submit any request. Unfortunately, it was warning me when I didn't url-encoded it, but did not alert me that it was not correct until I tried to use the refresh token.
So just read very very well the documentation: client_id: The Application (client) ID that the Azure portal – App registrations experience assigned to your app (so not the one you choose).
https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow
Maybe including a format validation in the documentation would help!
When I try to access rest API using iPhone I have passed following parameter in URL and used both methods POST and GET but it displays Access Denied.
oauth_version="1.0",
oauth_signature_method="HMAC-SHA1",
oauth_nonce="B0dlzkfMWCAn0TJ",
oauth_timestamp="1366280813",
oauth_consumer_key="klkjylsiozbv6vfdsqtuheqo3kmqqzv2",
oauth_token="t9pefrwylmg7webyepsqepotlhzbytkp",
oauth_signature="NeOwbCLUPbIyF9ErnHoFQOl9%2Bwo%3D"
I have worked with REST Client plugin available for Firefox and Chrome, REST API is work well using REST Client plugin but not accessible in iPhone.
I am generating a random value for oauth_timestamp, oauth_signature and oauth_nonce then also REST API is displaying Access Denied.
Please provide suggestions.
//here final_sign is signature generated from following procedure.
$nonce = substr(md5(uniqid('nonce_', true)),0,16);
$temprealm="http://magentohost/api/rest/products";
$realm=urlencode($temprealm);
$oauth_version="1.0";
$oauth_signature_method="HMAC-SHA1";
$oauth_consumer_key="dfddfgdgdfgddf6qgygmyvw7e3";
$oauth_access_token="fdgdfgfdgdfg357gimpdnuejvcbtk51ni";
$oauth_method="GET";
$oauth_timestamp=time();
$algo="sha1";
$key="sb88hfdihyg25ipt1by559yzbj2m3861&s7uhaheu8nrx961oxg6uc3os4zgyc2tm"; //consumer secret & token secret //Both are used in generate signature
$data="oauth_consumer_key=".$oauth_consumer_key."&oauth_nonce=".$nonce."&oauth_signature_method=".$oauth_signature_method."&oauth_timestamp=".$oauth_timestamp."&oauth_token=".$oauth_access_token."&oauth_version=".$oauth_version;
$send_data=$oauth_method."&".$realm."&".urlencode($data);
$sign=hash_hmac($algo,$send_data,$key,1); // consumer key and token secrat used here
$fin_sign=base64_encode($sign);
echo $fin_sign;
From your question I understand that you use a random value for the signature and the nonce.
The latter would be fine, but a random signature would lead the receiver not to trust you as a legitimate client.
So, actually, you get the response you requested (;-)). But that does not solve your problem.
You have to generate a valid signature for the magento system.
We received a request to create a REST api. I was a little confused in the example of provided by our client. As you can see below, they've identified the app_id and secret in the URL before the #. The remainder of the URI looks like what I would expect.
Is this valid? I thought maybe this is some weird cURL format I haven't seen before.
https://{application_id}:{api_secret}#api.example.com/entity/{entity_id}/
https://{application_id}:{api_secret}#api.example.com/entity/{entity_id}/entity_locations/{locations_id}/
Just seeing if anyone has seen this format before?
A URI is made up of various parts, one of them being the authority part, which can feature optional username:password element.
The full scheme is:
scheme://username:password#domain:port/path?query_string#fragment_id
This way your REST api remains stateless [not relying on previous app states like storing stuff in session]. But I advice you not to explicitly go with the username:password#stuff route, but to rely on Basic HTTP Auth, so the credentials are sent encoded in Base64 at least.
EDIT: a brief note about BasicAuth now you're asking - things go like this:
you make a request to http://johndoe:12345#service/api/foo/bar;
are credentials good? Ok, you get a 200 OK response with proper body;
are they not? You get a 401 Unauthorized response.
In the latter case, it's the browser [or any other program / script performing the request] that should prompt the user with the login popup.
Usually browsers ask you to cache credentials not to ask them every time, but this does not mean that they are not sent - it's just that every request to protected resources are featured with such header:
Authorization Basic base64encode(username:password)
Where base64encode is your custom way to encode the username:password string.
Via the Magento OAuth API i have managed to obtain an access_token and access_token_secret.
The call to acquire these requires a valid signature. Since i'm using the plainOAuth library and I'm able to sign the authorize request valid I'm I suspect the library is not the issue.
Issue:
Once Im making a REST call "test.magentohost.com/api/rest/products" using the tokens and consumer token's, i get the response invalid signature. The sig is signed using consumer/access token secret via the library and (i think) all params are in the header.
I hope anyone can see a mistake in my header, it's driving me nuts!
This is my "Authorization" header.
oauth_realm="",
oauth_timestamp="1340011522",
oauth_nonce="ff5c167677069d9770d5cfc1dba12e0fc1d924f9",
oauth_signature_method="HMAC-SHA1",
oauth_consumer_key="ic88q1nq0iitd9tmowz6bs3dzg2d07ng",
oauth_version="1.0",
oauth_token="uye05e0pb0f8dap1ovglecxoq6ziee35",
oauth_signature="G%2Frl7S%2Bw57pjCk8xk1DMpOLkjxI%3D"
I think there is a bug inside Magento Core. I just filed a bug report here: http://www.magentocommerce.com/bug-tracking/issue?issue=14307 (unfortunately you have to be logged in magento site to see it).
Basically they include clients signature in calculating server signature and then comparing both of them which always fails.
Please let me know how you solved this?
I had this issue and I got working version after make these steps. But before, example request token signature
POST&http%3A%2F%2Fmagento.test.com%2Foauth%2Ftoken%2Frequest%2F&oauth_consumer_key%3Duaa3romggcur5yrjjm85ydiunfxfyuxx%26oauth_nonce%3D1479663271%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1479663271%26oauth_version%3D1.0
Take a note, that between method and url and other params, they use & without apply urlencode. This is for split arguments with params, I think.
During request token we should not put oauth_token into params.
All parameters must be sorted in alphabetical order and the characters must be escaped with function like the urlencode:
this
http%3A%2F%2Fmagento.test.com%2Foauth%2Ftoken%2Frequest%2F
instead this:
http://magento.test.com/oauth/token/request
and this
oauth_consumer_key%3Duaa3romggcur5yrjjm85ydiunfxfyuxx%26oauth_nonce%3D1479663271%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1479663271%26oauth_version%3D1.0
instead this
oauth_consumer_key=uaa3romggcur5yrjjm85ydiunfxfyuxx&oauth_nonce=1479663271&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1479663271&oauth_version=1.0
Im trying to get TripIt OAuth authentication working, but I find the documentation to go a bit over my head. TripIt docs
The paragraph below is from the documentation, I have tried putting together a POST request for a SOAP service where the documentation specified what to put into the headers and how to build an xml for the Http body. In this case I have no idea on how to build my request.
I have all the values the service asks for, just no idea of how to set these using only the info given below?
To obtain an authorized access token,
POST the following request parameters
to the URL:
https://api.tripit.com/oauth/access_token
oauth_consumer_key: The Consumer's public key.
oauth_nonce: A nonce no more than 80 characters in length.
oauth_signature: The signature of the reque…
oauth_signature_method: Current supported methods are HMAC-SHA1.
oauth_timestamp: The timestamp in seconds since the epoch.
oauth_token: The request token obtained in Step 1.
oauth_token_secret: The request token secret obtained in Step 1.
oauth_version: OPTIONAL - Assumed to be '1.0'
Could someone help me with how I'll go about building the POST request from the above?
Thank you:)
The way to do it yourself would be to read up on how the body of a POST request is put together (it looks a lot like a URL query string), build the string out of the various parts, and then use the request's -setHTTPBody: method.
Most people recommend using ASIHTTPRequest, which, among many other things, will do that work for you. See, in particular, the ASIFormDataRequest class, and its -setPostValue:forKey: method.
Here's some more detail on the format of the POST body:
From the W3C HTML4 spec, the section on forms.
The Wikipedia entry on "percent escaping".
From the HTML5 spec draft. These rules should be backwards-compatible, while being more precise than the text in the HTML4 spec, but no promises.