尝试创建自己的自定义OpenId Auth提供程序,该提供程序将指向IdentityServer服务,但似乎在ServiceStack程序集中找不到OpenIdOAuthProvider。
VS 2017说
错误CS0012在未引用的程序集中定义了“ OAuthProvider”类型。您必须添加对程序集'ServiceStack,Version = 5.0.0.0,Culture = neutral,PublicKeyToken = 02c12cbda47e6587'的引用
public class MyCustomOpenIdOAuthProvider : ServiceStack.Authentication.OpenId.OpenIdOAuthProvider
{
//code goes here to point to IdentityServer Realm...
}
我确实引用了ServiceStack 5.4.1和ServiceStack.Authentication.OpenId。 .Net Core 2.2
这里有任何帮助。
答案 0 :(得分:1)
ServiceStack.Authentication.OpenId包是not supported in .NET Core的.NET Framework唯一项目,原因是OpenIdOAuthProvider.cs需要DotNetOpenAuth,而该对象不适用于.NET Core。
在使用v5.4.1 pre-release MyGet packages时,您可能会对新的NetCoreIdentityAuthProvider感兴趣,该example on GitHub提供了一个将经过身份验证的.NET Core身份用户映射到经过身份验证的ServiceStack用户会话的适配器。
因此,如果您使用IdentityServer对.NET Core应用进行身份验证,则访问ServiceStack Services时,经过身份验证的用户应映射到经过身份验证的UserSession。
查看您的"sub" Claim后,我有几点笔记。基本上,由于您已决定使用IdentityServer作为身份验证提供程序,因此删除了除NetCoreIdentityAuthProvider
之外的所有其他ServiceStack AuthProvider:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new NetCoreIdentityAuthProvider(AppSettings),
}));
哪个提供了适配器,以将身份用户ClaimsPrincipal
转换为ServiceStack身份验证的UserSession(反之亦然)。
如果您使用的是NetCoreIdentityAuthProvider
,还应该删除替代的IdentityServerAuthFeature
实施,这样您就只采用一种与Identity Server Auth集成的解决方案:
// this.Plugins.Add(new IdentityServerAuthFeature() // remove...
由于Identity Server使用JWT填充ClaimsPrincipal
用户,因此它不使用ClaimTypes.NameIdentifier
来指示会话ID使用什么。 JWT通常有一个your first call来标识作为JWT主题的主体,该主体是在ServiceStack的AuthUserSession.Id
中填充的,而AuthUserSession.Type
中将填充“ sub”以指示经过身份验证的类型会话,并且会话Id
中使用了JWT的子对象(通常是用户ID)。
您将能够使用默认的NetCoreIdentityAuthProvider
配置来对Identity Server JWT进行身份验证,该身份验证JWT会按照RequestTokenAsync_CallResourceOwnerFlow()
中的example token I got from this request进行身份验证:
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "roclient",
ClientSecret = "secret",
UserName = "bob",
Password = "password",
Scope = "apiMB openid",
});
您可以通过解码jwt.io中的JWT来验证,这是Bob's UserId的有效载荷:
{
"nbf": 1545170425,
"exp": 1545174025,
"iss": "http://127.0.0.1:65048",
"aud": [
"http://127.0.0.1:65048/resources",
"apiMB"
],
"client_id": "roclient",
"sub": "2",
"auth_time": 1545170425,
"idp": "local",
"scope": [
"openid",
"apiMB"
],
"amr": [
"pwd"
]
}
我们可以看到其中包含“ 2” 的“子”,即2nd Authentication Request:
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "password",
IsActive = true
}
您的doesn't contain a subject in its JWT是认证客户端的示例:
var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "apiMB"
});
其中latest v5.4.1 on MyGet,但仅填充:
{
"nbf": 1545170914,
"exp": 1545174514,
"iss": "http://127.0.0.1:65048",
"aud": [
"http://127.0.0.1:65048/resources",
"apiMB"
],
"client_id": "client",
"scope": [
"apiMB"
]
}
在这种情况下,ServiceStack会将其认证为客户端,其中AuthUserSession.Type
将被填充client_id
,会话Id
将被填充client
。
默认情况下,ServiceStack允许使用任何经过身份验证的client_id
(在到达ServiceStack之前由Identity Server进行验证)进行身份验证。如果您只想限制客户端应用程序的子集才能访问ServiceStack Services,则可以在RestrictToClientIds
中指定它们,例如:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new NetCoreIdentityAuthProvider(AppSettings) {
RestrictToClientIds = new List<string> { "client" },
},
}));
ServiceStack仅允许使用client
client_id的客户端应用程序进行访问。
在AuthUserSession的Audiences
中填充了JWT的受众群体(aud),而在Scopes
属性中填充了JWT范围,而会话{{1 }}字典。
Meta
中的这些更改仅在{{3}}中可用。如果您已经拥有v5.4.1,则需要清除NuGet缓存以从MyGet获取最新的v5.4.1:
NetCoreIdentityAuthProvider
与身份验证无关,但是我注意到您的代码中有一些问题,您可以从其中读取AppSettings的AppSettings,而应该使用$ nuget locals all -clear
属性,而不是创建新实例:
AppSettings
您还可以通过以下方式访问.NET Core的// var appSettings = new AppSettings(); // Use base.AppSettings instead
:
IConfiguration
与其尝试使用以下方法重新创建它:
var configuration = ((NetCoreAppSettings) AppSettings).Configuration;