C# Web API 2 & Angular - Microsoft Account Authentication - c#

I've asked the question below a couple weeks ago and I didn't get a working answer. Or maybe just not suitable for my case.
C# Microsoft Authentication Get logged user from controller
So I thought maybe I wasn't asking the right question. What i'm trying to do is create an app which has a C# Web API 2 backend and an Angular 2 frontend. Now, I want that my authentication be using people's Microsoft Account which means this will be an external authentication.
What's the best way of doing this? It would be very much appreciated if you can give a link on a blog or article that explain what I'm looking for. On my link above I've used msal.js and so far it was working fine for me until I had to get the logged user's details. It was possible from Angular's side but I want to do it in Web API so it is more secured.
Thanks in advance!

If you are using OpenId, you have claims that are returned when user is authorized. I am assuming you are using Azure B2C for authorization in which case you can select clams that will be returned as part of token.
For example, if you want to fetch user id:
var userId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
Email:
string userName = ClaimsPrincipal.Current.Claims.Where(x => x.Type == "emails").FirstOrDefault()?.Value;
It depends what claims your authorization has returned, easiest way would be to put breakpoint on
ClaimsPrincipal.Current
and inspect it, it should return list of claims.

From your code in the previous post, it looks like you need to read from the ClaimsPrincipal instead. ClaimsPrincipal is the implementation of IPrincipal when you use OAuthBearerTokens, so of course you can get the username from CurrentPrincipal.Current.Identity
From this documentation
https://msdn.microsoft.com/en-us/library/system.security.claims.claimsprincipal(v=vs.110).aspx
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-api-dotnet
public IEnumerable<Models.Task> Get()
{
var user = ClaimsPrincipal.Current;
...
}

i do with this example
https://github.com/Azure-Samples/active-directory-b2c-javascript-angular2.4-spa
and it work well

Related

Custom blazor server-side authentication

I am new to blazor and stumbled across a problem when trying to implement authentication in my app. For now, I need to store all my users' data in JSON file and do not have a SQL DB to refer to, which, as I understand is needed to implement authentication.
As for now I have a list of users and check if the user is in my list of signed in accounts, then call markAsAuthenticated
public void markUserAsAuthenticated(string emailAddress)
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, emailAddress),
}, "someType");
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged (Task.FromResult(new AuthenticationState(user)));
}
I would like to add roles or claims now to be able to include them in the component, but find it difficult to understand, what the following steps should be.
Most of the tutorials use Authorization services provided by VisualStudio, but we work in VSCode and I would like to implement this myself, so I can use the list of users I have.
I would also like to find out if I can use cookies or JWT in my app and if there are any good tutorials for that or suggestions considering work with VSCode and server-side work, thanks in advance!
If you want to use cookies you need to use a razor page (.cshtml). You can have a razor page inside a Blazor application. It's the same code you'd use in a traditional razor application (pre-Blazor).
There's nothing Visual Studio specific to this that I know of.
See https://blazorhelpwebsite.com/ViewBlogPost/36

RESTful API Design - same path diffrent roles

I´m currently working on a RESTful API, which has to give access to two diffrent Roles: Admin and User. (I'm wokring with Azure AD App Roles)
My Problem is that I don't understand how I can design the controller logic.
For example I want both (admin and user) to access the endpoint /books, but the admin is allowed to see all books and the user is only allowed to see his books.
What is the best practice to give both the allowed access? I thought of splitting it into two enpoints like this:
/books -> with annotation [Authorize(Roles="Admin")]
/user/{id}/books -> with annotation [Authorize(Roles="User")]
Thanks for helping!
Best regards
I think this sample may be of some help. And if you need sample written by other languages, you can refer to this document to find a suitable one.
And on your case, I think the most important thing is to find out the way to execute the right query and make the query result return to correct user.
So if you set a specific url for each user(I don't think this a good idea to expose user id in the request link), or you hide the user role/id into the token which contained in request header, you all need to write logic code to check which query method need to run. For example, hit domain:port/books with an access token, then your filter catch this request and decode the token to know the user id and user role, and maybe can save them in the session, then your controller may check the value stored in session and choose a right query to get the books information.

How to store user information with Net Core API with external users from Auth0

I am building an API which will use authentication with Auth0 and will have web and mobile clients.
Both clients will get their tokens using web based login from Auth0.
I am looking for the best way to get and store some user information in my API database, so I can e.g. list users in some group, relate article with the author, give some permissions to the user which cannot be stored in Auth0 (for 2 reasons: no mtm tokens and more important, that it's sort of multi tenant app and permissions are to complex to keep them in tokens).
There is userId in the token which can be used but e.g. when to trigger user save/update? Running it on each and every request does not sound efficient.
Anyone has done something like this?
How to approach it in the best way?
I have figured out a solution, however if anyone here would recommend a better approach, please do! Thanks to comments I went into hooks and then rules direction, so I appreciate any engagement.
I see it as fairly simple case, a bit tricky during local development but can be worked around with some development middleware in the API.
I am going to use Auth0 rules with crazy simple rule:
function (user, context, callback) {
const axios = require('axios');
axios.post('https://my-web-api.com/auth0/notify', { user }, {
headers: {
'x-api-key': configuration.API_KEY
}})
.then(() => callback(null, user, context));
}
In the Rules, I have added API_KEY as a variable so it is not there in the code, encrypted, safe.
By using this I will send the current user profile from Auth0 to the backend where I will simply check if the user exists or not and update a profile if necessary.
As per docs:
Please note that rules also run during the token refresh flow.
it gives me also updates during the refreshing flow, so if anything changes, I will get the updates as well.

How to make sure that all call to asp web api is authorized?

I'm building an saas application using asp web api 2 and asp identity. This api will be consumed by web, mobile and desktop applications. How do i make sure that all calls to my web api method is authorized? In web, we can ask user to login before going to certain page, but how bout mobile/desktop? Does user need to provide login and password on each call? Are there better solution for this? I've been searching and havent found any article about this. A sample or articles will be much appreciated.
Usually when using api's as a back-end you have to authenticate the user on every request.
(it actually also happens with other frameworks, such as mvc.net, but they keep track of the user using cookies which are send back and forth with every request)
I would suggest you use token based authentication (e.g. OAuth). In such a case you set the token in the header of the request. This token will be used to authenticate (and potentially authorize) the user.
If you need more info i can always explain it a bit more.
== Edit: Added Code sample ==
You could use a request handler to validate that the header of the request includes a valid token:
public class AuthorizationHeaderHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage pRequest, CancellationToken pCancellationToken)
    {
        IEnumerable<string> apiKeyHeaderValues = null; 
        if (!pRequest.Headers.TryGetValues("Authorization", out apiKeyHeaderValues)
|| !TokenRepo.IsVallidToken(apiKeyHeaderValues))
        {
var response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
            {
                Content = new StringContent("{\"error\": \"invalid_token\"}")
            };
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return Task.Factory.StartNew(() => response);
}
return base.SendAsync(pRequest, pCancellationToken);
}
}
All you have to do is keep which token is associated with which user, and make sure tokens have an expiration period. Once this is passed, it is also not valid anymore.
I hope this clarifies it a bit.
Again, if you have more questions, do not hesitate to ask.

Generic OAuth Library C#

What i am Trying to do:
Write a Generic Library in C# to handle OAuth Flow to every service ( Just like Twitter,LinkedIn and Foursquare). The hardest part is that, i want to simulate all the user input in code so that no user action is needed to click on buttons like "Ok,I will Allow It",or even writing its username/password.
Doubts That i have so far:
1 - Whats the usage of the authenticity_token in twitters API ?
2 - What are the factors that all services use, so that i can implement a generic usage of OAuth Flow. For example i´ve found the first Step is really easy to make a Generic method to execute. All i have to do is change the URL for the webRequest,and BAM, i have the Request tokens.
3 - How do i Get the Verifier for each service? In LinkedIn Service for instance, i was able to parse a page to fetch this value, but i can't find this verifier for twitter API for example. Even when authorizing in browser my aplication, i see no Verifier in any HTML during the flow, or any JavaScript generating it.
Observations:
1 - I know that there are Lots of OAuth Libraries out there, like this or that ones, but there is no Library that allows me to make what i want to, that is to Authenticate and authorize a user, without prompting for any user input.
2 - I can't,by any means,ask for user input. All the values like username and password for the authentication, will be hardcoded and every user will use the same account for this requests.
3 - I also know, that there are other posts here that i've written, with almost the same doubts, and the reason i am resposting is to try to make it clearer and fresher.
4 - Sorry about any english mistake or missunderstanding of concepts in advance.
Basic Code Sample:
This is, for instance, the method i am using (that is avaible widely abroad the web) for getting request tokens for any service. All i have to do is change the REQUEST_TOKEN value to the specific url to be used for a service,so i can get the Tokens for LinkedIn,Twitter or Foursquare for instance. But i can't manage to apply the same process in the other steps.
public string AuthorizationLinkGet()
{
string ret = null;
string response = oAuthWebRequest(Method.GET, REQUEST_TOKEN, String.Empty);
if (response.Length > 0)
{
//response contains token and token secret. We only need the token.
NameValueCollection qs = HttpUtility.ParseQueryString(response);
if (qs["oauth_callback_confirmed"] != null)
{
if (qs["oauth_callback_confirmed"] != "true")
{
throw new Exception("OAuth callback not confirmed.");
}
}
if (qs["oauth_token"] != null)
{
ret = AUTHORIZE + "?oauth_token=" + qs["oauth_token"];
}
}
return ret;
}
Don't.
OAuth was designed to require a user to press that button once. If you automate it you will have your application key revoked and your program will no longer work.
What you need to do is save locally the authorization token and reuse that. The user clicks"I Allow" once then you re-use the authorization token for future connections. You need to check to make sure it is not expired, and if it is you just re-authorize and they click "I Allow" again.
No website doing OAuth correctly will allow you to bypass the website authorization, some will allow you to pass the username and password via a query and get a token, but if they have a web authorization, you MUST have the user manually do it.
If you are the OAuth provider and consumer you need to do something Dropbox did for their v0 of the API (I can't find any links to their old API, if anyone can find it edit this post) that passed the username and password to a special address that returned a autorization token without using a webpage. Or you need to use a different authentication scheme than OAuth.

Categories