0

因此,我正在构建一个新的安全令牌服务,以取代基于 IdentityServer3 的旧解决方案。我希望使用 PKCE 流进行身份验证,到目前为止,我已经为新服务配置了证书、身份资源、测试用户、API 资源和客户端。

身份资源

IEnumerable<IdentityResource> IdentityResources => new List<IdentityResource>
{
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResource
    {
        Name = JwtClaimTypes.Role,
        UserClaims = new List<string> { JwtClaimTypes.Role }
    }
};

用户

List<TestUser> Users => new List<TestUser>
{
    new TestUser
    {
        SubjectId = "1234",
        Username = "asd",
        Password = "asd",
        Claims = new [] { new Claim(JwtClaimTypes.Role, "super") }
    }
};

API 资源

IEnumerable<ApiResource> Apis => new List<ApiResource>
{
    new ApiResource
    {
        Name = "api",
        UserClaims = new List<string> { JwtClaimTypes.Role },
        Scopes = new List<Scope> { new Scope("api") }
    }
};

客户

IEnumerable<Client> Clients => new List<Client>
{
    new Client
    {
        ClientId = "client",
        AllowedGrantTypes = GrantTypes.Code,
        AllowAccessTokensViaBrowser = true,
        RequirePkce = true,
        RequireClientSecret = false,
        RequireConsent = false,

        AllowedScopes =
        {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            JwtClaimTypes.Role,
            "api"
        },

        AllowedCorsOrigins = { "http://localhost:3005/" },
        RedirectUris = { "http://localhost:3005/callback.html" },
        PostLogoutRedirectUris = { "http://localhost:3005/index.html" }
    }
};

AngularJS 客户端正在使用 oidc-client.js。这与我的令牌服务之间的通信似乎工作正常。我得到了从 IdentityServer4 返回的有效 JWT 令牌,其中包含我期望的数据。我的目标是将访问令牌中包含的用户 ID 传递给 API,因此它可以确保通过专门为检查用户是否具有“超级”角色而构建的外部库对用户进行身份验证,并使用用户 ID。

客户端像这样配置 OIDC UserManager:

return new Oidc.UserManager({
    client_id: 'client',
    response_type: 'code',
    filterProtocolClaims: true,
    loadUserInfo: true,
    revokeAccessTokenOnSignout: true,
    scope: 'openid profile role api',
    authority: 'https://localhost:44300/',
    redirect_uri: 'http://localhost:3005/callback.html',
    post_logout_redirect_uri: 'http://localhost:3005/index.html'
});

现在,这是一个旧代码库 - 但在我看来,当从客户端调用 API 时 - 访问令牌被放入使用 $httpProvider.interceptors 的 push() 调用中的授权标头中,就像这样..

$httpProvider.interceptors.push(function (apiUrl, oidcManager, currentLanguage) {
    return {
        'request': function (config) {
            if (isApiCall(config, apiUrl, oidcManager)) {        
                var userManager = oidcManager.getUserManager();
                userManager.getUser().then(function (user) {
                    if (!user) {
                        userManager.signinRedirect();
                    }
                    config.headers.Authorization = 'Bearer ' + user.access_token;
                });
            }            
            return config;
        }
    };
});

在记录配置对象时,我可以验证 Authorization 标头是否确实包含我需要的访问令牌。但是,当使用没有必需输入参数的简单 GET 请求调用 API 时 - 受操作方法上的 [Authorize] 属性保护,我得到 401 Not Authorized 响应。API 是这样配置的,在 Startup 类中..

JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
    app.UseIdentityServerBearerTokenAuthentication(
        new IdentityServerBearerTokenAuthenticationOptions {
            Authority = "https://localhost:44300/",
            RequiredScopes = new[] { "api" }
        }
);

现在,在控制器构造函数中为我试图命中的端点设置一个断点,我可以看到没有用户数据、声明等被拾取。我猜这与旧的 AngularJS 客户端如何构建和传递这些请求有关,但到目前为止我被困住了!

对此问题的任何见解和指导将不胜感激 - 并感谢您阅读我的长期混乱!

4

0 回答 0