ServiceStack尝试创建我自己的OpenIdOAuthProvider,但是VS 2017说缺少程序集5.0.0.0

时间:2018-12-14 10:30:04

标签: servicestack openid identityserver4 openid-provider

尝试创建自己的自定义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

这里有任何帮助。

1 个答案:

答案 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。

SS API示例

查看您的"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;