Michael Edwards
Michael Edwards

Reputation: 6518

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?

Upvotes: 24

Views: 7136

Answers (5)

error505
error505

Reputation: 1216

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

Upvotes: 1

Bill
Bill

Reputation: 1261

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.

Upvotes: 7

S.Dav
S.Dav

Reputation: 2466

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

Upvotes: 5

Gary Holland
Gary Holland

Reputation: 2645

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.

Upvotes: 1

Related Questions