Does / can Alexa replace its generated UserId for a linked user? - authentication

We have an application utilizing Alexa skill with account linking for user details.
According to Alexa's account linking documentation:
Our skill is set up for Account Linking which in turn refers to a 3rd party (or it could be internal) Identity Management System (IMS) for user authentication. Our application (as well as our organization) does NOT internally maintain the app's user identities.
Let's say the user enabled our skill on her device, at which point (according to the above docs) she was issued an Alexa generated userId, something like:
"userId": "amzn1.ask.account.AFMWOL5WIGQZLYYEMM2IJL2BJ26ICPQHBPR2DSLRX46CHW36R6CPVH7RZTUZMBCHHJLQQNU3YO2BWZWNIRTM3PCAGTNZKILK33PM2XVI36H4RSINFH2A26OLURAIB2RVPV6GMK56BR5BLBIFNJKT64EANASM7IDTQJBQLGDIEUZHUIM6VSHTTOUPVPITIPOIOPESUK53TSALU5I"
Consequently, upon further interaction with the skill, she wanted to access some more personalized information which triggered account linking so her identity was confirmed and re-established via provided account linking details (OAuth 2 Authorization Code Profile), which, while doing so, as mentioned before contacted the 3rd party Identity Management System (not LWA) to verify the user identity:
the user is presented with a login screen,
she enters her credentials, say: "alice"/"password123"
she answers the relevant questions to permit certain actions that our app can do on her behalf and
is allowed to further interact with the system on a more personalized basis
Let's say that inside our app, we want to be able to identify the user by her real userId: alice and NOT the one auto-assigned by Amazon, as described above.
Does Alexa allow for this?
Upon successful account linking, does Alexa overwrite in its JSON request (or can it somehow pass it through, along with now embedded accessToken field) the userId it receives from the 3rd party Identity Provider) so that that "real" userId (is it called subjectId in OAuth parlance?)can then be used to identify the user actions during her further interactions with the app?
If yes, how can we obtain the user details from JSON via Alexa Java API?
If no, what would be possible ways to facilitate such ability?
Can the real userId be obtained from the accessToken that Alexa puts in its request after authenticating a user? If so, how?
I'm not sure if it's related to this, seems to be a similar request, has it been put on Alexa's roadmap or became a feature already?

This seems to be a detailed version of How to obtain userId specified by Alexa user during account linking
Generally speaking, after the user complete the OAuth authentication, the application (i.e. Alexa in this case) would receive a access_token and refresh_token. If you want any additional data, e.g. username alice, email, phone, address...etc., you would need to check with your OAuth provider and see if they have an API to retrieve those based on the access_token with the appropriate scope.

Related

Obtain user information on Actions on Google Through OAuth in AoG?

Account Linking provides several ways of linking users to their own accounts such as their Google account or Twitter account.
I chose OAuth in Actions on Google website to do OAuth 2.0 Authorization Code Grant for obtaining access token in exchange for data resources. When I linked a user to a Google account Google Sign-In enabled, the fetching of user information was easy because the data is stored under payload, but OAuth implementation does not seem like it produces user data under payload inside User object.
So should I make an API call to the third party to fetch the user data and store that personal data to a database in this case? I wondered if there is a way that Google prepares on behalf of developers. If not, then greeting a user who visits my app again by saying 'Hello, {person name}' gets tedious...
You have two options with Account Linking.
In the case you describe, you're providing an OAuth endpoint and getting an auth token from the Assistant, and you are responsible for taking this token and using it to determine who the user is so you can get whatever you know about him. The token is one that you issue and control, so presumably you have that info in your database already. If you are reusing a token from another service, that service should be able to tell you who they are.
It sounds like you're using using a Google Sign In, however, in which case it is easier to use Google Sign In for Assistant. Once the user has signed into your service (either through an app or webapp) and granted permission to your service, then they will also be able to gain access through the Assistant. You will get an id token which can be decoded to get profile information about the user including their Google ID and name.

API - allow users access to only data they created

This is an API related question that applies to the APIs that I'm working on and would like to know the standard way of doing this.
say a user1 has created accounts so he can access it by
GET /accounts
but when he accesses transactions for a particular account
GET /accounts/acct1/transactions
how would this API know that the acct1 actually belongs to that user1 and is not the case where user2 is accessing user1's accounts.
This api is accessed via a Mobile app using Oauth 2.0 tokens. So while the access token control the access to API endpoints, how do we control access to only specific user's data at that endpoint. (using scopes?)
I've been looking at Spotify's apis and they seem to be doing this via v1/me end point.. Still reading...
I'm a noob at this and it looks to me that this should be documented somewhere in a standard manner in some RFC, but I couldn't find it and would appreciate direction
Can you provide more details on your use case? Why are you using OAuth?
It sounds like you need an authentication protocol - i.e. a protocol to let your server know who is accessing a particular API.
To quote the OAuth website:
OAuth 2.0 is not an authentication protocol
OAuth's main use-case is letting one application perform operations on behalf of a user of another application.
As an example, if your server wants to post a message on Facebook on behalf of a user, you will use OAuth to obtain a token from Facebook which lets you post messages on behalf of the user. Note that, in the most general case, your application does not know which user is represented by the token. Indeed, the user may not even be a (registered) user of your application - they only have to be a user of Facebook.
Practically speaking, you often can use the token you have to query Facebook for the identity of the user. So your server would extract the OAuth token from the request headers and use it to issue a query to Facebook's Graph API to obtain the user ID.
Note that the user is a Facebook user rather than a user of your app, so you will need to somehow map the Facebook user ID to your own users and permission system - i.e. check your database to ensure that the user has permissions to do what they asked to do.
This is the mechanism that is typically used when using OAuth like an authentication protocol (which, as quoted above, it is not).
I should add that if your app obtains an OAuth token and passes it to your server for the purposes of authentication, then this flow is not 100% secure, as discussed for example here, so make sure you do proper risk analysis for your case. In a nutshell, a determined attacker can theoretically impersonate your app and obtain tokens representing other users.

Anonymous login using OpenID or OAuth

In short: Can I use OpenID oder OAuth for anonymous logins on my web service?
Described in more detail:
Scenario/Background: I'm going to provide online-tools for mental health related exercises. The users should be able to see their completed exercises after each login, but I don't want them to register at my service—because I don't want to store their e-mail adresses, passwords, not even nicknames or anything like that (not even hashed!), because it could reveal the users' identities. I want to keep their privacy perfectly safe by not storing anything that relates to the offline identity.
Problem: How to perform the login (or how to recognize recurring users) without credentials?
Approach(?): When I use my Google account to log in at some third-party web services, I'm asked wether I want to share my profile data, e-mail adress—and what else. Would it here be possible to reveal nothing? The only thing, the service would know, is that somebody has a google account and knows the password. To me, it's completely unimportant who the owner is, it's just important to recognize the same owner after each login—let's say by some kind of anonymous token id.
Is this approach working?
Are there other approaches for anonymous user logins—without storing data?
Use OpenID Connect. OpenID Connect is a specification built on top of OAuth 2.0 (RFC 6749). You can delegate user authentication to an Identity Provider (such as Google) that supports OpenID Connect.
An IdP will issue an ID token to you after successful user authentication. You can find the user's attributes such as name, email address, etc. in the ID token. So, you don't have to manage users' attributes any more if you use an external Identity Provider that supports OpenID Connect.
(Addition for the comment)
OpenID Connect Core 1.0 has defined 6 standard scopes as listed below. These values can be included in scope parameter of an authorization request.
openid
profile
email
address
phone
offline_access
Among the above, profile, email, address and phone are defined in "5.4. Requesting Claims using Scope Values". They can be used to request some attributes of a user to be included in an ID token which will be issued by an authorization server. For example, when email is included in scope parameter, the ID token issued based on the request will contain values of email and email_verified (if the authorization server supports the attributes).
So, if you want to minimize the number of attributes contained in an ID token, avoid including profile, email, address and phone in scope parameter. In other words, scope parameter should contain only openid.

External Login Account vs. Native Login Account

I am brand new to Visual Studio 2012 and MVC 4, and I've been working with the SimpleMembershipProvider via the WebMatrix.WebData library.
I'd like to integrate Facebook as an external login source down the road, but it's not a requirement as of right now. However, to get a decent feel for what it would take, I've been following the tutorial and guide found here - http://www.asp.net/mvc/tutorials/mvc-4/using-oauth-providers-with-mvc.
My question :
If a user has already been created using :
WebSecurity.CreateUserAndAccount(model.Email, model.Password);
WebSecurity.Login(model.Email, model.Password);
Can they be "upgraded" to an oAuthMemebership account in the future, if they choose to use their Facebook credentials instead of the email and password they created when first signing up?
I couldn't find a clear answer to this question in the guide, or elsewhere, so I'm hoping someone can clarify how that process may work.
The SimpleMembership setup allows for a local and multiple OAuth logins all sharing the same UserProfile - so a single user can login with either a local password, or FacebOogLiveWitter.
(I should state, that I'm assuming in this answer that the OAuth provider does not send back a matching piece of information for a local account. If they do then the principles of actually performing the merge are the same, but the complexity and steps are vastly reduced.)
The OAuth registration process will refuse the user if they use an existing user name, rather than try and merge two accounts. Therefore this isn't simple, you'll have to build the functionality yourself. The process is complex as there are many directions the user can approach this from (so you could simplify by only supporting one or two), and you need to enforce security as well in case someone tries to merge into an account they don't own.
I will assume you are comfortable with the link you've posted, and you've followed the Facebook help at (for example) Facebook Login and The Login Flow for Web (without JavaScript SDK) so you have a working test application.
Your general process has to have multiple user journey approaches to make sense to a user:
for a logged in user (with a local account)
let them login to facebook and associate the accounts
let them merge an existing account on your site which uses a facebook login
for a logged-in user (with a facebook account)
let them create a local account
let them merge an existing local account on your site
for a non logged in user who tries to register a local account
let them merge this new account with a facebook login that is already registered, and do that as part of the registration process
for a non logged in user who tries to register (or log in for the first time with) a facebook account
let them link this with an existing local account as part of the registration process
etc.
ASK PERMISSION
(You can skip this if the OAuth provider has sent back a matching identifying piece of information, such as an email address).
You should enforce confirmation security, usually through email confirmation sent to the target account of the merge. Otherwise:
someone can login to your site with facebook for the first time
during that process say they "own" the email address or username of a local account (remember, facebook won't necessarily confirm what their email is for you)
and therefore gain access to the existing local account
So, once the merge "request" is made, you need to ask for permission to proceed from the target account of the merge.
The MVC 4 AccountController
I will use Facebook as our OAuth example. To compare what happens when you register a user on your local authentication framework vs. OAuth:
Local: creates an entry in webpages_Membership and an entry with the same UserId in UserProfile (assuming you are using the default tables for the MVC 4 application template)
OAuth: creates an entry in webpages_OAuthMembership and an entry with the same UserId in UserProfile
Now let's look at what happens when a user signs in using Facebook for the first time:
They click on Login using Facebook (or whatever your button says)
they get taken to facebook to login
they succeed (let's assume that, and ignore the failure case)
they then get sent, invisibly to them, to /Account/ExternalLoginCallback
OAuthWebSecurity.SerializeProviderUserId is called, passing the OAuth details to that Action
They get redirected to /Account/ExternalLoginConfirmation and asked to provide a username for their new presence on your site
If that user name is available then UserProfile and webpages_OAuthMembership entries are created
This process is your chance to "join" the accounts by matching some unique piece of information. As long as you end up with the same UserId in UserProfile, webpages_Membership and webpages_OAuthMembership you should be ok. So we have to intercept the process at the point of /Account/ExternalLoginConfirmation.
If the OAuth provider has sent back a matching identifying piece of information, such as an email address, this becomes simple, test for this in the ExternalLoginConfirmation action, and auto-merge using a similar process to the one outlined below.
However, I think you can't/shouldn't assume that the user uses the same email address for your site and OAuth, (nor should you for many reasons). Also, probably in the T&Cs for something like FacebOogLiveWitter it stops you asking for the email of their account anyway, and if they don't currently they might in future.
So instead, you could link the accounts based on alternatives, like username or email address, or phone number. Either way you are going to need them to input some identifying piece of information that is unique against an account, and will pull back the target account.
Wrapping up
So to put this all together: In the first part of this answer I outlined how you will need to consider multiple user journeys to merge accounts. I will use the example 4.1.
Your process will need to:
(Assumption - when a user first registers with a local account, you ask them for an email address and validate it or assume it is valid)
Let the user login with facebook for the first time
at Account/ExternalLoginConfirmation ask them if they want to
Create a new account with you
Use their facebook login to access an existing account
Assuming the latter, then you log a request in a new table (maybe "MergeAccountRequests") with:
The facebook account UserId
The target merge local account UserId
An authorisation code to use in the email you need to send
(From this point on, if they login without confirming that merge, they will have to get sent to a page to ask them to confirm, rather than create objects in other db tables which you have to worry about later)
You then send an email to the address of the target merge (local) account asking for permission to complete the merge (a standard confirmation email, with a link)
When they click on that link, or enter the code you sent them (you could use SMS as well as email) then you need to merge the two accounts
Choose the "new" and "target accounts (in this case "new" is the facebook account as you don't have data associated with it yet)
Delete the UserProfile of the "new" account
Change the UserId of the "new" account webpages_OAuthMembership table to the same as the "target" account
Log the user out (so there are no complications depending on which account they are currently logged in with)
Display a message to the user telling them the merge is almost complete and that they can now log in with either account to confirm and complete the merge
Rather than send them to a login page, i would give them the login options alongside the confirmation message.

Associate multiple claims based identity providers to one user with ASP.NET

In an ASP.NET MVC 4 application using the .NET 4.5 framework in conjunction with Azure Access Control Service (ACS), I want to provide the users multiple authentication possibilities (i.e. Google, Facebook, Windows Live, etc.). What is the "best practice" for associating a single user to multiple identity providers?
For example, say the user logs in with Google one day, then goes to another browser the next day and logs in with Facebook. How would I know to associate the Facebook login with the previous Google login to the same user?
Look no further than stackoverflow itself for a good example of this. Click your user profile and then select "my logins".
When a user creates their account, they select which identity provider you want to use to sign in. Under the hood, your application creates a new site-specific unique user ID, and links it with a 3rd party provided unique ID. (You might use email, but most identity providers will also provide a unique user ID claim that doesn't change, even if the user changes their email)
Now, after the user has signed in, they have an account management control panel through which they can establish additional links to other identity providers.
I see two options for achieving this:
Have your MVC application persist account links. When a user signs in, you query your account link store using the 3rd party unique ID claim and resolve your site specific unique user ID.
Use the ACS rules engine. You would create one rule per account link. For example, lets say I can sign in with either gmail or liveid and my unique id is 1234. Two rules look like this:
google + me#gmail.com --> output user ID claim 1234
liveId + me#live.com --> output user ID claim 1234
For the unique ID output claim type, you can pick from the available claim types or designate your own. ACS has an OData based management service which you can use to create these rules programmatically from your MVC application. Here's a code sample.
If you are using ACS, you can translate the information from each IdP (e.g. Gogle, Yahoo!, FB, etc) to a common handle using claims transformation on ACS. A common handle people use is the users e-mail. But if you want to accept many e-mails mapping to the same user, then you'd introduce your own unique id (as a claim) and map IdP supplied claims into it:
myemail#gmail.com (e-mail - Google) -> (UserId - YourApp) user_1234
myotheremail#yahoo.com (email - Yahoo!) -> (UserId - YourApp) user_1234
64746374613847349 (NameIdentifier - LiveId) -> (UserId - YourApp) user_1234
You can automate this through ACS API. You should also probably handle the first time user logs in into your site (e.g. asking user for an e-mail and sending a confirmation message that will trigger the mapping).
Presumably, you are using this information to retrieve data from a local database in your app, otherwise, you could just encode everything in claims and not worry about any equivalences. Claims are often a good place to encode common profile data. (e.g. Roles, etc)