ASP 身份角色未出现在使用 IdentityServer v3 的客户端中
ASP Identity Roles not appearing in Client using IdentityServer v3
感觉我在 IdentityServer 或客户端配置中遗漏了一些东西。我已经从 ASP 成员身份升级到 Identity,然后切换到将 SSO 与 IdentityServer 一起使用。我可以通过 Identity Server 登录并返回到客户端应用程序,在那里我可以调试并查看 UserKey 和声明,但我在声明中看不到任何角色并且 user.IsInRole(roleName) 总是 returns错误的。
IdentityServer 配置:
public class Scopes
{
public static IEnumerable<Scope> Get()
{
return new Scope[]
{
StandardScopes.OpenId,
StandardScopes.Profile,
StandardScopes.Email,
StandardScopes.AllClaims,
StandardScopes.Roles,
StandardScopes.OfflineAccess,
new Scope
{
IncludeAllClaimsForUser = true,
Name = "read",
DisplayName = "Read data",
Type = ScopeType.Resource,
Emphasize = false,
},
new Scope
{
Name = "write",
DisplayName = "Write data",
Type = ScopeType.Resource,
Emphasize = false, //true
},
new Scope
{
Name = "forbidden",
DisplayName = "Forbidden scope",
Type = ScopeType.Resource,
Emphasize = false //true
}
};
}
}
public static class Clients
{
public static IEnumerable<Client> Get()
{
return new[]
{
new Client
{
Enabled = true,
ClientName = "MVC Client",
ClientId = "implicitclient",
Flow = Flows.Implicit,
AllowedScopes = new List<string> {
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
Constants.StandardScopes.Email,
Constants.StandardScopes.Roles
},
RedirectUris = new List<string>
{
"https://localhost:44301/"
}
},
new Client
{
Enabled = true,
ClientName = "MyClientName",
ClientId = "myclientName",
Flow = Flows.Implicit,
AllowedScopes = new List<string> {
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
Constants.StandardScopes.Email,
Constants.StandardScopes.Roles,
"read",
"write"
},
RedirectUris = new List<string>
{
"https://localhost:44302/"
}
}
};
}
}
public static IdentityServerServiceFactory Configure()
{
var factory = new IdentityServerServiceFactory();
var scopeStore = new InMemoryScopeStore(Scopes.Get());
factory.ScopeStore = new Registration<IScopeStore>(scopeStore);
var clientStore = new InMemoryClientStore(Clients.Get());
factory.ClientStore = new Registration<IClientStore>(clientStore);
factory.CorsPolicyService = new Registration<ICorsPolicyService>(new DefaultCorsPolicyService { AllowAll = true });
return factory;
}
客户端配置(MVC 5 应用程序):
public void Configuration(IAppBuilder app)
{
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "myclientname",
Authority = "https://localhost:44300/core", //Constants.BaseAddress, //STS Server Address
RedirectUri = "https://localhost:44302/", //This site
ResponseType = "id_token token",
//Scope = "openid email write",
Scope = "openid email roles",
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var token = n.ProtocolMessage.AccessToken;
// persist access token in cookie
if (!string.IsNullOrEmpty(token))
{
n.AuthenticationTicket.Identity.AddClaim(
new Claim("access_token", token));
}
}
}
});
}
}
非常感谢任何建议!
作用域角色只有一个作用域声明,“role”,此作用域声明具有以下属性“AlwaysIncludeinIdToken”设置为 false,这意味着如果您请求“token”response_type,它不会被隐式发送。 (这是我的理解,可能没那么简单)
首先尝试删除“token”response_type,只询问“” openid”和“roles”范围。如果这解决了问题,那么它就不会隐式发送它们。
您需要明确询问剩余的声明,即未在 "id_token" 请求中发送的声明。您需要使用您获得的 access_token 和“userinfo”端点。 (作为在文档中搜索正确使用端点的提示)
EDIT:UserInfo Documentation,这可能对如何调用 Userinfo 端点很有用。
感觉我在 IdentityServer 或客户端配置中遗漏了一些东西。我已经从 ASP 成员身份升级到 Identity,然后切换到将 SSO 与 IdentityServer 一起使用。我可以通过 Identity Server 登录并返回到客户端应用程序,在那里我可以调试并查看 UserKey 和声明,但我在声明中看不到任何角色并且 user.IsInRole(roleName) 总是 returns错误的。
IdentityServer 配置:
public class Scopes
{
public static IEnumerable<Scope> Get()
{
return new Scope[]
{
StandardScopes.OpenId,
StandardScopes.Profile,
StandardScopes.Email,
StandardScopes.AllClaims,
StandardScopes.Roles,
StandardScopes.OfflineAccess,
new Scope
{
IncludeAllClaimsForUser = true,
Name = "read",
DisplayName = "Read data",
Type = ScopeType.Resource,
Emphasize = false,
},
new Scope
{
Name = "write",
DisplayName = "Write data",
Type = ScopeType.Resource,
Emphasize = false, //true
},
new Scope
{
Name = "forbidden",
DisplayName = "Forbidden scope",
Type = ScopeType.Resource,
Emphasize = false //true
}
};
}
}
public static class Clients
{
public static IEnumerable<Client> Get()
{
return new[]
{
new Client
{
Enabled = true,
ClientName = "MVC Client",
ClientId = "implicitclient",
Flow = Flows.Implicit,
AllowedScopes = new List<string> {
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
Constants.StandardScopes.Email,
Constants.StandardScopes.Roles
},
RedirectUris = new List<string>
{
"https://localhost:44301/"
}
},
new Client
{
Enabled = true,
ClientName = "MyClientName",
ClientId = "myclientName",
Flow = Flows.Implicit,
AllowedScopes = new List<string> {
Constants.StandardScopes.OpenId,
Constants.StandardScopes.Profile,
Constants.StandardScopes.Email,
Constants.StandardScopes.Roles,
"read",
"write"
},
RedirectUris = new List<string>
{
"https://localhost:44302/"
}
}
};
}
}
public static IdentityServerServiceFactory Configure()
{
var factory = new IdentityServerServiceFactory();
var scopeStore = new InMemoryScopeStore(Scopes.Get());
factory.ScopeStore = new Registration<IScopeStore>(scopeStore);
var clientStore = new InMemoryClientStore(Clients.Get());
factory.ClientStore = new Registration<IClientStore>(clientStore);
factory.CorsPolicyService = new Registration<ICorsPolicyService>(new DefaultCorsPolicyService { AllowAll = true });
return factory;
}
客户端配置(MVC 5 应用程序):
public void Configuration(IAppBuilder app)
{
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = "myclientname",
Authority = "https://localhost:44300/core", //Constants.BaseAddress, //STS Server Address
RedirectUri = "https://localhost:44302/", //This site
ResponseType = "id_token token",
//Scope = "openid email write",
Scope = "openid email roles",
SignInAsAuthenticationType = "Cookies",
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var token = n.ProtocolMessage.AccessToken;
// persist access token in cookie
if (!string.IsNullOrEmpty(token))
{
n.AuthenticationTicket.Identity.AddClaim(
new Claim("access_token", token));
}
}
}
});
}
}
非常感谢任何建议!
作用域角色只有一个作用域声明,“role”,此作用域声明具有以下属性“AlwaysIncludeinIdToken”设置为 false,这意味着如果您请求“token”response_type,它不会被隐式发送。 (这是我的理解,可能没那么简单)
首先尝试删除“token”response_type,只询问“” openid”和“roles”范围。如果这解决了问题,那么它就不会隐式发送它们。
您需要明确询问剩余的声明,即未在 "id_token" 请求中发送的声明。您需要使用您获得的 access_token 和“userinfo”端点。 (作为在文档中搜索正确使用端点的提示)
EDIT:UserInfo Documentation,这可能对如何调用 Userinfo 端点很有用。