【问题标题】:auth0 authorisation in asp.net core app (MVC)asp.net 核心应用程序 (MVC) 中的 auth0 授权
【发布时间】:2023-03-13 08:05:01
【问题描述】:

我正在尝试让 Auth0 在我的 MVC 应用程序中工作。 虽然身份验证有效,但我似乎无法获得授权。

我已经学习了这个教程:https://auth0.com/docs/quickstart/webapp/aspnet-core

我的代码:

public static IServiceCollection AddAuth0(this IServiceCollection services, IConfiguration configuration)
{
    var auth0Options = configuration.GetSection(nameof(Auth0Config))
        .Get<Auth0Config>();

    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

        //                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        //                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }) //do i need this for access_token?
       //                .AddJwtBearer(options =>
       //                {
       //                    options.Authority = auth0Options.Domain;
       //                    options.Audience = auth0Options.ApiIdentifier;
       //
       //                    options.SaveToken = true;
       //                    options.RequireHttpsMetadata = false;
       //                })
        .AddCookie()
        .AddOpenIdConnect(Auth0Constants.Auth0Scheme, options =>
        {
            options.Authority = $"https://{auth0Options.Domain}";

            options.ClientId = auth0Options.ClientId;
            options.ClientSecret = auth0Options.ClientSecret;

            options.ResponseType = Auth0Constants.ResponseTypeCode;

            options.SaveToken = true;

            options.Scope.Clear();
            options.Scope.Add(Auth0Constants.Auth0Scope.openid.ToString());
            options.Scope.Add(Auth0Constants.Auth0Scope.email.ToString());
            options.Scope.Add(Auth0Constants.Auth0Scope.profile.ToString());
            options.Scope.Add("read:cars");

            options.CallbackPath = new PathString("/callback");

            options.ClaimsIssuer = Auth0Constants.Auth0Scheme;

            options.Events = new OpenIdConnectEvents
            {
                OnRedirectToIdentityProviderForSignOut = context => OnRedirectToIdentityProviderForSignOut(context, auth0Options),
                OnRedirectToIdentityProvider = context => OnRedirectToIdentityProvider(context, auth0Options)
            };
        });

    services.AddAuthorization(options =>
    {
        options.AddPolicy("read:cars", policy => policy.Requirements.Add(new HasScopeRequirement("read:cars", auth0Options.Domain)));
    });

    services.AddSingleton<IAuthorizationHandler, HasScopeHandler>();

    return services;
}

private static Task OnRedirectToIdentityProvider(RedirectContext context, Auth0Config config)
{
    context.ProtocolMessage.SetParameter("audience", config.ApiIdentifier);

    return Task.CompletedTask;
}

private static Task OnRedirectToIdentityProviderForSignOut(RedirectContext context, Auth0Config auth0Options)
{
    var logoutUri = $"https://{auth0Options.Domain}/v2/logout?client_id={auth0Options.ClientId}";

    var postLogoutUri = context.Properties.RedirectUri;
    if (!string.IsNullOrEmpty(postLogoutUri))
    {
        if (postLogoutUri.StartsWith("/"))
        {
            var request = context.Request;
            postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
        }

        logoutUri += $"&returnTo={Uri.EscapeDataString(postLogoutUri)}";
    }

    context.Response.Redirect(logoutUri);
    context.HandleResponse();

    return Task.CompletedTask;
}

当我查看我的 charles 会话时,我确实看到令牌中返回了正确的范围和权限:

"scope": "openid profile email read:cars",
"permissions": [
  "read:cars"
]

但例如,我无法像他们说的那样获得access_token

var accessToken = await HttpContext.GetTokenAsync("access_token");

这返回空值;它也不在索赔中。

在我的一个控制器上,我有:[Authorize("read:cars")] 我被拒绝访问,我是否删除该权限并只使用授权,那么我很好。

检查范围是否存在:

public class HasScopeRequirement : IAuthorizationRequirement
{
    public string Issuer { get; }
    public string Scope { get; }

    public HasScopeRequirement(string scope, string issuer)
    {
        Scope = scope;
        Issuer = issuer;
    }
}

public class HasScopeHandler : AuthorizationHandler<HasScopeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)
    {
        // If user does not have the scope claim, get out of here
        if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
            return Task.CompletedTask;

        // Split the scopes string into an array
        var scopes = context.User.FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' ');

        // Succeed if the scope array contains the required scope
        if (scopes.Any(s => s == requirement.Scope))
            context.Succeed(requirement);

        return Task.CompletedTask;
    }
}

但我想这不是我的问题,我认为它在我的 access_token 中,我什至无法阅读。所以我在想我错过了什么。是因为 DefaultAuthenticationScheme/ChallengeScheme 还是 ...?

【问题讨论】:

    标签: asp.net-core-mvc auth0 asp.net-core-2.2


    【解决方案1】:

    感谢柯克!

    修复了一些与我最初的想法不同的问题;现在我正在使用角色。

    在 auth0 中我有用户,并为他们分配所需的角色;

    并且作为一项规则:

    function (user, context, callback) {
      context.idToken['http://schemas.microsoft.com/ws/2008/06/identity/claims/roles'] = context.authorization.roles;
    
      callback(null, user, context);
    }
    

    我使用http://schemas.microsoft.com/ws/2008/06/identity/claims/roles 作为默认声明,因为 .net 核心默认映射到该声明。

    在我的设置中我添加了:

    options.TokenValidationParameters= new TokenValidationParameters
    {
        RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/roles"
    };
    

    现在我可以在我的控制器上使用 Authorize 属性了

    只是为了清楚;我只有一个 webapp。如果我要使用不同的 API,那么我将不得不使用 access_token。

    【讨论】:

    • 整个上午都在尝试调试您遇到的相同问题,并意识到我遵循的建议从 user.app_metadata.roles 获得了角色(可能是针对 Auth Extension 或 @987654327 @. 非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2013-10-07
    • 2020-04-28
    • 2020-06-11
    • 2021-07-13
    • 2019-02-04
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多