c# - ASP.NET 身份(使用 IdentityServer4)获取外部资源 oauth 访问 token

标签 c# oauth asp.net-identity identityserver4 asp.net-identity-3

我已经阅读了 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 通信,允许我获取此外部访问 token ,以便我可以代表我的登录用户使用 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 });
    }
}

这里的重要部分是:

等待 _signInManager.UpdateExternalAuthenticationTokensAsync(info);

这会将您的外部凭据保存在与您的 ASP.Net 身份 关联的数据库表中。在 AspNetUserTokens 表中,您现在将拥有 3 个条目,名称类似于: access_tokenexpires_attoken_type

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

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

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

关于c# - ASP.NET 身份(使用 IdentityServer4)获取外部资源 oauth 访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41040702/

相关文章:

c# - Orderby 不工作

c# - C# 应用程序中未使用的引用

javascript - GAPI 的 OAuth - 首次登录 Javascript 后避免身份验证和授权

c# - 无法将类型 'bool' 隐式转换为 'Microsoft.AspNetCore.Mvc.ActionResult'

asp.net-mvc - 使用多上下文应用程序自定义 ASPNET Identity 一对多关系

c# - .NET字典插入的怪异性能行为

c# - 日期时间格式 yyyymm

iOS LinkedIn API 错误

firebase - Twitter OAuth request_token : Error Code 32, 无法进行身份验证

c# - 更改身份数据库