代码之家  ›  专栏  ›  技术社区  ›  Henrik Poulsen

为OpenIddict MVC Core 2.0设置自定义范围

  •  4
  • Henrik Poulsen  · 技术社区  · 8 年前

    我对MVC中的OpenId和auth相当陌生,并且创建了一个OpenIddict auth服务器和客户端MVC应用程序,如授权代码流示例所示。 https://github.com/openiddict/openiddict-samples 我需要补充 companyId

    到目前为止,我发现了以下几点:

    AuthorizationController.CreateTicketAsync 通过创建一个新的ClaimsPrincipal并添加新的声明,然后通过调用 ticket.SetScopes

    // Add my specific claims: CompanyId and CompanyName
    var claims = new List<Claim>();
    claims.Add(new Claim(MyClaimsConstants.Claims.CompanyId, user.SelectedCompanyId.ToString()));
    T_Company company = await _companyRepo.GetCompany(user.SelectedCompanyId);
    claims.Add(new Claim(MyClaimsConstants.Claims.CompanyName, company.CompanyName));
    
    // Create the new identity with the added claims
    var newIdentity = new ClaimsIdentity(principal.Identity, claims);
    
    principal = new ClaimsPrincipal(newIdentity);
    
    ....
    
    if (!request.IsAuthorizationCodeGrantType())
    {
        // Set the list of scopes granted to the client application.
        // Note: the offline_access scope must be granted
        // to allow OpenIddict to return a refresh token.
        ticket.SetScopes(new[]
        {
            OpenIdConnectConstants.Scopes.OpenId,
            OpenIdConnectConstants.Scopes.Email,
            OpenIdConnectConstants.Scopes.Profile,
            OpenIdConnectConstants.Scopes.OfflineAccess,
            OpenIddictConstants.Scopes.Roles,
            MyClaimsConstants.Scopes.Company // <-
        }.Intersect(request.GetScopes()));
    }
    

    我将目的地添加到AuthorizationController中的声明中。创建ticketasync将其添加到IdentityToken。

    foreach (var claim in ticket.Principal.Claims)
    {
        // Never include the security stamp in the access and identity tokens, as it's a secret value.
        if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType)
        {
            continue;
        }
    
        var destinations = new List<string>
        {
            OpenIdConnectConstants.Destinations.AccessToken
        };
    
        // Only add the iterated claim to the id_token if the corresponding scope was granted to the client application.
        // The other claims will only be added to the access_token, which is encrypted when using the default format.
        if (((claim.Type == OpenIdConnectConstants.Claims.Name || claim.Type == OpenIdConnectConstants.Claims.Nickname) && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile)) ||
            (claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email)) ||
            (claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles)) ||
            ((claim.Type == MyClaimsConstants.Claims.CompanyId || claim.Type == MyClaimsConstants.Claims.CompanyName) && ticket.HasScope(MyClaimsConstants.Scopes.Company))) // <-
        {
            destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken);
        }
    
        claim.SetDestinations(destinations);
    }
    

    我在UserInfoController中添加了范围检查并有条件地添加声明

    if (User.HasClaim(OpenIdConnectConstants.Claims.Scope, MyClaimsConstants.Scopes.Company))
    {
        claims[MyClaimsConstants.Claims.CompanyId] = user.SelectedCompanyId;
        claims[MyClaimsConstants.Claims.CompanyName] = (await _companyRepo.GetCompany(user.SelectedCompanyId))?.CompanyName;
    }
    

    options.Scope.Add(MyClaimsConstants.Scopes.Company);
    

    这似乎在按预期工作。

    有人能对这些步骤发表评论吗,或者可以指出一个显示这种特定实现的示例吗?(这看起来很基本,但我不知道我在这个过程中是否做了一些非常糟糕的事情)。

    1 回复  |  直到 5 年前
        1
  •  2
  •   Fredrik Ljung    5 年前

    因为这确实是实现自定义作用域的方式。

    services.AddOpenIddict(options =>
    {
        // ...
    
        options.RegisterScopes(
            OpenIdConnectConstants.Scopes.Profile,
            OpenIdConnectConstants.Scopes.Email,
            MyClaimsConstants.Scopes.Company);
    });
    
    推荐文章