locked
Calling WebApi with with Toekn Authentication RRS feed

  • Question

  • User1122355199 posted

    Hello everyone and thanks for the help in advance.  This is a continuation from a previous post.  I'm learning token authentication for WebApi and want to call it from a Windows application.  I am confused as to the role of System.IdentityModel.Tokens.Jwt and when it should be used as opposed to OAuthAuthorizationServerOptions.  Are they just different implementations of token authentication.  Pros and cons?  Any help would be appreciated.

    Tuesday, October 15, 2019 6:38 PM

All replies

  • User475983607 posted

    System.IdentityModel.Tokens.Jwt  is a library for managing a JWT tokens.  These are things like creating a JWT token or reading claims from a JWT token.

    OAuthAuthorizationServerOptions are options passed to middleware that define the OAuth authorization configuration for a token server application.  

    Tuesday, October 15, 2019 9:31 PM
  • User1122355199 posted

    Thank you for the response.  But when do you implement each one?

    Tuesday, October 15, 2019 9:37 PM
  • User475983607 posted

    But when do you implement each one?
      

    You need to readjust your thinking...

    OAuthAuthorizationServerOptions is an OWIN middleware component for configuring an OAuth token server.   OAuth is a single sign on protocol for securing remote resources.  An OAuth server is a standalone service where clients can exchange valid credentials for a token.  The client sends the token when accessing secured remote resources.  These remote resource know the OAuth server and can validate the token.

    A JavaScript Web Token (JWT) is a type of token that is commonly used in OAuth.

    The following documentation covers many fundamental concepts related to OAuth, token, and security flows.

    https://docs.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server

    Tuesday, October 15, 2019 10:19 PM
  • User1122355199 posted

    Thanks again for the response.  So the System.IdentityModel.Tokens.Jwt is actually for the handling of the token itself once the middleware, such as OAuth, has generated the token.  Am I thinking correctly?

    Wednesday, October 16, 2019 1:57 AM
  • User475983607 posted

    So the System.IdentityModel.Tokens.Jwt is actually for the handling of the token itself once the middleware, such as OAuth, has generated the token.  Am I thinking correctly?

    Middleware runs in the HTTP pipeline and validates tokens.  Middleware does not create tokens.  The JWT library creates the JWT token which is usually code written in an action that looks up a user's account etc.  See my first thread. 

    Wednesday, October 16, 2019 10:00 AM
  • User1122355199 posted

    Thanks for the response.  Perhaps I can understand by posting some code.  In my startup.cs:

        public partial class Startup
        {
            //
            //  https://forums.asp.net/t/2132701.aspx?How+to+accept+and+pass+token+for+web+api+when+client+is+windows+client
            //
            public void Configuration(IAppBuilder app)
            {
                //ConfigureAuth(app);
    
                // Enable CORS (cross origin resource sharing) for making request using browser from different domains
                app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    
                OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
                {
                    AllowInsecureHttp = true,
    
                    //The Path For generating the Token
                    TokenEndpointPath = new PathString("/token"),
    
                    //Setting the Token Expired Time (24 hours)
                    AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
    
                    //MyAuthorizationServerProvider class will validate the user credentials
                    Provider = new MyAuthorizationServerProvider()
                };
    
                //Token Generations
                app.UseOAuthAuthorizationServer(options);
                app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    
                HttpConfiguration config = new HttpConfiguration();
                WebApiConfig.Register(config);
    
            }
        }

    What is generating the token.  Using postman, posting valid credentials to http://localhost/token generates what appears to be a valid token.  I have not even added JWT to the project, so what is creating the token?  Identity Framework?

    Wednesday, October 16, 2019 2:34 PM
  • User475983607 posted

    I think part of the confusion is you are configuring an entire OAuth server when really you just want a simple token auth example. 

    Below is a simple token auth ASP.NET Core example.

    appsetting.json

    {
      "Tokens": {
        "Issuer": true,
        "Key": "DEF74CFD-1743-4438-8DF1-0F3056406508"
      },
      "Logging": {
        "LogLevel": {
          "Default": "Warning"
        }
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
        "JwtApiContextConnection": "Server=(localdb)\\mssqllocaldb;Database=JwtApi;Trusted_Connection=True;MultipleActiveResultSets=true"
      }
    }

    Startup.cs

            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddAuthentication()
                  .AddJwtBearer(cfg =>
                  {
                      cfg.RequireHttpsMetadata = false;
                      cfg.SaveToken = true;
    
                      cfg.TokenValidationParameters = new TokenValidationParameters()
                      {
                          ValidIssuer = Configuration["Tokens:Issuer"],
                          ValidAudience = Configuration["Tokens:Issuer"],
                          IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
                      };
    
                  });
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
    
                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseAuthentication();
                app.UseMvc();
    
            }
        }

    Model

        public class LoginViewModel
        {
            [Required]
            [EmailAddress]
            public string Email { get; set; }
    
            [Required]
            [DataType(DataType.Password)]
            public string Password { get; set; }
    
            [Display(Name = "Remember me?")]
            public bool RememberMe { get; set; }
        }

    Token controller

        [Route("api/[controller]")]
        [ApiController]
        public class TokenController : ControllerBase
        {
            private readonly IConfiguration _config;
    
            public TokenController(IConfiguration config)
            {
                _config = config;
            }
    
            //GET: api/token
            [HttpPost]
            public IActionResult GenerateToken([FromBody] LoginViewModel model)
            {
                var claims = new Claim[]
                {
                    new Claim(JwtRegisteredClaimNames.Sub, model.Email)
                };
    
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    
                var token = new JwtSecurityToken(_config["Tokens:Issuer"],
                  _config["Tokens:Issuer"],
                  claims,
                  expires: DateTime.Now.AddMinutes(30),
                  signingCredentials: creds);
    
                return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
            }
        }

    Secured controller

        [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
        [Route("api/[controller]")]
        [ApiController]
        public class ValuesController : ControllerBase
        {
             // GET api/values
            [HttpGet]
            public ActionResult<IEnumerable<string>> Get()
            {
                return new string[] { "value1", "value2" };
            }

    The generate token method does not valid the user credentials, it just generates a token.   You can add your own data access layer to lookup the user and add whatever claims/roles you like.

    Wednesday, October 16, 2019 3:24 PM
  • User1122355199 posted

    Thanks so much for the response.  I'm going to wade into the stupid end of the pool.  What is the difference between running an OAuth server or the JWT token example you provided.  I understand it works, but I'm confused when to use each implementation.

    Thanks again.

    Wednesday, October 16, 2019 11:17 PM
  • User1724605321 posted

    Hi kncnet ,

    You codes seems using OAuth token server  work as identity provider for issue/validate token , sso and so on .   It will issue jwt tokens which could be used to identify user and accessing protected resources . And @mgebhard's code will help you understand how to issue/validate token between client app and IDP app

    Best Regards,

    Nan Yu

    Thursday, October 17, 2019 5:27 AM
  • User475983607 posted

    What is the difference between running an OAuth server or the JWT token example you provided. 

    OAuth is a protocol.  Use OAuth when you want to create a Single Sign On (SSO) solution that supports many different types of clients using industry standard security best practices.   The following link was in the docs now moved to GIT but it show how to configure the OAuth Server API for different clients.

    https://github.com/andrewlock/Docs/blob/master/aspnet/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server.md

    The JWT example illustrates the OAuth Password Grant flow by manually building a JWT and showing how to configure middleware to wire up the standard MVC [Authorize] attribute.  This is the same flow you've configured in your previous thread using the OAuth Server API.

    I understand it works, but I'm confused when to use each implementation.

    From my perspective, it seems you are asking the same question over and over and not reading the links or doing any research.  OAuth is vast subject with a fairly steep learning curve depending on your experience in building secure applications.  OAuth is not a subject you can learn from a forum response.  You actually have to spend time learning.  I prefer the RFCs; https://tools.ietf.org/html/rfc6749

    Thursday, October 17, 2019 10:20 AM