IdentityServer4:“子”范围怎么样?

时间:2017-02-07 23:34:23

标签: openid identityserver4

我已经运行了IdentityServer4。当我现在尝试进行身份验证时,出现以下错误:

info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
fail: IdentityServer4.Validation.ScopeValidator[0]
      Requested scope not allowed: sub

当我从/.well-known/openid-configuration/获取open id文档时,我获得了支持范围:

["address","phone","openid","email","profile","api1","offline_access"]

其中没有“sub”范围作为supported_scope。

这是完整的配置文档:

{"issuer":"http://localhost:5000","jwks_uri":"http://localhost:5000/.well-known/openid-configuration/jwks","authorization_endpoint":"http://localhost:5000/connect/authorize","token_endpoint":"http://localhost:5000/connect/token","userinfo_endpoint":"http://localhost:5000/connect/userinfo","end_session_endpoint":"http://localhost:5000/connect/endsession","check_session_iframe":"http://localhost:5000/connect/checksession","revocation_endpoint":"http://localhost:5000/connect/revocation","introspection_endpoint":"http://localhost:5000/connect/introspect","frontchannel_logout_supported":true,"frontchannel_logout_session_supported":true,"scopes_supported":["openid","address","phone","openid","email","profile","api1","offline_access"],"claims_supported":["sub","address","phone_number","phone_number_verified","email","email_verified","name","family_name","given_name","middle_name","nickname","preferred_username","profile","picture","website","gender","birthdate","zoneinfo","locale","updated_at"],"response_types_supported":["code","token","id_token","id_token token","code id_token","code token","code id_token token"],"response_modes_supported":["form_post","query","fragment"],"grant_types_supported":["authorization_code","client_credentials","refresh_token","implicit","password"],"subject_types_supported":["public"],"id_token_signing_alg_values_supported":["RS256"],"token_endpoint_auth_methods_supported":["client_secret_basic","client_secret_post"],"code_challenge_methods_supported":["plain","S256"]}

我在启动时尝试了以下内容:

app.UseIdentity();
app.UseIdentityServer();

var allowedScopes = new []{"address","phone","email","profile","api1","offline_access", "sub"};
var identityAuthOptions = new IdentityServerAuthenticationOptions();
identityAuthOptions.AllowedScopes =  allowedScopes;
identityAuthOptions.AutomaticAuthenticate = true;
identityAuthOptions.AutomaticChallenge = true;        
app.UseIdentityServerAuthentication(identityAuthOptions);

我对IdentityServer的配置如下:

services.AddIdentityServer()
    .AddTemporarySigningCredential()
    .AddAspNetIdentity<ApplicationUser>()
    .AddOperationalStore(options => 
        options.UseSqlite(Configuration.GetConnectionString("PersistedGrants"), 
        builder => builder.MigrationsAssembly(Assembly.GetEntryAssembly().FullName)))
    .AddInMemoryApiResources(Config.GetApiResources())
    .AddInMemoryClients(Config.GetClients())
    .AddTestUsers(Config.GetUsers())
    .AddInMemoryIdentityResources(Config.GetIdentityResources());


services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

Config类是这样的:

public class Config
    {
        // scopes define the resources in your system
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Address(),
                new IdentityResources.Phone(),
                new IdentityResources.OpenId(),
                new IdentityResources.Email(),
                new IdentityResources.Profile()
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("api1", "Main API", new[]{ "sub" })
            };
        }

        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            // client credentials client
            return new List<Client>
            {
                new Client
                {
                    ClientId = "actionCommunity",
                    AllowPlainTextPkce = true,
                    AlwaysSendClientClaims = true,
                    AllowRememberConsent = true,
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
                    RedirectUris = {
                        "http://localhost:3333/login-success",
                        "http://localhost:3000/login-success",
                        "http://localhost:3000/auth.html"
                    },
                    AllowAccessTokensViaBrowser = true,

                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes = {
                        "api1", "sub",
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                        IdentityServerConstants.StandardScopes.Address,
                        IdentityServerConstants.StandardScopes.Email,
                        IdentityServerConstants.StandardScopes.Phone,
                        IdentityServerConstants.StandardScopes.Profile,
                    },
                    AllowOfflineAccess = true
                }
            };
        }

        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>
            {
                new TestUser
                {
                    SubjectId = "1",
                    Username = "testUser",
                    Password = "testPassword",

                    Claims = new List<Claim>
                    {
                        new Claim("name", "Testuser"),
                        new Claim("website", "https://www.testuser.de")
                    }
                },
                new TestUser
                {
                    SubjectId = "2",
                    Username = "bob",
                    Password = "password",

                    Claims = new List<Claim>
                    {
                        new Claim("name", "Bob"),
                        new Claim("website", "https://bob.com")
                    }
                }
            };
        }
    }

所以:无论我尝试什么,我都无法设法获得奇怪的“子”范围。

有人可以帮我吗?

2 个答案:

答案 0 :(得分:1)

您在创建APiResource时已经传递了claimType。

   public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource("api1", "Main API", new[]{ "sub" })
        };
    }

以下是构造函数的签名:

public ApiResource(string name, string displayName, IEnumerable<string> claimTypes)

您可以通过引用从IdentityServer4文档中获取的以下代码段来添加范围:

// expanded version if more control is needed
    new ApiResource
    {
        Name = "api2",

        // secret for using introspection endpoint
        ApiSecrets =
        {
            new Secret("secret".Sha256())
        },

        // include the following using claims in access token (in addition to subject id)
        UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.Email }
        },

        // this API defines two scopes
        Scopes =
        {
            new Scope()
            {
                Name = "api2.full_access",
                DisplayName = "Full access to API 2",
            },
            new Scope
            {
                Name = "api2.read_only",
                DisplayName = "Read only access to API 2"
            }
        }
    }

请参阅以下链接以了解更多详情:

http://docs.identityserver.io/en/release/configuration/resources.html#defining-api-resources

答案 1 :(得分:1)

sub不是范围,而是声明。它包含在openid范围内(因此也包含在每个身份标记中)。

由于没有配置IdentityServer这样的范围,这也是您收到错误的原因。如果您从请求中删除了sub范围,则应该可以使用。