Пакет ServiceStack.Authentication.OpenId является проектом .NET Framework только, который не поддерживается в .NET Core из-за OpenIdOAuthProvider.cs , требующего DotNetOpenAuth, который являетсянедоступно для .NET Core.
Поскольку вы используете предварительные выпуски v5.4.1 MyGet , вас может заинтересовать новый NetCoreIdentityAuthProvider , который обеспечиваетадаптер, который сопоставляет аутентифицированного пользователя .NET Core Identity с аутентифицированным пользовательским сеансом ServiceStack.
Таким образом, если вы аутентифицируете свое .NET Core приложение с помощью IdentityServer, то аутентифицированный пользователь должен сопоставляться с аутентифицированным UserSession при доступе к ServiceStack Services.
Пример SS API
У меня есть несколько заметок после просмотра вашего примера на GitHub .По сути, поскольку вы решили использовать IdentityServer в качестве провайдера аутентификации, вы удаляете все другие сервис-провайдеры ServiceStack, за исключением NetCoreIdentityAuthProvider
:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new NetCoreIdentityAuthProvider(AppSettings),
}));
, который предоставляет адаптер для преобразования из аутентификационного пользователя ClaimsPrincipal
в ServiceStack AuthenticatedUserSession (и наоборот).
Если вы используете NetCoreIdentityAuthProvider
, вам также следует удалить альтернативную реализацию IdentityServerAuthFeature
, чтобы вы использовали только одно решение для интеграции с Identity Server Auth:
// this.Plugins.Add(new IdentityServerAuthFeature() // remove...
Поскольку Identity Server использует JWT для заполнения ClaimsPrincipal
пользователя, он не использует ClaimTypes.NameIdentifier
, чтобы указать, что использовать для идентификатора сеанса.У JWT обычно есть "sub" Претензия , чтобы идентифицировать принципала, который является предметом JWT, который заполнен в AuthUserSession.Id
ServiceStack, и AuthUserSession.Type
будет заполнен "sub", чтобы указать ТипСеанс, прошедший проверку подлинности, и то, что подсистема JWT (обычно это Идентификатор пользователя) используется в сеансе Id
.
. Вы сможете использовать конфигурацию по умолчанию NetCoreIdentityAuthProvider
для аутентификации с помощью JWT Identity Server, который аутентифицируетПользователь, как это было сделано в вашем первом вызове в RequestTokenAsync_CallResourceOwnerFlow()
:
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "roclient",
ClientSecret = "secret",
UserName = "bob",
Password = "password",
Scope = "apiMB openid",
});
, который вы можете проверить, расшифровав JWT в jwt.io, вот полезная нагрузка примера токенаЯ получил от этого запроса :
{
"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"
]
}
, который мы видим, содержит "sub" из "2" , который UserId Боба :
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "password",
IsActive = true
}
Ваш 2-й запрос аутентификации является примером аутентификации клиента:
var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "apiMB"
});
Который не содержит субъекта в своем JWT но вместо этого заполняется только:
{
"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"
]
}
В этомcase ServiceStack с аутентификацией в качестве клиента, где AuthUserSession.Type
будет заполнен client_id
, а сеанс Id
будет заполнен client
.
По умолчанию ServiceStack позволяет проходить аутентификацию с любым Аутентифицированным client_id
(который проверяется Identity Server, прежде чем он достигнет ServiceStack).Если вместо этого вы хотите ограничить доступ к Сервисным службам только подмножеству клиентских приложений, вы можете указать их в RestrictToClientIds
, например:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new NetCoreIdentityAuthProvider(AppSettings) {
RestrictToClientIds = new List<string> { "client" },
},
}));
, где ServiceStack разрешит доступ только из клиентских приложений сclient
client_id.
Аудитории (aud) JWT заполняются в Audiences
AuthUserSession, в то время как области действия JWT заполняются в свойстве Scopes
, тогда как все другие несопоставленные свойства из JWT всеансы Meta
словарь.
Эти изменения в NetCoreIdentityAuthProvider
доступны только в последней версии 5.4.1 на MyGet .Если у вас уже был v5.4.1, вам нужно очистить кеш NuGet, чтобы получить последнюю версию v5.4.1 из MyGet:
$ nuget locals all -clear
Проблемы с проверкой кода
Не относится к аутентификации, но язаметил несколько проблем в вашем коде, где для чтения AppSettings из вашего приложения вы должны просто использовать свойство AppSettings
вместо создания нового экземпляра:
// var appSettings = new AppSettings(); // Use base.AppSettings instead
Вы также можете получить доступ к .NET Core IConfiguration
с помощью:
var configuration = ((NetCoreAppSettings) AppSettings).Configuration;
Вместо попытки воссоздать его с помощью:
//IConfigurationRoot configuration = new ConfigurationBuilder()
// .SetBasePath(Directory.GetCurrentDirectory())
// .AddJsonFile("appsettings.json")
// .Build();