我发现这确实令人困惑,无法在任何地方找到任何文档。我希望我没有打算转移到身份服务器,我遇到的所有问题是什么.... 无论如何,当前的问题是,当我进行身份验证时,没有任何声明基于 User.Identity 。
我尝试使用 ClaimsTransformer 来使用 ClaimsTransformer 添加我的声明but it turns out that you can't use DI to get database claims。所以我不得不想出另一个解决方案。
我经过大量挖掘后发现,您可以使用 ClaimsProvider 。但是当我添加它时,我无法授权我的请求。 这是我的配置之前我添加了 ClaimsProvider :
public static class Config
{
/// <summary>
/// Configures identity server
/// </summary>
public static void ConfigureIdentityServer(this IAppBuilder app, CormarConfig config)
{
// Create our options
var identityServerOptions = new IdentityServerOptions
{
SiteName = "Cormar API",
SigningCertificate = LoadCertificate(),
IssuerUri = "https://cormarapi-test.azurewebsites.net",
LoggingOptions = new LoggingOptions
{
EnableHttpLogging = true,
EnableWebApiDiagnostics = true,
EnableKatanaLogging = true,
WebApiDiagnosticsIsVerbose = true
},
Factory = new IdentityServerServiceFactory().Configure(config),
// Disable when live
EnableWelcomePage = true
};
// Setup our auth path
app.Map("/identity", idsrvApp => { idsrvApp.UseIdentityServer(identityServerOptions); });
}
/// <summary>
/// Configures the identity server to use token authentication
/// </summary>
public static void ConfigureIdentityServerTokenAuthentication(this IAppBuilder app, HttpConfiguration config)
{
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://cormarapi-test.azurewebsites.net/identity",
DelayLoadMetadata = true,
ValidationMode = ValidationMode.Both,
RequiredScopes = new[] {"api"},
ClientId = "api",
ClientSecret = "8at?7nAtaB!E"
});
}
/// <summary>
/// Loads the certificate
/// </summary>
/// <returns></returns>
private static X509Certificate2 LoadCertificate()
{
var certPath = $"{AppDomain.CurrentDomain.BaseDirectory}App_Data\\idsrv3test.pfx";
var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
certStore.Open(OpenFlags.ReadOnly);
var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, "3A1AFB6E1DC5C3F341E63651542C740DA4148866", false);
certStore.Close();
// If we are on azure, get the actual self signed certificate, otherwise return the test one
return certCollection.Count > 0 ? certCollection[0] : new X509Certificate2(certPath, "idsrv3test");
}
/// <summary>
/// Configure the identity service factory with custom services
/// </summary>
/// <returns></returns>
private static IdentityServerServiceFactory Configure(this IdentityServerServiceFactory factory, CormarConfig config)
{
var serviceOptions = new EntityFrameworkServiceOptions {ConnectionString = config.SqlConnectionString};
factory.RegisterOperationalServices(serviceOptions);
factory.RegisterConfigurationServices(serviceOptions);
factory.CorsPolicyService = new Registration<ICorsPolicyService>(new DefaultCorsPolicyService {AllowAll = true}); // Allow all domains to access authentication
factory.Register(new Registration<DbContext>(dr => dr.ResolveFromAutofacOwinLifetimeScope<DbContext>()));
factory.UserService = new Registration<IUserService>(dr => dr.ResolveFromAutofacOwinLifetimeScope<IUserService>());
factory.ClientStore = new Registration<IClientStore>(dr => dr.ResolveFromAutofacOwinLifetimeScope<IClientStore>());
factory.ScopeStore = new Registration<IScopeStore>(dr => dr.ResolveFromAutofacOwinLifetimeScope<IScopeStore>());
return factory;
}
}
如果设置如此,我在 Startup.cs 中调用它:
app.ConfigureIdentityServer(scope.Resolve<CormarConfig>());
app.ConfigureIdentityServerTokenAuthentication(config);
app.UseWebApi(config);
一切正常(索赔除外)。我可以进行身份验证,我可以授权我的请求。 现在我需要获取 UserClaims ,因此我创建了 ClaimsProvider ,如下所示:
public class ClaimsProvider: DefaultClaimsProvider
{
private readonly IUserStore<User> _userStore;
public ClaimsProvider(IUserService userService, IUserStore<User> userStore)
: base(userService)
{
_userStore = userStore;
}
public override async Task<IEnumerable<Claim>> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, Client client, IEnumerable<Scope> scopes, ValidatedRequest request)
{
var id = subject.GetSubjectId();
var user = await _userStore.FindByIdAsync(id);
return user.Claims.Select(ModelFactory.Create).ToList();
}
}
然后我将它添加到我的 IdentityServerServiceFactory配置方法中,如下所示:
factory.ClaimsProvider = new Registration<IClaimsProvider>(dr => dr.ResolveFromAutofacOwinLifetimeScope<IClaimsProvider>());
ClaimsProvider 已在 Autofac 中注册,如下所示:
builder.RegisterType<ClaimsProvider>().As<idsrv.IClaimsProvider>().InstancePerDependency();
我仍然可以验证并获取我的令牌,但是一旦我尝试使用我的令牌访问任何端点,我就会收到此错误:
收到无效的承载令牌
我不知道为什么。有人可以帮忙吗?
答案 0 :(得分:0)
我在这里完全看错了地方。 要向用户添加声明,您必须在自定义 UserService 中覆盖 GetProfileDataAsync 。我之前已经这样做了,但声称没有坚持下去。然后我读到了 ScopeClaims 。在我的情况下,我的声明属于“角色”类型,所以我只添加了一个名为role的新 ScopeClaim ,然后当我登录时,我看到 GetProfileDataAsync ,果然,声明已添加到我的 User.Identity 。 例如,以下是我的 GetProfileDataAsync :
public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subject = context.Subject;
var requestedClaimTypes = context.RequestedClaimTypes;
var user = await _userProvider.FindByIdAsync(subject.GetSubjectId());
if (user == null) throw new ArgumentException("Invalid user id");
var claims = GetClaimsFromUser(user);
if (requestedClaimTypes != null && requestedClaimTypes.Any()) claims = claims.Where(m => requestedClaimTypes.Contains(m.Type));
context.IssuedClaims = claims;
}
private IEnumerable<Claim> GetClaimsFromUser(User model)
{
var claims = model.Claims.Select(ModelFactory.Create).ToList();
if (model.EmailConfirmed) claims.Add(new Claim(Constants.ClaimTypes.EmailVerified, model.EmailConfirmed ? "true": "false"));
return claims;
}