Пакет ServiceStack.Authentication.OpenId — это проект только .NET Framework, который не поддерживается в .NET Core из-за того, что OpenIdOAuthProvider.cs требует DotNetOpenAuth, который недоступен для .NET Core.
Поскольку вы используете предварительные версии пакетов MyGet версии 5.4.1, вас могут заинтересовать новые NetCoreIdentityAuthProvider, который предоставляет адаптер, который сопоставляет прошедшего проверку подлинности пользователя .NET Core Identity с прошедшим проверку подлинностью сеансом пользователя ServiceStack.
Поэтому, если вы аутентифицируете свое приложение .NET Core с помощью IdentityServer, тогда аутентифицированный пользователь должен сопоставляться с Authenticated UserSession при доступе к ServiceStack Services.
Пример API СС
У меня есть несколько замечаний после просмотра вашего примера на GitHub. По сути, поскольку вы решили использовать IdentityServer в качестве поставщика аутентификации, вы удаляете все остальные поставщики аутентификации ServiceStack, кроме NetCoreIdentityAuthProvider
:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new NetCoreIdentityAuthProvider(AppSettings),
}));
Который предоставляет адаптер для преобразования из Identity User ClaimsPrincipal
в ServiceStack Authenticated UserSession (и наоборот).
Если вы используете NetCoreIdentityAuthProvider
, вам также следует удалить альтернативную реализацию IdentityServerAuthFeature
, чтобы вы применяли только одно решение для интеграции с аутентификацией Identity Server:
// this.Plugins.Add(new IdentityServerAuthFeature() // remove...
Поскольку Identity Server использует JWT для заполнения ClaimsPrincipal
пользователя, он не использует ClaimTypes.NameIdentifier
для указания того, что использовать для идентификатора сеанса. У JWT обычно есть "sub" утверждение для идентификации принципала, который тема JWT, которая заполняется в ServiceStack AuthUserSession.Id
и AuthUserSession.Type
, будет заполнена «sub», чтобы указать тип сеанса с проверкой подлинности и то, что 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", который является Идентификатор пользователя Боба:
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "password",
IsActive = true
}
Ваш второй запрос на клиент:
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"
]
}
В этом случае ServiceStack аутентифицирует его как клиента, где AuthUserSession.Type
будет заполнен client_id
, а сеанс Id
будет заполнен client
.
По умолчанию ServiceStack разрешает аутентификацию с помощью любого аутентифицированного client_id
(который проверяется Identity Server до того, как он достигает ServiceStack). Если вместо этого вы хотите ограничить доступ к ServiceStack Services только подмножеству клиентских приложений, вы можете указать их в RestrictToClientIds
, например:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new NetCoreIdentityAuthProvider(AppSettings) {
RestrictToClientIds = new List<string> { "client" },
},
}));
Где ServiceStack разрешает доступ только клиентским приложениям с идентификатором client
client_id.
Аудитории (aud) JWT заполняются в AuthUserSession Audiences
, в то время как области действия JWT заполняются в свойстве Scopes
, а все другие необработанные свойства из JWT — в словаре сеансов Meta
.
Эти изменения в NetCoreIdentityAuthProvider
доступны только в последней версии 5.4.1 на MyGet. Если у вас уже была версия 5.4.1, вам необходимо очистить кеш NuGet, чтобы получить последнюю версию 5.4.1 из MyGet:
$ nuget locals all -clear
Проблемы проверки кода
Не связано с аутентификацией, но я заметил несколько проблем в вашем коде, где для чтения AppSettings из вашего приложения вы должны просто использовать свойство AppSettings
вместо создания нового экземпляра:
// var appSettings = new AppSettings(); // Use base.AppSettings instead
Вы также можете получить доступ к IConfiguration
.NET Core с помощью:
var configuration = ((NetCoreAppSettings) AppSettings).Configuration;
Вместо того, чтобы пытаться воссоздать его с помощью:
//IConfigurationRoot configuration = new ConfigurationBuilder()
// .SetBasePath(Directory.GetCurrentDirectory())
// .AddJsonFile("appsettings.json")
// .Build();
person
mythz
schedule
14.12.2018