ASP.NET Core 2.1: как получить доступ к "искам действия" в коде контроллера (особенно во время регистрации пользователя)?

63
4

Используя проверку подлинности OAuth2 на основе идентификационной информации (и получение информации о пользователе), последние образцы MS используют такой код:

   options.Events = new OAuthEvents
{
// ...
OnCreatingTicket = async (OAuthCreatingTicketContext context) =>
{
var userInfo = // ..
context.RunClaimActions(userInfo);
}
}

MS называют это "Требования к действию".

Но как получить доступ к этим заявлениям о действиях позже, в коде контроллера? Чтобы быть конкретным, как получить доступ к ним в "Core Identity 2.1" сгенерированные страницы Razor, пользовательский внешний вход OnGetCallbackAsync

// ExternalLogin.cshtml.cs
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
var claimsIdentity = User.Identity as ClaimsIdentity;
var claimsPrincipal = User.Identity as ClaimsPrincipal; // null
// claimsIdentity doesn't contains oauth target claims (since this new not registered yet user?)
// ..
var signInResult = await _signInManager.ExternalLoginSignInAsync(...);
if (signInResult.Succeeded)
{
}else // means yet not registered locally
{
// HOW TO ACCESS ACTION CLAIMS THERE?
// or how to get authentication token to get user info manually...
}
}

PS
Дополнительно к asnwer: RunClaimActions следует использовать вместе с MapJsonKey

serviceCollection.AddAuthentication().AddOAuth(options =>
{
// ...
// https://msdn.microsoft.com/en-us/library/microsoft.identitymodel.claims.claimtypes_members.aspx

options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
options.ClaimActions.MapJsonKey("SalesforceOrganizationId", "organization_id");

Тогда поля userinfo могут быть доступны как обычные заявки пользователя. Поэтому "Заявки на действие" не являются "особыми типами требований", а просто "еще одной магией ASP MVC".

Также не забывайте о параметрах. options.SaveTokens = true; Только с этим вы сможете получить токен как

var info = await _signInManager.GetExternalLoginInfoAsync();
var token = info.AuthenticationTokens ()[0];

и получить дополнительную информацию от других подключенных сервисов.

спросил(а) 2021-01-19T19:29:03+03:00 6 месяцев, 1 неделя назад
1
Решение
64

Я видел этот пример в официальной документации.

Ссылка Сохранение дополнительных претензий и токенов от внешних поставщиков в ASP.NET Core

Сначала вам нужно будет отобразить нужные претензии при настройке поставщика проверки подлинности

В примере с документацией использовался Google, где он сопоставляет ключи пользовательских данных и создает претензии

В опциях поставщика укажите MapJsonKey для каждого ключа в пользовательских данных внешнего поставщика JSON для идентификации приложения, которое необходимо прочитать при входе в систему.

Запускать

services.AddAuthentication().AddGoogle(options => {

//....

options.ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender");
//...map other claims/claim types

//...
}

И оттуда вы сможете получить доступ к ClaimsPrincipal через ExternalLoginInfo.Principal которого есть ClaimsPrincipal представляющий пользователя, связанного с логином.

ExternalLogin.cshtml.cs

//Executes when a previously registered user signs into the app.
public async Task<IActionResult> OnGetCallbackAsync(
string returnUrl = null, string remoteError = null) {
if (remoteError != null) {
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login");
}

// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null) {
return RedirectToPage("./Login");
}

// Sign in the user with this external login provider if the user
// already has a login
var result = await _signInManager.ExternalLoginSignInAsync(
info.LoginProvider, info.ProviderKey, isPersistent: false,
bypassTwoFactor : true);

if (result.Succeeded) {
// Store the access token and resign in so the token is included in
// in the cookie
var user = await _userManager.FindByLoginAsync(info.LoginProvider,
info.ProviderKey);

// What is the gender of this user if present
if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Gender)) {
var gender = info.Principal.FindFirst(ClaimTypes.Gender);
//...use gender
}

var props = new AuthenticationProperties();
props.StoreTokens(info.AuthenticationTokens);

await _signInManager.SignInAsync(user, props, info.LoginProvider);

_logger.LogInformation(
"{Name} logged in with {LoginProvider} provider.",
info.Principal.Identity.Name, info.LoginProvider);

return LocalRedirect(Url.GetLocalUrl(returnUrl));
}

if (result.IsLockedOut) {
return RedirectToPage("./Lockout");
} else {
// If the user does not have an account, then ask the user to
// create an account
ReturnUrl = returnUrl;
LoginProvider = info.LoginProvider;

if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Email)) {
Input = new InputModel {
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
}

return Page();
}
}

Просмотрите комментарии в коде и обратите внимание на доступ к info.Principal.Identity, который должен содержать претензии, связанные с текущим пользователем после выхода из системы.

ответил(а) 2021-01-19T19:29:03+03:00 6 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема