我正在编写一个Angular4应用程序,我想在IdentityServer4上使用RestFul API进行身份验证/授权。为了开始这个过程,我下载了GitHub IdentityServer4Demo项目。我做了演示工作并决定添加 ResourceOwnerPasswordValidator 和 ProfileService 服务来验证应该有权访问该应用程序的用户。我的问题是,现在所有用户ID /密码组合都会从IdentityServer 触发有效的令牌,无论用户是否有效。我在这里错过了什么? the userid and password should be alice to get an access token Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var builder = services.AddIdentityServer()
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryClients(Config.GetClients());
// .AddTestUsers(TestUsers.Users);
services.AddTransient<IProfileService, Configuration.ProfileService>();
services.AddTransient<IResourceOwnerPasswordValidator, Configuration.ResourceOwnerPasswordValidator>();
// demo versions
services.AddTransient<IRedirectUriValidator, DemoRedirectValidator>();
services.AddTransient<ICorsPolicyService, DemoCorsPolicy>();
if (_env.IsDevelopment())
{
builder.AddTemporarySigningCredential();
}
else
{
builder.AddTemporarySigningCredential();
//builder.AddSigningCredential("6B7ACC520305BFDB4F7252DAEB2177CC091FAAE1", StoreLocation.CurrentUser, nameType: NameType.Thumbprint);
}
}
ResourceOwnerPasswordValidator.cs
public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
using (IDbConnection db = new SqlConnection("Data Source=server1;Initial Catalog=myDB;Integrated Security=SSPI;"))
{
var user = db.Query<User>("select * from Users where UserName=@UserName and Password=@Password",
new { UserName = context.UserName, Password = context.Password }).SingleOrDefault<User>();
if (user == null)
{
context.Result = new GrantValidationResult(IdentityModel.OidcConstants.TokenErrors.UnauthorizedClient, "Invalid User of Password.");
return Task.FromResult<ResourceOwnerPasswordValidationContext>(context);
}
else
{
context.Result = new GrantValidationResult(user.Id.ToString(), "password");
return Task.FromResult<ResourceOwnerPasswordValidationContext>(context);
}
}
}
ProfileService.cs
public class ProfileService : IProfileService
{
public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
context.IssuedClaims = context.Subject.Claims.ToList();
//context.IssuedClaims.Add(new Claim("test-claim", "test-value"));
return Task.FromResult(0);
}
public Task IsActiveAsync(IsActiveContext context)
{
return Task.FromResult(0);
}
}
Config.cs
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client1",
RequireClientSecret = false,
//ClientSecrets = { new Secret("secret".Sha256()) },
//AccessTokenLifetime = 3600,
//AlwaysSendClientClaims=false,
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
AllowedScopes = { "openid", "profile", "email", "api","api1" },
AllowOfflineAccess = true
},
答案 0 :(得分:2)
当你在行var user = db.Query<User>("select * from Users where UserName=@UserName and Password=@Password"
上设置断点时,User
使用无效的用户名/密码调用它时会有什么价值?它是空的吗?如果没有,则问题出在select
/ tables
上,因为 正在寻找用户。
如果它不为null,则问题在于您如何返回Task.
在我们的实施中,我们正在做类似以下的事情:
context.Result = new GrantValidationResult(TokenRequestErrors.UnauthorizedClient);
return Task.FromResult(false);
这样的成功......
context.Result = new GrantValidationResult(user.UserName, "password", claims);
return Task.FromResult(0);
答案 1 :(得分:0)
不确定为什么你想要角度应用程序的ResourceOwnerPassword流程。您应该使用隐式或混合解决方案。
规范建议仅使用资源所有者密码授予 “可信”(或遗留)应用程序。一般来说,你是 通常使用交互式OpenID Connect之一会好得多 当您想要对用户进行身份验证并请求访问令牌时流动。
无论如何,here是一个很好的示例应用程序,您可以查看,可能有助于解决您的问题。