简体   繁体   中英

Understanding Token Generation/Validation in ASP.NET (MVC, web API)

I am developing a MVC project in which I am generating a token to authorize anyone who has it to say the famous "Hello World!". Since I am a new one in ASP.NET I don't understand WHERE and WHO generates the token, and where (or how) is it saved once it is generated. Also I don't know Who validates the token once I launch a Get/Post with the token. The final purpose is to try to change the type of token generated, obtaining a new one like a JWT Token, instead of a Basic one. I'm using OWIN.

Here are the parts I think important to undestand all.

using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;
using ExampleToUnderstand.Models;
using ExampleToUnderstand.Providers;

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);
        app.UseWebApi(config);
    }
}

/*Following the partial class Startup.Auth.cs*/
public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
        var oAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            // AuthorizationCodeFormat = new JwtFormat(audienceId, new SymmetricKeyIssuerSecurityTokenProvider(issuer, signingKey)), // da togliere se non funziona
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(3),
            Provider = new AuthorizationProvider ()
        };
        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}

Then I developed a provider, following some guides, and the result is this:

using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security.OAuth;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Threading.Tasks;
 
public class AuthorizationProvider : OAuthAuthorizationServerProvider
{
    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
        var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
        IdentityUser user = await userManager.FindAsync(context.UserName, context.Password);
        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }
        
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        identity.AddClaim(new Claim(ClaimTypes.Role, "User"));
        context.Validated(identity);
    /*WHO GENERATES THE TOKEN HERE?? WHICH IS THE ALGHORITHM USED??*/
    }
}

Using Postman I obtain a result like this.

{
  "access_token": "mxHZZEFB6pAc6WnTkjeamyxgDMUVNy64CkmtTEwwN2yLZkDQkfDy3J6EIVVLDNRN1-XkeA50Xqk0oB9DEprEuCzGAdsgOG69iPUmf7i7OEZuJfnIXWf0S_qf23gsU5Ppr_lBnpP8pd1RRSQNwvFk_HiumdrJTm91cKenhvWEfbg8a9qhQCH4cwDCzbZ1mwR682WqApk0NOUK7w8UXR7kqIKrS9S2Y4azAvh-9zNWXB3lEkCtoZgDKgLBWotIc9cA8N5FVxd_WOYchA2BYBkgkisZtuW0CigJ4l5Om0zzJJypGGS22foyAdnHFbgkpcIW",
  "token_type": "bearer",
  "expires_in": 179
}

Invoking the following method I get "Hello World!".

/*Method inside Homecontroller.cs that extends a controller*/
[Route("/api/HelloWorld")]
[HttpGet]
[Authorize] // How does the authorization works? 
public string HelloWorld()
{
    return "Hello World";
}

So very good but I want to know How all it works. If anyone has suggestions, texts, valid books/guides sources or something else I'll be grateful!

Thanks in advance

"Also I don't know Who validates the token once I launch a Get/Post with the token. "

I believe somewhere in the request processing pipeline , checking is done to determine if the token is valid or not. if you take a look at the source code for AuthorizeAttribute

protected virtual bool IsAuthorized(HttpActionContext actionContext)
        {
            if (actionContext == null)
            {
                throw Error.ArgumentNull("actionContext");
            }

            IPrincipal user = actionContext.ControllerContext.RequestContext.Principal;
            if (user == null || user.Identity == null || !user.Identity.IsAuthenticated)
            {
                return false;
            }

            if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
            {
                return false;
            }

            if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
            {
                return false;
            }

            return true;
        }

The IsAuthenticated property for user identity is already set. So if your token is valid IsAuthenticated would be true.

The source code to AuthorizeAttribute can be found at here https://github.com/aspnet/AspNetWebStack/blob/main/src/System.Web.Http/AuthorizeAttribute.cs

According to this answer Where does Web API store generated tokens in order to validate subsequent requests?

it is the OAuthBearerAuthenticationMiddleware that consumes your token during the early stage of request pipeline

After doing some source code diving i found some information on OAuthBearerAuthenticationOptions and one of its property AccessTokenFormat

/// <summary>
        /// The data format used to un-protect the information contained in the access token.
        /// If not provided by the application the default data protection provider depends on the host server. 
        /// The SystemWeb host on IIS will use ASP.NET machine key data protection, and HttpListener and other self-hosted
        /// servers will use DPAPI data protection. If a different access token
        /// provider or format is assigned, a compatible instance must be assigned to the OAuthAuthorizationServerOptions.AccessTokenProvider 
        /// and OAuthAuthorizationServerOptions.AccessTokenFormat of the authorization server.
        /// </summary>
        public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; set; }

So when you are configuring your OAuthBearerAuthenticationOptions, if you didn't specify a AccessTokenFormat, then the default one will be used. And that depends on what host you are using.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM