WebAuthenticationBroker in a Universal App with Login With Amazon - amazon-web-services

I'm working on a new Universal App (first time) and I am trying to use Login with Amazon as my authentication provider. Amazon doesn't provide an SDK for .NET for LWA so I'm left trying to figure it out on my own.
Here is what I am doing so far:
var redirectUrl = "https://localhost/";
var baseUrl = "https://amazon.com/ap/oa?client_id=MY_CLIENT_ID&response_type=code&scope=profile";
var uri = new Uri(baseUrl);
var redirectUri = new Uri(redirectUrl);
WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, uri, redirectUri);
This gets me to the login with Amazon page just fine, and allows me to login, but handing off back seems to be a problem.
Any and all help appreciated.

Amazon LWA Developer Guide
Page 25.
As I can see you missed some required parameters - scope and redirest_uri. Specify them properly and probably it will work.
For a Universal App, make sure you enable the Internet Client & Server Capability.

I haven't used WebAuthenticationBroker and you haven't provided the error message you're getting, so I have to do some guessing here...
Scanning the MSDN docs for WebAuthenticationBroker, it looks like it's meant to work with the Implicit grant flow (where an access token is returned after login/consent) vs. the Authorization grant flow (where you get back a code you must then exchange for an access token).
So if it's getting back an Authorization grant response instead of an Implicit grant response, it could be throwing an error because it's missing expected fields.
Try changing your response_type from code to token and see if that helps. If it doesn't, please post some more detail on the error you're getting.

Related

How Do I Use Login With Amazon to Link A User Account to My Skill?

I am having a hard time getting this to work by following along with Amazon's Alexa documentation. I'm running aground on Account Linking because I can't figure out how to get Login with Amazon (LWA) to ask for alexa::skills:account_linking scope.
I've included the Amazon API library in my application and set that all up correctly and I'm invoking the process using the (globally available) amazon object as follows (typescript):
const options: any = {};
options.scope = ['profile', 'alexa::skills:account_linking'];
options.scope_data = {
profile : {essential: false}
};
options.response_type = 'code';
const self = this;
amazon.Login.authorize(options, (response) => {
if (!response || !response.code) {
throw { error: response };
}
// ... send the response code to my server
// ... to be exchanged for bearer and refresh tokens
});
What I would expect to happen from that is a popup Amazon login process to be spawned which (1) has the user log in to Amazon, and (2) collects the user's consent to link their Amazon account to my Alexa skill (i.e. linked to my credentialed hosted service), so that we get back (in the browser) an authorization code that we can exchange (on our server) for bearer and refresh tokens to act on behalf of the user.
The problem is, that code above immediately fails and never pops up a process. The message that is thrown says: "An unknown scope was requested". If I remove the 'alexa::skills:account_linking' string from the options.scope array, I get to an Amazon login screen, and if I log in to Amazon, my server does get an authorization code, etc. But no Account Linking has taken place, so I'm stuck.
I've tried to reconcile this documentation (which also talks about including a Skill ID somehow), with this documentation but I'm just not seeing how to make it work. Can anyone please help point me in the right direction about what I'm doing wrong here? It must be something pretty fundamental.
If your goal is to use Login with Amazon for account linking only for the skill and to not store the tokens on your own server, you can set up the skill and Login with Amazon with the below configurations. The advantage of this approach is that you don't need to stand up your own web server to just handle the LwA flow. This approach also handles all the flow out of the box, including refreshing tokens.
If you're using these tokens for another purpose, you may want to look into something like AWS Cognito to simplify the process.
Skill Account Linking Configuration
Replace Your Client ID with the LwA Client ID, replace Your Secret with the LwA Client Secret, and copy your redirect URIs
LwA Configuration
Paste your Alexa redirect URLs here. These will be specific to your vendor account so it's important to have the right ones.
Source: This is what I do for my Aberto Sonorus skill: https://www.amazon.com/WBPhoto-Aberto-Sonorus/dp/B078W199Z3 (edited screenshots attached)

How do I access APIs without using NetworkCredential in C#/UWP?

I got some of the APP's APIs.
When I use the browser to access these APIs, the browser popup window tell me to fill in the username/password, Then I tried to fill out my username/password and found that I passed the verification!
Then I tried to write the code
var myClientHandler = new HttpClientHandler();
myClientHandler.Credentials = new NetworkCredential("abc", "!##");
this._client = new HttpClient(myClientHandler);
this._client.BaseAddress = new Uri("http://api.xxx.com");
var result = await this._client.GetStringAsync("some_api_foo.json");
Run well!
(We know that if there are no NetworkCredential, there will be 401 unauthorized exception)
But I found out that the official APP could access some of the APIs without the user logging in. How does it work? Does it use a public account? Or is there another way to access the APIs?
It uses Windows integrated authentication (Kerberos) to authenticate your users without asking them for credentials
Use Fiddler >check Authorization Header is present: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxx is Username:Password(Base64)
Decrypt it!

WSO2 Implicit Flow not returning id_token

I am trying to authenticate a user from a custom web app with an OpenID Connect Service Provider within WSO2. I am following an answer on this article and added the Nuget package Thinktecture.IdentityModel.Client. My code is very similar to the linked article:
var client = new OAuth2Client(new Uri(serviceProviderAuthorizeUrl));
var url = client.CreateImplicitFlowUrl(
clientId,
redirectUri: redirectUrl,
scope: scope,
nonce: Guid.NewGuid().ToString());
Response.Redirect(url);
The url comes out to be: https://{wso2_url}/oauth2/authorize?client_id={my_client_id}&response_type=token&scope=openid&redirect_uri=https%3A%2F%2F{mydomain}%2F{my_app}%2FCallback.aspx&nonce=f0db4eac-18df-46f6-92f1-c28ba621596d
Now this does work and returns an access_token: https://{my_domain}/{my_app}/Callback.aspx#token_type=Bearer&expires_in=970&access_token=067e3366217798986912326a86abd92f
My issue is that I have no idea who the user is. Further more, this WSO2 article shows that if I pass a response_type:id_token I should be able to decode the response and find out who the user is by using the "sub" attribute but I am not getting the id_token response. The code above creates a url with a response_type of token instead. Simply changing the response_type gives me an error. How can I use implicit flow in WSO2 and get the id_token response?
I followed this article for the configuration of WSO2. I currently have Implicit and Client Credential checked.
Make sure you have these as query parameters.
response_type=id_token
client_id=xxxxx
redirect_uri=http://xx.com/xx/x
nonce=xxxx
scope=openid
Make sure that you pass on the scope intended to use for the Idp (WSO2) to know what data it needs to return. Make sure your scop
scope=openid.

Amazon Skill register oauth missing redirect_uri

I'm writing an Amazon Skill that I want hooked up with a google account via oauth2. In my edit skill page, I configured it with my client id, an authorization url and token url from the oauth playground, and made it an authoritative grant with my secret and authentication scheme of "http basic", which is recommended.
I tested my client id/secret in the oauth playground and it works as I expect it to, but when I go to sign in on the Alexa App, I get a "missing redirect_uri" error. Looking at the link in the popup, it looks like the following:
https://accounts.google.com/o/oauth2/auth?client_id=custom_client_id&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email
Why is it missing the redirect_uri parameter? I can't change it on the skills page, it's set, and I added it to my valid redirect_uri lists on the google console. Anyone else seen this issue before?
An easier version of what jking31cs is saying is to include ?redirect_uri= ...
In your base URL. So if you provide them Oath.com/auth as your authorization URL, instead try Oath.com/auth?redirect_uri=
The redirect URI is constant, so this is a good fix until amazon bothers fixing this. It's only an issue on custom skills.
They've fixed the issue with an update to the Alexa App :D

Facebook Api Check Access Token Without Hardcoding App Secret

I'm building a manual login flow for my App which is integrating some facebook functionality.
I need to check when the current access_token of the user will expire.
The API documentary says I should do this call:
GET graph.facebook.com/debug_token?
input_token={token-to-inspect} &access_token={app-token-or-admin-token}
So I did this in C#:
Uri inspectAccessTokenUri = new Uri("http://graph.facebook.com/debug_token?input_token="+access_token+"&"); //IDK which value should have the last parameter
HttpWebRequest checkToken = (HttpWebRequest)WebRequest.Create(inspectAccessTokenUri);
var response = await checkToken.GetResponseAsync();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string data = reader.ReadToEnd();
Debug.WriteLine(data);
The last parameter should be the app-token:
BUT: Of course I looked up how to get the app-token and facebook says:
Note that because this request uses your app secret, it must never be
made in client-side code or in an app binary that could be decompiled.
It is important that your app secret is never shared with anyone.
Therefore, this API call should only be made using server-side code.
(Facebook Graph API Documentation 1.1.16)
So my question: Can I check the token without the app-token or hardcoding the app-secret?
App secret is usually used by the server-side app, we don't use it in our UWP app, it could be decompiled.
Read the official doc about FB Graph Debug-Token, this can only be used when you debug your app, for example if you want to check the metadata about a given access token, after you publish your app, your code will not relay on it.
In an UWP app, we use WebAuthenticationBroker class to connect to OAuth providers such as Facebook, Flickr, Google, and Twitter. Maintenance is need during using OAuth connections. For example, expires information is included in the access token, when we use OAuth protocol for authentication and authorization, we need to refresh the access token after it expired.
Due to these conditions, you may reconsider what you can do in an UWP app and which API you should choose.
If the app-token is expired you will get a facebook response error. And you can catch this exception to deal with the situation you want. In this way you don't need to make a request with your app secret.
You can also use fb-uwp sdk that contains AccessTokenData for authenticated users