Using Identity.UI in WebAPI project - c#

I'm pretty new to Asp.NET and would like some more information on how to proceed. I have a standard WebAPI project which contains the standard weather template - I'm trying to apply some authentication via registering/logging in. I know theres a way to have template do it for you when create project, but for web api it doesn't let you do a local database which I want.
So right now I've attached the Identity.UI package to give me access to this method and generate the migration for identity tables
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
which allows me to use the UserManager to register a user and for login I do this:
if (!ModelState.IsValid) return BadRequest();
var result = await m_userManager.FindByNameAsync(user.Email);
var correct = await m_userManager.CheckPasswordAsync(result, user.Password);
if (!correct) return BadRequest();
return Ok(new { token = m_tokenService.BuildToken(user.Email) });
My question is a correct way of handling registering and login via WebAPI because the Microsoft.AspNetCore.Identity.UI package as the name suggests provides razor pages for login/registering which I don't really need which makes me believe this isn't correct. Is there downside/problem doing it this way, or is this a cleaner way of doing this.

The default Microsoft.AspNetCore.Identity.UI package provides a razor page for login/registration that seems redundant for web api .
For implementing Microsoft identity on web api to handle basic individual user accounts , you could try to use JWT tokens , refer to the following links which are good tutorials about using JwtBearer Authentication in an ASP.NET Core API Project :
https://wildermuth.com/2018/04/10/Using-JwtBearer-Authentication-in-an-API-only-ASP-NET-Core-Project
https://dotnetdetail.net/asp-net-core-3-0-web-api-token-based-authentication-example-using-jwt-in-vs2019/

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

Identity Server 4 won't use custom Authentication Handler

I have a working AuthenticationHandler<> for MVC Core and it works beautifully. Now I want to re-use the whole thing for Identity Server 4 but the framework seems to work against me.
I have added
builder.Services.AddAuthentication().AddScheme<MyWebsiteOptions, MyWebsiteAuthenticationHandler<TIdentity, MyWebsiteUser>>(CredentialStoreConstants.SCHEMA_NAME, x => { x.ConnectionString = options.ConnectionString; });
And like I said it works 100% for the MVC Core-part. Now, I cannot access IdentityServer4 endpoints like /connect/authorize/callback with it. I have already read the Identity Server 4 documentation over and over again, but somehow I am missing some key thing here.
Does anyone has an idea? I am sure I am not the first person to run into this.
The Identityserver Endpoints are just that, plain endpoints implemented as a middleware for your pipeline.
The relevant files on the Identityserver4 are:
The Middleware: https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Hosting/IdentityServerMiddleware.cs
The Endpoint Router (and its interface): https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Hosting/EndpointRouter.cs
Endpoint Implementation (token endpoint for instance): https://github.com/IdentityServer/IdentityServer4/blob/master/src/IdentityServer4/src/Endpoints/TokenEndpoint.cs
This means they're out of MVC so you can't use your AuthenticationHandler with them
HINT: If you read all the documentation and the answer is not there, its time to dive into the code: https://github.com/IdentityServer/IdentityServer4
Answer. It was more obvious than I imagined it to be.
For the standard .NET Core Authentication, a succesfull pass at AuthenticationHandler<> in not enough
If you have a custom usertype and custom login flow, you also need to do something like this after you succesfully verified the credentials of said custom usertype.
At one point, you need to retrieve the corresponding user from the database and into the rest of the MVC Core authentication flow.
So after something like AuthenticationHandler<>().Succeeded == true you need to do this:
var systemUser = await _userResolver.GetUserAsync(user.Email);
await _signInManager.SignInAsync(systemUser, true);
The last line is the most important as it initializes a correct MVC Core user-session

Add token authentication for webApi controller to existing asp.net MVC 5 application

I currently have a Web API controller added to an existing MVC 5 project (not using .net core) and I was able to successfully create and get data from the controller that I have set up. The purpose of the API is to pass data between it and a mobile application that uses the same data source that the MVC project uses (I will also be calling existing methods in the project from the API so I would prefer the API exist in the MVC project). I am now looking for a way to add token authentication to the API, as I only want logged in users in the mobile application to be allowed to access the API. How can I achieve this?
The simplest solution should be to use the Token Validation Middleware from the IdentityServer 3 suite.Just add the nuget package and configure your application following the doc:
public class Startup
{
public void Configuration(IAppBuilder app)
{
// turn off any default mapping on the JWT handler
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44333/core",
RequiredScopes = new[] { "api1" }
});
app.UseWebApi(WebApiConfig.Register());
}
}
It's ok to set app.UseIdentityServerBearerTokenAuthentication() only prior to app.UseCookieAuthentication() and app.UseOpenIdConnectAuthentication() and call GlobalConfiguration.Configure(WebApiConfig.Register) in Global.asaxSuch approach allows to combine token and cookie-based auth in one MVC application.The only problem for today is that IdentityServer 3 family tools are frozen and support System.IdentityModel 4 and OWIN 3 only, so
update:
The preferred solution for ASP.NET 4.6+ becomes IdentityServer3.Contrib.AccessTokenValidation -- a fork, refactored according to the recent framework changes.

ASP.net core web api: Using Facebook/Google OAuth access token for authentication

For serveral days now I am trying to get OAuth authentication with Google and Facebook to work within my ASP.net core web api project.
my current status is:
I have an ASP.net core Web Api project in which the users need to be authenticated
I have an angular 2 web app which should use my web api (with authentication)
I have an android app, which should use my web api (with authentication)
my goal is:
Using Google/Facebook as OAuth providers for login
later: adding own user accounts (probably with IdentityServer4)
no need to redirect to a special login website (like the IdentityServer4 solution). Just hit the facebook/google button in the app, allow access, done!
In my android and angular app I am able to retrieve the access tokens from google/facebook. Now, I want to use the OAuth implicit flow, to authenticate the user on my web api, with the given access tokens (putting the tokens into the header as bearer token)
There is my problem: is there any genric way to do this easily? I do not want to use the facebook/google SDKs for this.
I have tried following:
using IdentityServer4: With this I am able to login with facebook/google on my webapi, but there is need of a redirection to the IdentityServer4 login page. Is there any possible way of just hitting the google/fb-Button in my app and logging in, without redirection to the identityServer login page?
using the google/facebook authentication middleware (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/): But they are not validating my sent bearer token (tried countless ways to achieve proper validation). Is this even possible to use within the web api?
trying to use Microsoft.AspNetCore.Authentication.JwtBearer-Middleware and putting in the necessary options for google/facebook by myself, but also not validating (aswell countless attempts)
In the last few days, I have tried so much possible solutions, that I am totally stuck and lost track of what I need to do to achieve this. At this point I have read nearly every asp.net web api oauth tutorial/stackoverflow entry but can't figure out how to use this in my case as I want. Most tutorials are just for mvc-Websites or using IdentityServer4 with the redirection to its login page.
Any suggestions or solutions? What am I missing?
If I undertsand correctly, you already have your Facebook user token from Facebook SDK through your app.
Like you I couldn't find how to do it with an ASP.NET Core library / package. So I went back to basics.
I just call a endpoint of my api with the Facebook token, check it against the Facebook graph api and if fine then I register the user (if required) and return my JWT token as if the user logged through a classical username / password path.
[HttpPost]
[AllowAnonymous]
[Route("api/authentication/FacebookLogin")]
public async Task<IActionResult> FacebookLogin([FromBody] FacebookToken facebookToken)
{
//check token
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.facebook.com/v2.9/") };
var response = await httpClient.GetAsync($"me?access_token={facebookToken.Token}&fields=id,name,email,first_name,last_name,age_range,birthday,gender,locale,picture");
if (!response.IsSuccessStatusCode) return BadRequest();
var result = await response.Content.ReadAsStringAsync();
var facebookAccount = JsonConvert.DeserializeObject<FacebookAccount>(result);
//register if required
var facebookUser = _context.FacebookUsers.SingleOrDefault(x => x.Id == facebookAccount.Id);
if (facebookUser == null)
{
var user = new ApplicationUser {UserName = facebookAccount.Name, Email = facebookAccount.Email};
var result2 = await _userManager.CreateAsync(user);
if (!result2.Succeeded) return BadRequest();
facebookUser = new FacebookUser {Id = facebookAccount.Id, UserId = user.Id};
_context.FacebookUsers.Add(facebookUser);
_context.SaveChanges();
}
//send bearer token
return Ok(GetToken(facebookUser.UserId));
}
You have to copy the custom code available in this article on medium
Creat a function in AccountController.cs
private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_WithExternalBearer()
And paste the code given in the article

Application and User Authentication using ASP.NET Core

Can anyone point me to some good documentation or provide good information on the best way to implement authentication and authorisation for an ASP.NET Core REST API.I need to authenticating and authorising the app first and then authenticate and authorise the user.
Ideally I want to be able restrict the controller method that an authenticated app and/or user can access.
I am thinking of using AspNet.Security.OpenIdConnect.Serverenter for the App authentication but I am not sure then how best to perform the user authentication. Maybe reuse the OpenIdConnect authentication on a different endpoint for users with a different header to contain the user token.
Once authenticated I am thinking of just using roles base security to restrict which controllers methods can be accessed.
Is this the correct route to solving this problem?
This is actually a tougher question that that it may seem because the type of clients (software clients) that are using the api seem to drive what kind of auth* is needed. For example, in a web application, where the web application needs auth*, then Asp.Net Identity would work with either a token or a cookie. However, if other clients are going to consume the provided services (mobile apps, WUP apps, then it may be easier to implement using token authentication . When I had this problem, I ran into the issue that I had a knowledge gap because I didn't really understand OAuth. I had to get back to basics.
https://alexbilbie.com/guide-to-oauth-2-grants/
https://www.pluralsight.com/courses/oauth2-json-web-tokens-openid-connect-introduction
Most of the tutorials around Asp.Net Identity "Seem" to be geared towards web clients. Although it is possible to find those that are not. With the introduction of asp.net core, the syntax has changed and many of the old tutorials that show combining cookie and token authentication are no longer applicable. Additionally, Web Api is not longer a separated from other project types in Visual Studio making the change even more pronounced. Here are some older tutorials.
http://satvasolutions.com/combine-asp-net-identity-web-api-and-mvc-best-in-a-single-web-app/
http://blog.iteedee.com/2014/03/asp-net-identity-2-0-cookie-token-authentication/
Combine the use of authentication both for MVC pages and for Web API pages?
IdentityServer is a completely valid solution, works with both client credential and Resource owner credentials grant (user,password) and Brock Allen has usually been very responsive in SO under the tag
https://stackoverflow.com/questions/tagged/identityserver4
or on the github site under issues labeled as questions
https://github.com/IdentityServer/IdentityServer4/issues
With identity server, Once again, I had to go back to basics and work through the tutorials to get an understanding of how this would work in my project.
https://identityserver4.readthedocs.io/en/release/intro/big_picture.html
As Brock quickly pointed out to me in another post, asp.net ef identity is a user store and good to use with the resource owner credentials workflow.
For authentication you can use ASP.NET Core Identity that will use the Microsoft.AspNetCore.Identity.EntityFrameworkCore package, which will persist the identity data and schema to SQL Server using Entity Framework Core.
For authorization you can use Role Based Authorization that uses the Microsoft.AspNetCore.Authorization package.
You can also checkout this video for an overview on ASP.NET Core Authorization
I couldn't find any good documentation on this, however I had to achieve the same thing so I coded the rest api myself by modifying the actions in the standard ASP.NET authentication template to REST API equivalents.
For example here is how I worked the login action:
// POST: /Account/Login
[HttpPost("[action]")]
[AllowAnonymous]
public async Task<ReturnValue<ApplicationUser>> Login([FromBody] loginModel login)
{
if (ModelState.IsValid)
{
ApplicationUser user = await _userManager.FindByEmailAsync(login.email);
if (user == null)
{
return new ReturnValue<ApplicationUser>(false, "Login failed, check username and password.", null);
}
// else if (user.EmailConfirmed == false)
// {
// return new ReturnValue<ApplicationUser>(true, "Confirm email address.", null, user);
// }
else
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(user, login.password, (bool)login.rememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return new ReturnValue<ApplicationUser>(true, user);
}
//if (result.RequiresTwoFactor)
//{
// return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
//}
if (result.IsLockedOut)
{
return new ReturnValue<ApplicationUser>(false, "The account is locked out.", null);
}
}
}
else
{
string message = string.Join("; ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage));
return new ReturnValue<ApplicationUser>(false, "Invalid login attempt: " + message, null);
}
// If we got this far, something failed in the model.
return new ReturnValue<ApplicationUser>(false, "Login failed.", null);
}
If you call the API from a javascript within a browser the cookies will be loaded and you should be able to make further authorised calls to the API, if you're calling from another type of client, you will want to ensure the CookieContainer is retained for authorized calls.
From this point you can authorize your REST API controllers using [Authorize] decorator through the standard Microsoft libraries: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity
Good luck.
Here it is:
A workshop for moving through the various new pieces in ASP.NET Core Authorization:
https://blogs.msdn.microsoft.com/webdev/2016/03/15/get-started-with-asp-net-core-authorization-part-1-of-2/
https://github.com/blowdart/AspNetAuthorizationWorkshop
Please refer following links.
For Asp.net Core
https://stormpath.com/blog/token-authentication-asp-net-core
For API
https://stormpath.com/blog/rest-api-mobile-dotnet-core

Categories