ASP.NET Core 2.1: как получить доступ к «заявкам на действия» в коде контроллера (особенно при регистрации пользователя)? - PullRequest
0 голосов
/ 31 августа 2018

При использовании аутентификации Core Identity 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...
        }
  }

приписка
В дополнение к ответу: 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];

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

1 Ответ

0 голосов
/ 02 сентября 2018

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

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

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

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

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

Запуск

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

    //....

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

    //...
}

И оттуда вы сможете получить доступ к претензиям через 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, который должен содержать утверждения, связанные с текущим пользователем после выхода в отставку.

...