c# - 如何从 IdentityServer4 请求用户信息
问题描述
ResourceOwnerPassword
我有一个使用授权类型的基本登录流程。用户可以登录,验证他们的密码并获得一个他们可以用来访问 API 的令牌。我现在正在尝试将索赔传回给客户,以便我可以确定我正在处理什么样的用户,但是我收到了一个错误,我认为这是客户范围的问题(尽管我看不到什么)。
下面的代码被删减以避免页面和代码页面,但我相信它包含所有相关的内容。这是身份服务器设置:
services
.AddIdentityServer()
.AddInMemoryClients(IdentityServerHelper.GetClients())
.AddInMemoryApiResources(IdentityServerHelper.GetApiResources())
.AddTestUsers(IdentityServerHelper.GetUsers())
.AddInMemoryIdentityResources(
IdentityServerHelper.GetIdentityResources());
辅助方法:
internal static IEnumerable<Client> GetClients()
{
var clients = new List<Client>
{
new Client
{
ClientId = "MyClientApp",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes =
{
"myApi",
"Role",
IdentityServerConstants.StandardScopes.OpenId
/*
IdentityServerConstants.StandardScopes.Profile
*/
}
}
};
}
internal static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource> {
new IdentityResource {
Name = "Role",
UserClaims = new List<string> { JwtClaimTypes.Role },
}
};
}
internal static List<TestUser> GetUsers()
{
var users = new List<TestUser>
{
new TestUser
{
SubjectId = Guid.NewGuid(),
Username = "user",
Password = "pass",
Claims = new List<Claim>()
{
new Claim(JwtClaimTypes.Role, "Role1")
}
},
这个想法是返回Role1
给客户。这是客户端代码:
_discoveryResponse = await _httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
{
Address = "https://localhost:5021",
Policy =
{
ValidateIssuerName = false,
}
});
var response = await _httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = _discoveryResponse.TokenEndpoint,
ClientId = "MyClientApp",
ClientSecret = "secret",
Scope = "openid Role myApi",
UserName = username,
Password = password
});
if (response.IsError)
{
return false; // When specifying openid, get invalid scope here
}
_accessToken = response.AccessToken;
. . .
var userInfo = await _httpClient.GetUserInfoAsync(new UserInfoRequest()
{
Address = _discoveryResponse.UserInfoEndpoint,
Token = _accessToken
});
// userInfo is returning "Forbidden" here.
编辑:
在范围中指定 openid 时,我在 Identity Server 日志中收到以下错误:
失败:IdentityServer4.Validation.ScopeValidator[0] 不允许请求的范围:openid
解决方案
openid
请求令牌时,您至少需要添加范围。像下面这样更改代码可能会解决问题。
var clients = new List<Client>
{
new Client
{
ClientId = "MyClientApp",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes =
{
"myApi",
"Role",
IdentityServerConstants.StandardScopes.OpenId
}
}
};
var response = await _httpClient.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = _discoveryResponse.TokenEndpoint,
ClientId = "MyClientApp",
ClientSecret = "secret",
Scope = "openid Role myApi",
UserName = username,
Password = password
});
您可以从https://github.com/IdentityServer/IdentityServer4/blob/master/src/Validation/Default/UserInfoRequestValidator.cs#L47查看源代码部分
推荐阅读
- java - 如何阻止 Recyclerview 产生重复项并停止洗牌?
- r - 为什么我的错误栏的末端不显示?
- django - 尝试将模型转换为 dict 时图像字段上的值错误
- javascript - 尝试连接到 MongoDB Atlas 时如何修复密码错误?
- google-maps - 由于自定义图像,Google Maps API v3 多个标记不起作用?
- backendless - 无法连接到后端 API 服务器
- macos - 每次打开 rails 项目文件夹时都需要输入 rvm use
- scala - 在 Confluent conn 失败时通过 HTTPS 的 Kafka Schema Registry
- php - 如何最好地处理 catch 块中抛出的异常?
- java - ScrollView 不与 LinearLayout 一起使用打开键盘时视图有重量?