question

shaqspeare avatar image
shaqspeare asked

Verifying access tokens obtained via Implicit Grant over CORS

[On behalf of: init_js] The developer manual for Login with Amazon explains that the implicit grant method is to be chosen if server-side scripting is not possible. Specifically: "The advantage of the implicit grant is that it is relatively simple to implement, as it relies on the web browser to receive and store the access token. If the client architecture does not support server-side scripting, this is the only authorization grant that will work with the Login with Amazon authorization service." With this method, the client website is responsible for verifying that access tokens received are indeed coming from the same client application by doing a cliend id comparison (because the tokens are passed inside redirected URIs). The manual describes the verification API on page 20: GET https://api.amazon.com/auth/O2/tokeninfo?access_token=XXXXX However this REST call cannot be made without server-side scripting, because it does not support cross-origin-resource-sharing (CORS), based on small experiments. Is there a different way of invoking that API, e.g. through a postMessage interface, or turning on different parameters to enable CORS? I would expect it to be okay to add the grant audience's origin as one of the Access-Control-Allow-Origin.
login with amazon
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

shaqspeare avatar image
shaqspeare answered
Hi, To make sure I'm on the same page, are you using the Login with Amazon SDK for JavaScript to obtain the access token? Or are you obtaining access tokens via other means, e.g. parsing the access token from a query param in a redirect from Login with Amazon?
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

shaqspeare avatar image
shaqspeare answered
[On behalf of: init_js] Here's the flow I'm using. Steps 1 to 3 are taken directly from the Login with Amazon "Getting Started Guide": 0. User visits app at https://myapp.tld/index.html 1. User press the "Login with Amazon" yellow button 2. User logs in with the popup window served by amazon.com 3. After successful login, the user's browser is redirected to: https://myapp.tld/logged-in.html?scope=profile&...&access_token=blah 4. Client side javascript code in logged-in.html grabs the info from the query parameters, and tries to verify them using the documented APIs by issuing ajax calls: 4a) https://api.amazon.com/auth/O2/tokeninfo?access_token=foo for the token itself nor 4b) https://api.amazon.com/user/profile?access_token=foo to read the profile info The problem I'm hitting is that neither of 4a or 4b can be done from myapp.tld due to cross origin violations. My end goal is to convert the access_token into temporary IAM credentials with http://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html and then using CORS requests to play with an S3 bucket, all from client side javascript. Edited by: init_js on Aug 7, 2013 9:22 PM
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

shaqspeare avatar image
shaqspeare answered
For (4a), you do not have to make the call to validate the token since you are completely client-side. The tokeninfo call is useful in the scenario where the client website accepts any arbitrary access token as a query parameter and then needs to verify that the token belongs to the expected client ID. For (4b), instead of making the request for profile information yourself, you may use the retrieveProfile function built into the Login with Amazon SDK for JavaScript. It takes in the access token and a callback function. Here is an example usage: amazon.Login.authorize(options, function (response) { if (response.error) { alert('oauth error ' + response.error); return; } amazon.Login.retrieveProfile(response.access_token, function (response) { console.log(response.profile.PrimaryEmail); console.log(response.profile.Name); console.log(response.profile.CustomerId); }); }); Let me know if this helps.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

shaqspeare avatar image
shaqspeare answered
[On behalf of: init_js] This works as expected and allows me to retrieve a token completely client-side. Got it. I thought the second parameter to amazon.Login.authorize had to be a URL. Is there other documentation on this aside from what can be found by reverse engineering the minified login1.js file? To determine whether the access token has expired or is still valid (for instance on a page refresh), are client-side applications expected to cache tokens (e.g. localstorage) and then call retrieveProfile during page initialization to test validity of the cached credentials? Edited by: init_js on Aug 12, 2013 2:46 PM
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

shaqspeare avatar image
shaqspeare answered
Hi init_js, At this time, there is not external documentation for the JavaScript in question. And yes, client-side applications can store the access_token locally. When you receive the access token, the response include an "expires_in" field, which can be used to proactively refresh the access token before it expires, if you wish. Otherwise, you'll need to be sure to include error handling in your call to retrieveProfile() when the access token is expired.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

shaqspeare avatar image
shaqspeare answered
[On behalf of: init_js] I don't think that was there when I initially posted, but it would seem a new document appeared in the last few days on the Login With Amazon webpage's Documentation tab. Those steps above are explained there in "SDK for JavaScript Reference".
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.