简体   繁体   中英

Using Bearer/Jwt authorization without Identity

I'm developing a Web API with Asp 5 and reading some documents about Web API realize I need Bearer authorization.

After searching I can't find any document or sample that use authorization without Aspnet.Identity . I have my own membership and I don't want to use Identity
Should I use Identity library? or is there a way to implement authorization in my membership.

One little side question:
if I'm forced to use Identity how can I change EntityFramework to something like dapper or ADO.NET for my DBContext ?

To issue your own JWT tokens, you can use OpenIddict :

project.json

{
  "dependencies": {
    // ...
    "AspNet.Security.OAuth.Validation": "1.0.0-*",
    "OpenIddict": "1.0.0-*",
    "OpenIddict.EntityFrameworkCore": "1.0.0-*",
    "OpenIddict.Mvc": "1.0.0-*"
  }
}

Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        services.AddDbContext<DbContext>(options =>
        {
            // Configure the context to use an in-memory store.
            options.UseInMemoryDatabase();

            // Register the entity sets needed by OpenIddict.
            // Note: use the generic overload if you need
            // to replace the default OpenIddict entities.
            options.UseOpenIddict();
        });

        services.AddOpenIddict(options =>
        {
            // Register the Entity Framework stores.
            options.AddEntityFrameworkCoreStores<DbContext>();

            // Register the ASP.NET Core MVC binder used by OpenIddict.
            // Note: if you don't call this method, you won't be able to
            // bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
            options.AddMvcBinders();

            // Enable the token endpoint.
            options.EnableTokenEndpoint("/connect/token");

            // Enable the password flow.
            options.AllowPasswordFlow();

            // During development, you can disable the HTTPS requirement.
            options.DisableHttpsRequirement();
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        // Register the validation middleware, that is used to decrypt
        // the access tokens and populate the HttpContext.User property.
        app.UseOAuthValidation();

        // Register the OpenIddict middleware.
        app.UseOpenIddict();

        app.UseMvcWithDefaultRoute();
    }
}

AuthorizationController.cs

public class AuthorizationController : Controller
{
    [HttpPost("~/connect/token"), Produces("application/json")]
    public IActionResult Exchange(OpenIdConnectRequest request)
    {
        if (request.IsPasswordGrantType())
        {
            // Validate the user credentials.
            // Note: to mitigate brute force attacks, you SHOULD strongly consider
            // applying a key derivation function like PBKDF2 to slow down
            // the password validation process. You SHOULD also consider
            // using a time-constant comparer to prevent timing attacks.
            if (request.Username != "alice@wonderland.com" ||
                request.Password != "P@ssw0rd")
            {
                return Forbid(OpenIdConnectServerDefaults.AuthenticationScheme);
            }

            // Create a new ClaimsIdentity holding the user identity.
            var identity = new ClaimsIdentity(
                OpenIdConnectServerDefaults.AuthenticationScheme,
                OpenIdConnectConstants.Claims.Name,
                OpenIdConnectConstants.Claims.Role);

            // Add a "sub" claim containing the user identifier, and attach
            // the "access_token" destination to allow OpenIddict to store it
            // in the access token, so it can be retrieved from your controllers.
            identity.AddClaim(OpenIdConnectConstants.Claims.Subject,
                "71346D62-9BA5-4B6D-9ECA-755574D628D8",
                OpenIdConnectConstants.Destinations.AccessToken);

            identity.AddClaim(OpenIdConnectConstants.Claims.Name, "Alice",
                OpenIdConnectConstants.Destinations.AccessToken);

            // ... add other claims, if necessary.
            var principal = new ClaimsPrincipal(identity);

            // Ask OpenIddict to generate a new token and return an OAuth2 token response.
            return SignIn(principal, OpenIdConnectServerDefaults.AuthenticationScheme);
        }

        throw new InvalidOperationException("The specified grant type is not supported.");
    }
}

Request

POST /connect/token HTTP/1.1
Host: localhost:7096
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=alice%40wonderland.com&password=P%40ssw0rd

Response

{
  "token_type": "Bearer",
  "access_token": "CfDJ8Ec0ZpniaHhGg0e0UUvOH9BWZSGrPoEwGd0_Lq2cse-T29YOq985IBiT5fEe5tTSgY1vxq2Z2ZJ7Ikwlpmh0Lrc4x9pqhqHBziUzsP_rkGZkn47TkNkOkzKCwZJZK5x-irH3HROwClFFTq0rgWdb8rZ2xriffNzsby4VwhxhN5soFD435KzmVYkdv-VuaLYo3QiSuexbRi2USVO9LK30vomAG6h2SAxZ7R-jYsXgf0f5gAmdYxg7w3yicv9v8DpUSBiGGRRfymTOnvGEsFJjGuuP8OlY5qzMs6wGaRWkOvCyV2CK_RZF_3TMs7LYCdMQ-dqWY5A03-03OmP8blKzlrKJMDZfrPQHuysbS931xxy8b3kjicfjNLmMHqzQzbUO4fecm4kY8PFnKozojDtqajfTp2bYhxS65bmVYROrswYeUWEKYR6LSdS1K__IDaLoMlLa-Wf6x1wjM2CchzgqbHRF0KEtdL5Ks88dAS44mp9BM6iUOEWyL7VkbazsBdlNciM5ZZB1_6qunufDW_tcaR8",
  "expires_in": 3600
}

For more information, you can read this blog post I wrote about OpenIddict: http://kevinchalet.com/2017/01/30/implementing-simple-token-authentication-in-aspnet-core-with-openiddict/

There's already a JWT Bearer middleware , you just need to write something that issues bearer tokens. That's a little more complicated, depending on what you use as your identity store, and as you indicate it's something custom, it's hard to advise on any approach. Creating JWT tokens isn't that hard though;

var now = DateTime.UtcNow;

// Creates new keys automatically, you'd want to store these somewhere
var aes = new AesCryptoServiceProvider();

var signingTokenHandler = new JwtSecurityTokenHandler();
var tokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(
                new[]
                {
                    new Claim(JwtRegisteredClaimNames.Aud, "YOURWEBSITEURL")                    }),
                    TokenIssuerName = "YourWebSite",
                    Lifetime = new Lifetime(now, now.AddHours(1)),
                    SigningCredentials = new SigningCredentials(
                        new InMemorySymmetricSecurityKey(aes.Key),
                        "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
                        "http://www.w3.org/2001/04/xmlenc#sha256")
                };

var token = signingTokenHandler.CreateToken(tokenDescriptor);
var tokenAsString = signingTokenHandler.WriteToken(token);

None of the authorization pieces depend on membership at all, they'll work with any authentication middleware. None of the documentation for authorization even refers to Identity at all.

There's an authorization workshop available. You can see in the source for that that no-one does identity appear, it's creating user principals on the fly and then storing them in cookies.

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