In Azure Mobile App server, with client initiated authentication on device, we get userid (aka sid), now when I want to create a user record using mobile app service the sid is not available for the first time. Only information I have at the backend is, by reading claims with "NameIdentifier".
string uniqueId = creds.UserClaims.FirstOrDefault(c => c.Type.Equals(ClaimTypes.NameIdentifier))?.Value;
SO I am curious whether is this the right way to get user id?
Yes, this is the right way to get the user claims. For more information, check out Chapter 2 of my book: https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter2/authorization/
Related
So, we have a web API that is working great with Azure AD and bearer token authentication.
In my ConfigureServices I have this:
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = Configuration["Azure:AD:ClientId"];
options.Authority = $"{Configuration["Azure:AD:Instance"]}{Configuration["Azure:AD:TenantId"]}";
});
We have the Client ID setup to be a Web API app in Azure AD.
Now we are making a native application and we need to also have a native app client ID in Azure AD. My API is looking for the Web API client... how do I also allow a bearer token that was created with the native app?
It looks like your app is looking in the aud claim // audience field to verify the client ID. This field represents the app ID of who the token is intended for. This means if you register a new Native app registration, the tokens issued to that app for this API will have the same aud claim.
In v1.0 format tokens, they also have a appid claim which represents the App ID of the client application (your web app or native app for example) if your API is trying to verify the token was issued to one of your clients.
In v2.0 tokens, this claims is azp.
Do note,in the case of the native app, it's considered a public client meaning the exact identity of the client is not guaranteed, hence the name public client. Your web app is a confidential client so there is a stronger guarantee the appid claim will be the app it claims to be.
In both formats there's another claim (appidacr and azpacr, respectively) that represents the client type. You can have high confidence if the value is 1or 2, but should be careful in the case it's 0.
Reference for tokens
Ok! So... we got this working.
For posterity here is what we ended up doing.
We found this fine link: https://github.com/Azure-Samples/active-directory-dotnet-webapi-manual-jwt-validation
In step 2 of this, it tells you to change the Web API URI - We ended up not needing to do this...
What was critical thought was to add the permission from the Native app to the Web API (the second set of steps in #2). Basically, as I understand this, it allows the native app and web api app to work together and share a client id when it come to an authentication perspective.
We also found that editing the manifest on the Native app and make "oauth2AllowImplicitFlow" = true was also important.
Hope this helps someone.
I have been researching on Azure Mobile app service and I am freaking out because I think I had it all wrong.
I have one Azure Mobile App service and issue is I am trying to implement "custom" authentication for it (the reason for custom authentication is that I have a web app and web API which uses the same database and send REST requests to mobile service app to update database and both of them use asp.net identity)
But before I implement custom authentication in mobile app service, I just can't get my head around that even though the authentication is custom and I am manually checking users, once the token is generated and user is authorised, the user has access to all the data in the table. So if I am user1 and login, mobile app service will authenticate me and once I have the auth token I can simply do REST request to do anything to all the data.
How do I restrict that the generated token is only used to CRID only that user's data where in my table I have UserId column also.
I am very confused. any help will be appreciated.
How do I restrict that the generated token is only used to CRID only that user's data where in my table I have UserId column also.
Per my understanding, you could follow Per-User Data and leverage the following property to retrieve the current UserID from the incoming Easy Auth token:
public string UserId
{
get
{
var principal = this.User as ClaimsPrincipal;
return principal.FindFirst(ClaimTypes.NameIdentifier).Value;
}
}
For the complete tutorial about handling CURD operations which need to be limited to the user who generates the token, you could follow Data Projection and Queries.
I'm trying to understand conceptually and practically how to perform an oauth2 with openID-connect flow in my web-api application, utilising Azure AD.
Importantly, when a request is made to the API I want to know who made the request.
My current understanding is :-
My client would detect that the user isn't logged in and redirect to a sign-in.
The user would provide their credentials, and be redirected back to the client, along with an oauth2 token.
This token would be supplied to web-api endpoints for any requests.
This is where it gets murky for me.
How exactly do I use this token to authorize access to a particular resource, determine who is accessing the resource, and what is the mechanism that does so?
I'm sort of assuming that I would need to reuse the token to make a call to the Azure AD user endpoint - if the token was indeed valid, the AD endpoint would return the users details - thereby providing some means of determining that the token is valid and providing details on the users identity. Authorizing access to a resource could be done through membership of groups in Azure AD.
BUT ...
I can only assume this a solved problem, and have noticed use of OWIN middleware as per this example
https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet
But I'm still rather unsure as to what is exactly going on.
The service makes mention of scopes and claims, but I don't understand where these are derived from (I assume from a token supplied by the client, but not sure). The service must be receiving identity information in the call.
Which brings me to two points, for this to be secure -
The token provided in call to the service would need to be secured in transmission (hence the use of HTTPS) - to prevent MITM.
The token would need to be signed some how - I guess by using client secret or something - to prevent information in the token being spoofed.
Can someone help me clear up this muddled mess?
In particular -
How is the identity of the API caller determined - is identity determined from a call in the client or the server?
How to limit access to some endpoints of the API based on a user role?
What do I do to practically achieve this by building on existing middleware and libraries available to me?
Disclaimer: This will not be a comprehensive answer. It is off the top of my head.
OpenID Connect provides an identity layer on top of OAuth. In your case, Active Directory provides the authentication and sends back an access_token. The access token represents a user that AD has authenticated. If your doing OpenID Connect, then AD will also send an id_token, which may contain additional identity information (such as birthday, avatar, and whatever else AD exposes.)
Neither OpenID Connect nor Active Directory have anything to do with the the roles that your app assigns to a user; roles are entirely the bailiwick of your app. You assign user roles just like you normally would; you assign them to the nameid though instead of to an email address or username. Your app no longer has to authenticate the user but it does need to assign roles to the nameid.
How is the identity of the API caller determined - is identity determined from a call in the client or the server?
The identity is embedded in the access_token that AD includes in its response. This token will have a nameid in it that your app can associate with a user and role. The nameid is like an email address, username, or other uniqueID that your app uses to recognize the user.
How to limit access to some endpoints of the API based on a user role?
You choose. When your app receives a request with a particular access_token, that token will be associated with a particular user via its nameid, and you can assign whatever roles and rights to that user. Basically, associate roles with a nameid.
What do I do to practically achieve this by building on existing middleware and libraries available to me?
There is an unfinished demo here, though it doesn't use Active Directory as the provider, instead, it uses an internal provider. For the demo, the username is shaun and password is Testing123!. The source code is here.
Here is the link to the source of another demo, though again, it doesn't use Active Directory as the provider, instead, it uses Twitter.
The nice thing about OAuth and OpenID Connect is that we can use whatever identity provider we want, so you can adapt the demos to use Active Directory.
Apart from question #1 (the identity is verified on the service side) all your question are very open ended and would require a super long answer.
I would recommend reading https://azure.microsoft.com/en-us/documentation/articles/active-directory-authentication-scenarios/ - it is a good introduction to the flows underlying many of the modern authentication cenarios, including the web API one you are focusing on.
Once you have read that, you will find a complete set of samples in https://azure.microsoft.com/en-us/documentation/articles/active-directory-code-samples/ - in particular, I suggest studying the web API and thru authorization one to find guidance on the 3 questions you listed. HTH!
I'm trying to use Windows Azure Access Control to avoid the security risks in using usernames/passwords in my app and to simplify the authentication. However, this is a site that can be used by medium or large companies that may wish to "pre-authenticate" users. In other words, they may want to bulk create users by putting in the users' Windows Live IDs and create their accounts automatically, before that user has ever signed in through Azure ACS. I could accomplish this by sending that user an email with a link to a one-time-use page to create their account, but I am hoping to do something a little more seamless.
What I'm trying to do is equivalent to how Team Foundation Service (*.visualstudio.com) lets you add users to a team project just by putting in their Windows Live IDs and once you do, they can log in and access the project, even if that user had never signed in to TFS previously.
What I don't understand is how to do that using ACS and System.IdentityModel. I can use the nameidentifier claim to uniquely identify a user, but how do I get a nameidentifier for another user through a given provider?
I'm sorry if I'm not explaining this well, so feel free to ask questions.
Not really an answer but just wanted to share my thoughts on the issue.
The problem with ACS and Windows Live authentication is that ACS never returns the user's email address. All we get back from ACS is a token telling me that the user is authenticated. This token is created based on your ACS realm (i.e. if you change the ACS realm, a new token will be created by ACS for the same user). Again, the admins of the company who are using your application can enter the email addresses of the user but there's no way to get that email address back from ACS.
Just thinking out loud :), there're a few things you could do:
You use ACS for authenticating the user and then use Windows Live REST API to get more details about the user using the token sent by ACS. By using Windows Live REST API, you can get more details like name, email address etc. about a user. Or you could use just Windows Live API for authenticating the user. I'm not 100% sure but I think this is what Team Foundation Service does. Do take a look at http://zud.io as it does the same i.e. uses Windows Live API.
Another idea would be to create some sort of invitation tokens. In this approach, admins would "invite" folks. They would create invitation record by providing the name, email address of the users and the application would create unique invitation tokens. The application could then create an invitation link using which users would come to your application and authenticate themselves. Once authentication is done, you could look up the invitation record and retrieve user information from the database and create user record and associate the authentication token with the user record. The issue with this approach is that a user may not use the same Live Id as provided by the administrator. For example, I have at least 3 live ids and if I have that invitation link, I could sign with any of those live ids and the application won't be able to stop me from registering.
Yet another idea would be to use Windows Azure Active Directory (WAAD) instead of ACS. You could consume Graph API in your application to create new users for your clients. You're still not managing user names and passwords as that is done by WAAD. The two issues I could think of there are - a) As an end user, I have to remember one more username/password combination and b) At the time of login, I have to provide my credentials in myusername#yourtenantname.onmicrosoft.com which to me personally is a big hassle.
We too have been going through the same pain and for now we have decided to go with approach #2.
Hope this helps.
I'm building a mobile app and a ServiceStack web service back-end. The Authentication stuff in ServiceStack looks great but easy to get lost in its flexibility - guidance much appreciated. I'll be using my own db tables for storing users etc within the web service. I'd like to have a registration process and subsequent authentication something like this:
the user initially provides just an email address, my web service then emails a registration key to the user
the user enters the key. The app sends to the web service for registration: email, key & a unique device identifier.
the web service verifies the key and stores the email & device id. It responds back with an auth token that the app will use for later authentication.
Then subsequent web service requests would provide the device id and auth token (or a hash created with it). The app is not very chatty so I'm tempted to send the authentication details on each web request.
Question 1: Should I hook into ServiceStack's registration API or just add a couple of custom web service calls? e.g. without using ServiceStack's registration I would:
post to a registration web service with the email address and device id. My web service would send the registration email with a key and add a record to the user db table.
when the user enters the key it would again post to the registration web service, this time also with the key. My web service would validate the key and update the user table marking the user as registered, creating and recording the auth token & returning it to the caller
subsequent requests would be sent using http basic auth with the device id as username and the auth token as password. The service is not very chatty so creds will be sent with each request.
I'll implement a CredentialsAuthProvider that'll get the creds with httpRequest.GetBasicAuthUserAndPassword() and validate them against the db data.
But it feels like I should use registration built in to ServiceStack.
Question 2: What's wrong with passing the authentication details with each request? This would make it easier for composing my app requests but it doesn't seem 'done' based on the ServiceStack examples. Presumably that's because it's inefficient if you have lots of requests to need to re-authenticate every call - any other reasons? My app will only make a single web request at most every few minutes so it seems simpler to avoid having sessions and just re-auth each request.
Question 3: Am I on the right track subclassing CredentialsAuthProvider?
Question 4: Is there any point using the auth token to generate a hash instead of sending the auth token each time? All communication will be over https.
Answer1: It will be OK. if you give multiple call as per requirement. Normally authentication works based on cookie, now you can store it on client and/or on server and match the user with it. Again here if you are using device you, can always use device instead of user to map and authenticate user. Based on your requirement.
I will prefer to use provider as it hides many details which you need to do manually instead. You are on right track. There are many blogs specifically for authentication and how to create custom authentication with service stack. If you like let me know I have book marked some will give it you. Best way to search latest one is checkout twitter account of Servicestack.
Answer2: This is again, I say as per requirement. Now if your user will be in WIFI zone only. (Mostly true for business users), then there is not limit for calls. Just give a API call and do the authentication in background. Simple JSON token will not hurt, It is few bytes only. But again if you have big user base who is not using good internet connection then it will be better to store authentication detail on device and check against that. Just to save a network call. In any case network call is resource heavy.
Answer3: Yes you are on a right track. Still check out blog entries for more details. I don't remember the code snippet and how it works with last update so I am not putting up code here.
Answer4: This is answer is little complicated. Passing data over https and saving user from Identity fraud is little different thing. Now, if you are not generating auth token (hash based value) then you can pass user also over the http or https. Now, this can be used by another user to mock first user and send data. Even data is being passed through https but still data is getting mocked. Hashed based value is used to avoid this situation. And also there are couple of other business use cases can be covered using auth token.
Please let me know if I have understand you questions correctly and answered them?? or If any further details is required??