openiddict / openiddict-core

Flexible and versatile OAuth 2.0/OpenID Connect stack for .NET
https://openiddict.com/
Apache License 2.0
4.36k stars 510 forks source link

Migration from v2 to v3 rc1 - Login success, Authorize Failed - Bug? #1182

Closed Gillardo closed 3 years ago

Gillardo commented 3 years ago

I have converted my code from v2 to v3 by checking all the samples but the [Authorize] tag doesn't seem to be working. You can login successfully but the token cannot be used to successfully connect to a secure endpoint.

I have added the issue to github here and gather something is wrong with the samples in comparison to v2, or something not obvious.

Any help much appreciated, i am using EF6

kevinchalet commented 3 years ago

Hi,

Hard to say without seeing the logs or knowing what's the WWW-Authenticate header value returned, but I suspect it's because you're using both the JWT middleware and the OpenIddict validation handler. It's likely that your API controllers use the first one instead of the OpenIddict handler.

Can you please share your logs?

Gillardo commented 3 years ago

I have tried to remove the UseJwtBearer part but that doesnt seem to work either. Happy to share logs but not sure which one you mean (sorry)

kevinchalet commented 3 years ago

Please post the entire logs of the server app.

Gillardo commented 3 years ago

Sorry @kevinchalet running this via dotnet watch run not IIS so havent got any logs. I can copy and paste the console output? Sorry if i am missing something stupid

Gillardo commented 3 years ago
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/cms/home application/json - - 200 - application/json;+charset=utf-8 35.3573ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/connect/token application/x-www-form-urlencoded 117
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:23.941]: The request address matched a server endpoint: Token.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:23.958]: The token request was successfully extracted: {
        "username": "poweruser@measure2improve.com",
        "password": "[redacted]",
        "grant_type": "password",
        "scope": "openid profile email offline_access"
      }.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:23.987]: The token request was successfully validated.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      [13:33:23.990]: Executing endpoint 'm2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "Exchange", controller = "Authorization"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] Exchange() on controller m2i.Activ.Web.Features.Authorization.AuthorizationController (m2i.Activ.Web).
info: Microsoft.AspNetCore.Mvc.SignInResult[1]
      Executing SignInResult with authentication scheme (OpenIddict.Server.AspNetCore) and the following principal: System.Security.Claims.ClaimsPrincipal.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.213]: An ad hoc authorization was automatically created and associated with an unknown application: 489f1d35-07d7-415b-a317-1e485db9e6a3.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.492]: The response was successfully returned as a JSON document: {
        "access_token": "[redacted]",
        "token_type": "Bearer",
        "expires_in": 3600,
        "id_token": "[redacted]",
        "refresh_token": "[redacted]"
      }.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
      Executed action m2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web) in 502.6874ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      [13:33:24.496]: Executed endpoint 'm2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 POST http://localhost:5000/connect/token application/x-www-form-urlencoded 117 - 200 - application/json;charset=UTF-8 561.4510ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 OPTIONS http://localhost:5000/account - -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 OPTIONS http://localhost:5000/account - - - 204 - - 0.1460ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/account application/json -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 OPTIONS http://localhost:5000/account/role - -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 OPTIONS http://localhost:5000/account/role - - - 204 - - 0.0805ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/account/role application/json -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/.well-known/openid-configuration - -
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.594]: The request address matched a server endpoint: Configuration.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.599]: The configuration request was successfully extracted: {}.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.602]: The configuration request was successfully validated.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.619]: The response was successfully returned as a JSON document: {
        "issuer": "http://localhost:5000/",
        "authorization_endpoint": "http://localhost:5000/connect/authorize",
        "token_endpoint": "http://localhost:5000/connect/token",
        "end_session_endpoint": "http://localhost:5000/connect/logout",
        "jwks_uri": "http://localhost:5000/.well-known/jwks",
        "grant_types_supported": [
          "password",
          "refresh_token",
          "urn:m2i:params:oauth:grant-type:impersonate_user",
          "urn:m2i:params:oauth:grant-type:activ_id"
        ],
        "scopes_supported": [
          "openid",
          "offline_access",
          "email",
          "profile",
          "roles"
        ],
        "claims_supported": [
          "aud",
          "exp",
          "iat",
          "iss",
          "sub"
        ],
        "id_token_signing_alg_values_supported": [
          "RS256"
        ],
        "subject_types_supported": [
          "public"
        ],
        "token_endpoint_auth_methods_supported": [
          "client_secret_basic",
          "client_secret_post"
        ],
        "claims_parameter_supported": false,
        "request_parameter_supported": false,
        "request_uri_parameter_supported": false
      }.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/.well-known/openid-configuration - - - 200 1029 application/json;charset=UTF-8 26.9874ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/.well-known/jwks - -
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.702]: The request address matched a server endpoint: Cryptography.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.703]: The cryptography request was successfully extracted: {}.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.705]: The cryptography request was successfully validated.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:33:24.733]: The response was successfully returned as a JSON document: {
        "keys": [
          {
            "kid": "7032AEBAB786CB3A1FB779567CA4FF5588791B41",
            "use": "sig",
            "kty": "RSA",
            "alg": "RS256",
            "e": "AQAB",
            "n": "yBwWSF-kcRQqSMtr9sRmoGf0P0cLmcNSAH1cE80FUfVH0kJFN_LY7vC9W-Eb-KgIkZdiDxRt632bke1H6b2wGiWzCcNzNkcWXm1vuXe2kB5smNs79IYM3TmQ8wF8kIuGNkoEWo3yJG1SKdXgWaJ-e1xxkEleyFKfGeOkpbHmNCH9S7ExV4UT207hXAzlyVKVDnnNe0M6OLnlDYFCRIVxsYdAi1Btu14T4EEARYoBWn_jNBjNTu-8ZqcxrXtx4kaZ9adb71oZkCaIZg44kHAS9YS2Zown0MrbL9zO3bDbtamX_1WbUIFtiJDhmOgv_rJXfkwsxHFTZY0uKv79-ZnrbQ",
            "x5t": "cDKuureGyzoft3lWfKT_VYh5G0E",
            "x5c": [
              "MIIC9TCCAd2gAwIBAgIJAICQX/CCPpPaMA0GCSqGSIb3DQEBCwUAMDAxLjAsBgNVBAMTJU9wZW5JZGRpY3QgU2VydmVyIFNpZ25pbmcgQ2VydGlmaWNhdGUwHhcNMjAxMTI2MTI0MjU0WhcNMjIxMTI2MTI0MjU0WjAwMS4wLAYDVQQDEyVPcGVuSWRkaWN0IFNlcnZlciBTaWduaW5nIENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyBwWSF+kcRQqSMtr9sRmoGf0P0cLmcNSAH1cE80FUfVH0kJFN/LY7vC9W+Eb+KgIkZdiDxRt632bke1H6b2wGiWzCcNzNkcWXm1vuXe2kB5smNs79IYM3TmQ8wF8kIuGNkoEWo3yJG1SKdXgWaJ+e1xxkEleyFKfGeOkpbHmNCH9S7ExV4UT207hXAzlyVKVDnnNe0M6OLnlDYFCRIVxsYdAi1Btu14T4EEARYoBWn/jNBjNTu+8ZqcxrXtx4kaZ9adb71oZkCaIZg44kHAS9YS2Zown0MrbL9zO3bDbtamX/1WbUIFtiJDhmOgv/rJXfkwsxHFTZY0uKv79+ZnrbQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAKnjpzcrz4FRODhXk+5HNSQPxC9ietsLHbGO2Zwh/t2tWugfLjSJxzUQ/uAbWMkiD2/m8QtbTE2V7sr3iRVKXCETrSsc3DmEokv938mZl9Y8I+M8jYDUMFJ/dYI/gXIPeL6C1G1qEVJe3i9g7DCpdyvp7ehtCn2bHrrQvdJR4G1xvpSktLYCp8Gs83iE3nwn5y2hMnKoNVL49GCFKi8wz7xTG1Z4+dNhivgvr3OUedTQNsAF/H7gwWeen4uGnO2v7ZS2Br6Xq3+gtlof2W+kpHJghvHHPQXSO123yFVm0jjzR2rrcCaXGKhohRMgdedslk21cL8mEbveMjrF98xoRf8="
            ]
          }
        ]
      }.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/.well-known/jwks - - - 200 1635 application/json;charset=UTF-8 37.8473ms
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[1]
      Failed to validate the token.
      Microsoft.IdentityModel.Tokens.SecurityTokenDecryptionFailedException: IDX10609: Decryption failed. No Keys tried: token: 'System.String'.
         at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.ValidateDecryption(JwtTokenDecryptionParameters decryptionParameters, Boolean decryptionSucceeded, Boolean algorithmNotSupportedByCryptoProvider, StringBuilder exceptionStrings, StringBuilder keysAttempted)
         at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.DecryptJwtToken(SecurityToken jwtToken, TokenValidationParameters validationParameters, JwtTokenDecryptionParameters decryptionParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.DecryptToken(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
         at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[1]
      Failed to validate the token.
      Microsoft.IdentityModel.Tokens.SecurityTokenDecryptionFailedException: IDX10609: Decryption failed. No Keys tried: token: 'System.String'.
         at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.ValidateDecryption(JwtTokenDecryptionParameters decryptionParameters, Boolean decryptionSucceeded, Boolean algorithmNotSupportedByCryptoProvider, StringBuilder exceptionStrings, StringBuilder keysAttempted)
         at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.DecryptJwtToken(SecurityToken jwtToken, TokenValidationParameters validationParameters, JwtTokenDecryptionParameters decryptionParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.DecryptToken(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
         at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7]
      Bearer was not authenticated. Failure message: IDX10609: Decryption failed. No Keys tried: token: 'System.String'.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7]
      Bearer was not authenticated. Failure message: IDX10609: Decryption failed. No Keys tried: token: 'System.String'.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      [13:33:24.811]: Authorization failed. These requirements were not met:
      DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      [13:33:24.811]: Authorization failed. These requirements were not met:
      DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
      AuthenticationScheme: Bearer was challenged.
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
      AuthenticationScheme: Bearer was challenged.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/account application/json - - 401 0 - 317.5115ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/account/role application/json - - 401 0 - 314.7355ms
kevinchalet commented 3 years ago

OpenIddict uses MSFT's ILogger so you'll need to make sure it's correctly configured: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-5.0 should put you on the right track.

kevinchalet commented 3 years ago

Yeah, the logs confirm was I suspected: your API controllers use the JWT handler, which is not configured with the encryption key used by OpenIddict to encrypt your access tokens.

Make sure your API controllers use [Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)].

Gillardo commented 3 years ago

Should removing the `.AddJwtBearer' fix this? Just wondering as i have removed it and it doesnt.

Just encase it should, here are the logs?

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/connect/token application/x-www-form-urlencoded 117
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:37:22.947]: The request address matched a server endpoint: Token.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:37:22.963]: The token request was successfully extracted: {
        "username": "poweruser@measure2improve.com",
        "password": "[redacted]",
        "grant_type": "password",
        "scope": "openid profile email offline_access"
      }.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:37:22.996]: The token request was successfully validated.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      [13:37:23.000]: Executing endpoint 'm2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "Exchange", controller = "Authorization"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] Exchange() on controller m2i.Activ.Web.Features.Authorization.AuthorizationController (m2i.Activ.Web).
info: Microsoft.AspNetCore.Mvc.SignInResult[1]
      Executing SignInResult with authentication scheme (OpenIddict.Server.AspNetCore) and the following principal: System.Security.Claims.ClaimsPrincipal.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:37:23.548]: An ad hoc authorization was automatically created and associated with an unknown application: 1c0f6f78-9c37-47ce-b859-72ca0d1db319.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [13:37:23.849]: The response was successfully returned as a JSON document: {
        "access_token": "[redacted]",
        "token_type": "Bearer",
        "expires_in": 3599,
        "id_token": "[redacted]",
        "refresh_token": "[redacted]"
      }.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
      Executed action m2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web) in 851.0873ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      [13:37:23.855]: Executed endpoint 'm2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 POST http://localhost:5000/connect/token application/x-www-form-urlencoded 117 - 200 - application/json;charset=UTF-8 922.2811ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 OPTIONS http://localhost:5000/account - -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 OPTIONS http://localhost:5000/account - - - 204 - - 0.5326ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 OPTIONS http://localhost:5000/account/role - -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 OPTIONS http://localhost:5000/account/role - - - 204 - - 0.1516ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/account application/json -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/account/role application/json -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      [13:37:23.872]: Authorization failed. These requirements were not met:
      DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      [13:37:23.872]: Authorization failed. These requirements were not met:
      DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
      AuthenticationScheme: Identity.Application was challenged.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
      AuthenticationScheme: Identity.Application was challenged.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/account application/json - - 401 0 - 12.4774ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/account/role application/json - - 401 0 - 10.8024ms

By adding the code that you stated, that seems to work, although i do get this in the logs.

info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[1]
      Failed to validate the token.
      Microsoft.IdentityModel.Tokens.SecurityTokenDecryptionFailedException: IDX10609: Decryption failed. No Keys tried: token: 'System.String'.
         at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.ValidateDecryption(JwtTokenDecryptionParameters decryptionParameters, Boolean decryptionSucceeded, Boolean algorithmNotSupportedByCryptoProvider, StringBuilder exceptionStrings, StringBuilder keysAttempted)
         at Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities.DecryptJwtToken(SecurityToken jwtToken, TokenValidationParameters validationParameters, JwtTokenDecryptionParameters decryptionParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.DecryptToken(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
         at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
         at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7]
      Bearer was not authenticated. Failure message: IDX10609: Decryption failed. No Keys tried: token: 'System.String'.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]

I would happily remove JwtBearer if that is the better way to go wtih v3, but i need to be able to set the Authority and Audience, can i do that with openid directly?

kevinchalet commented 3 years ago

Should removing the `.AddJwtBearer' fix this? Just wondering as i have removed it and it doesnt.

Yeah, remove it. The OpenIddict validation handler offers a simpler configuration story, uses a newer JWT stack under the hood and is the recommended way in 3.0.

but i need to be able to set the Authority and Audience, can i do that with openid directly?

If you use options.UseLocalServer(), there's no need to set the authority, as the OpenIddict server config' is directly imported in-memory.

Regarding the audience, validation is not enforced by default, but you can register valid audiences via OpenIddictValidationBuilder.

Gillardo commented 3 years ago

Ok i have tried this but i still have a problem.

So i have removed JwtBearer, so my startup code looks like so

// the default value for AllowuserNameCharacters is "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+"
// here we have just added some additional characters
services.AddIdentity<User, Role>(options => { options.User.AllowedUserNameCharacters += "'&"; })
    .AddDefaultTokenProviders();

// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
services.Configure<IdentityOptions>(options =>
{
    options.ClaimsIdentity.UserNameClaimType = Claims.Name;
    options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
    options.ClaimsIdentity.RoleClaimType = Claims.Role;
});

// return unauthorized message instead of url
services.ConfigureApplicationCookie(options =>
{
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.StatusCode = 401;
        return System.Threading.Tasks.Task.CompletedTask;
    };
});

// configure all tokens generated from aspnet to expire in 3 days (create password, forget password etc)
services.Configure<DataProtectionTokenProviderOptions>(options => options.TokenLifespan = TimeSpan.FromDays(3));

// Authentication
var authenticationBuilder = services.AddAuthentication();

// OpenIddict
services.AddOpenIddict()
    .AddCore(options =>
    {
        options.UseEntityFramework(e => e.UseDbContext<ApplicationDbContext>());
    })
    .AddServer(options =>
    {
        // For token lifetimes look at the below link
        // https://github.com/openiddict/openiddict-core/wiki/Configuration-and-options

        // Enable the authorization, logout, token endpoints.
        options.SetAuthorizationEndpointUris("/connect/authorize")
               .SetLogoutEndpointUris("/connect/logout")
               .SetTokenEndpointUris("/connect/token");

        // Note: the Mvc.Client sample only uses the code flow and the password flow, but you
        // can enable the other flows if you need to support implicit or client credentials.
        options.AllowPasswordFlow()
               .AllowRefreshTokenFlow();

        // Mark the "email", "profile" and "roles" scopes as supported scopes.
        options.RegisterScopes(Scopes.Email,
                               Scopes.Profile,
                               Scopes.OpenId,
                               Scopes.OfflineAccess,
                               Scopes.Roles);

        // code to allow requests without client_id
        options.AcceptAnonymousClients();

        // Register a new ephemeral key, that is discarded when the application
        // shuts down. Tokens signed using this key are automatically invalidated.
        // This method should only be used during development.
        options.AddDevelopmentEncryptionCertificate()
               .AddDevelopmentSigningCertificate();

        // 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.UseAspNetCore()
               .EnableAuthorizationEndpointPassthrough()
               .EnableLogoutEndpointPassthrough()
               .EnableTokenEndpointPassthrough()
               .DisableTransportSecurityRequirement();  // Never use https because we use load balancer
    })
    .AddValidation(options =>
    {
        // Import the configuration from the local OpenIddict server instance.
        options.UseLocalServer();

        // set the audience
        options.AddAudiences(appSettings.ApiUrl);

        // Register the ASP.NET Core host.
        options.UseAspNetCore();
    });

But you can see that it says I get an error still [14:34:09.454]: Authorization failed. These requirements were not met: DenyAnonymousAuthorizationRequirement: Requires an authenticated user.. This is still by using the standard [Authorize] attribute.

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 POST http://localhost:5000/connect/token application/x-www-form-urlencoded 117
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [14:34:08.843]: The request address matched a server endpoint: Token.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [14:34:08.855]: The token request was successfully extracted: {
        "username": "poweruser@measure2improve.com",
        "password": "[redacted]",
        "grant_type": "password",
        "scope": "openid profile email offline_access"
      }.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [14:34:08.883]: The token request was successfully validated.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      [14:34:08.887]: Executing endpoint 'm2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "Exchange", controller = "Authorization"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] Exchange() on controller m2i.Activ.Web.Features.Authorization.AuthorizationController (m2i.Activ.Web).
info: Microsoft.AspNetCore.Mvc.SignInResult[1]
      Executing SignInResult with authentication scheme (OpenIddict.Server.AspNetCore) and the following principal: System.Security.Claims.ClaimsPrincipal.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [14:34:09.126]: An ad hoc authorization was automatically created and associated with an unknown application: f3219807-e6f3-4303-b0b2-1ed4061fbfa2.
info: OpenIddict.Server.OpenIddictServerDispatcher[0]
      [14:34:09.439]: The response was successfully returned as a JSON document: {
        "access_token": "[redacted]",
        "token_type": "Bearer",
        "expires_in": 3600,
        "id_token": "[redacted]",
        "refresh_token": "[redacted]"
      }.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
      Executed action m2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web) in 551.7849ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      [14:34:09.442]: Executed endpoint 'm2i.Activ.Web.Features.Authorization.AuthorizationController.Exchange (m2i.Activ.Web)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 POST http://localhost:5000/connect/token application/x-www-form-urlencoded 117 - 200 - application/json;charset=UTF-8 604.1041ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 OPTIONS http://localhost:5000/account - -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 OPTIONS http://localhost:5000/account - - - 204 - - 0.1323ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/account application/json -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 OPTIONS http://localhost:5000/account/role - -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 OPTIONS http://localhost:5000/account/role - - - 204 - - 0.1022ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/account/role application/json -
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
      CORS policy execution successful.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      [14:34:09.454]: Authorization failed. These requirements were not met:
      DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      [14:34:09.454]: Authorization failed. These requirements were not met:
      DenyAnonymousAuthorizationRequirement: Requires an authenticated user.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
      AuthenticationScheme: Identity.Application was challenged.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
      AuthenticationScheme: Identity.Application was challenged.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/account application/json - - 401 0 - 9.2956ms
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5000/account/role application/json - - 401 0 - 6.2213ms

If i change to [Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)] like you suggested, it works, but i havent got JwtBearer included anymore

kevinchalet commented 3 years ago

If i change to [Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)] like you suggested, it works, but i havent got JwtBearer included anymore

That's fine, the JWT bearer handler is not useful when using the OpenIddict validation handler.

Gillardo commented 3 years ago

If i change to [Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)] like you suggested, it works, but i havent got JwtBearer included anymore

That's fine, the JWT bearer handler is not useful when using the OpenIddict validation handler.

So i shouldnt need to change it, ok thats good. Not sure what problem is then atm.

kevinchalet commented 3 years ago

Not sure I understand. Do you still have something you think doesn't work?

Gillardo commented 3 years ago

Yes its still not working with the standard [Authorize] attribute.

kevinchalet commented 3 years ago

It's not an OpenIddict issue. It's caused by the fact ASP.NET Core Identity registers itself as the default authentication scheme when calling services.AddIdentity(). So by default, your controllers only accept authentication cookies, not tokens.

The approach I recommended is the best one. If you don't like it, you can explore other options like:

Gillardo commented 3 years ago

That's fine, think we have our wires crossed, i thought you ment i didnt need to change the standard [Authorize] tag for it to work. I am happy to change it to make it all working, just wanted to know what i was.

Thanks for your help

Gillardo commented 3 years ago

@kevinchalet Thought i would play around and found that if i change this line, it all works and i get to use the standard [Authorize] attribute. just encase someone else asks about it

services.AddAuthentication(options => options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);

kevinchalet commented 3 years ago

It's certainly an option, but I don't recommend it as it may break the antiforgery middleware, that uses the default scheme.

Gillardo commented 3 years ago

Thats fine, i dont use cookies on the api at all, only tokens to this should be ok for my use case.

kevinchalet commented 3 years ago

In this case, consider also setting DefaultChallengeScheme and DefaultForbidScheme to ensure OpenIddict handles challenges and return standard-compliant responses, with an appropriate WWW-Authenticate header.

Gillardo commented 3 years ago

Ok thank you, i have done this now as well

// authentication
var authenticationBuilder = services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
    options.DefaultForbidScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});