ASP.NET身份(带有IdentityServer4)获取外部资源OAuth访问令牌



我曾经通过IdentityServer4的文档,我已经将其设置为使用Microsoft Office 365作为登录提供商。当用户登录时,我想制作一个按钮,他可以在其中使用Graph.microsoft.com

的Webhooks API订阅他的日历事件。

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。

现在,我想知道是否有一种更聪明的方法可以与IdentityServer进行通信,使我能够获得此外部访问令牌,以便我可以代表我的登录用户使用Microsoft API?

还是我唯一直接从此OAuthevent获取Microsoft AccessToken并将其直接存储在数据库中的唯一选择,并链接到登录用户中?

我真的需要这个,因为我的大多数功能都是基于来自第三方的数据。

好吧,所以我终于得到了这个工作。我创建了一个使用ASP.Net IdentityIdentityServer4的新项目,都在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_tokenexpires_attoken_type

这些是我们感兴趣的令牌,我们可以用来访问应用程序中其他地方的用户凭据。

在登录用户的上下文中获取这些令牌:

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

并为用户获取我们可以使用的DB获取的用户:

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");

相关内容

  • 没有找到相关文章

最新更新