5

Я прошел через документы identServer4, и я установил его для использования Microsoft Office 365 в качестве поставщика логина. Когда пользователь вошел в систему, я хочу сделать кнопку, где он может позволить мое приложение, чтобы подписаться на его события календаря с помощью webhooks апи из graph.microsoft.comИдентификатор ASP.NET (с IdentityServer4) получает внешний токен доступа oauth доступа

Код в startup.cs

app.UseMicrosoftAccountAuthentication(new MicrosoftAccountOptions 
{ 
    AuthenticationScheme = "Microsoft", 
    DisplayName = "Microsoft", 
    SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme, 

    ClientId = "CLIENT ID", 
    ClientSecret = "CLIENT SECRET", 
    CallbackPath = new PathString("/signin-microsoft"), 
    Events = new OAuthEvents 
    { 
     OnCreatingTicket = context => 
     { 
      redisCache.Set("AccessToken", context.AccessToken.GetBytes(), new DistributedCacheEntryOptions 
      { 
       AbsoluteExpiration = DateTimeOffset.UtcNow.AddDays(3) 
      }); 
      return Task.FromResult(context); 
     } 
    } 
    Scope = 
    { 
     "Calendars.Read", 
     "Calendars.Read.Shared", 
    }, 
    SaveTokens = true 
}); 

Но это, очевидно, не жизнеспособный путь. Я сделал это только для целей тестирования и для того, чтобы сделать PoC необходимых подписей.

Теперь я хотел бы знать, есть ли более умный способ связи с идентификатором Server, который позволяет мне получить этот токен внешнего доступа, чтобы я мог использовать microsoft api от имени моих зарегистрированных пользователей?

Или мой единственный вариант - взять Microsoft AccessToken прямо из этого OAuthEvent и сохранить его непосредственно в базе данных, связанной с зарегистрированным пользователем?

Мне это действительно нужно, поскольку большинство моих функций основано на данных третьих лиц.

ответ

8

Итак, я наконец получил эту работу. Я создал новый проект, который использует ASP.Net Identity и IdentityServer4, оба построены поверх ASP.Net Core.

Проблема была в том, что я не был полностью осведомлен о потоке, который использовался во внешнем процессе входа.

При использовании котла пластины с обеих систем вы будете иметь AccountController где следующий метод будет присутствовать:

// 
// GET: /Account/ExternalLoginCallback 
[HttpGet] 
[AllowAnonymous] 
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null) 
{ 
    if (remoteError != null) 
    { 
     ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}"); 
     return View(nameof(Login)); 
    } 
    var info = await _signInManager.GetExternalLoginInfoAsync(); 
    if (info == null) 
    { 
     return RedirectToAction(nameof(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); 
    if (result.Succeeded) 
    { 
     await _signInManager.UpdateExternalAuthenticationTokensAsync(info); 

     _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider); 
     return RedirectToLocal(returnUrl); 
    } 
    if (result.RequiresTwoFactor) 
    { 
     return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl }); 
    } 
    if (result.IsLockedOut) 
    { 
     return View("Lockout"); 
    } 
    else 
    { 
     // If the user does not have an account, then ask the user to create an account. 
     ViewData["ReturnUrl"] = returnUrl; 
     ViewData["LoginProvider"] = info.LoginProvider; 
     var email = info.Principal.FindFirstValue(ClaimTypes.Email); 
     return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email }); 
    } 
} 

Важной частью здесь является:

await _signInManager.UpdateExternalAuthenticationTokensAsync(info);

Это сохранит ваши внешние учетные данные в таблице базы данных, связанной с вашим ASP.Net identity. В таблице AspNetUserTokens у вас теперь будет 3 записи, которые называются примерно так: access_token, expires_at и token_type.

Эти токены, которые нас интересуют, которые мы можем использовать для доступа к учетным записям пользователей в другом месте в нашем приложении.

Чтобы извлечь эти маркеры в контексте вошедшего в систему пользователя:

var externalAccessToken = await _userManager.GetAuthenticationTokenAsync(User, "Microsoft", "access_token");

И за ними для пользователя мы извлекаем из БД можно использовать:

var user = _userManager.Users.SingleOrDefault(x => x.Id == "myId"); 
if (user == null) 
    return; 

var claimsPrincipal = await _signInManager.CreateUserPrincipalAsync(user); 
var externalAccessToken = await _userManager.GetAuthenticationTokenAsync(claimsPrincipal, "Microsoft", "access_token"); 
+0

Привет Кристиана , используете ли вы все части в одном проекте asp.net или имеете другую конечную точку для IdentityServer? –

+0

@AmrElsehemy Я размещаю сервер идентификации в отдельном проекте. Мы используем микросервисы, а наши другие API-интерфейсы взаимодействуют с сервером идентификации через промежуточное программное обеспечение проверки доступа к токену. Надеюсь, что это ответ на ваш вопрос. –

+0

Спасибо, еще один вопрос: сервер идентификации, размещенный в той же конечной точке или внешний, который лучше использовать? –

Смежные вопросы