ASP.NET Identity(使用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并将其直接存储在链接到登录用户的数据库中的选项?
我真的需要这个,因为我的大部分function都是基于来自第三方的数据。
好的,所以我终于搞定了。 我创建了一个使用ASP.Net Identity
和IdentityServer4
的新项目,它们都构建在ASP.Net Core
之上。
问题是我并不完全了解外部登录过程中使用的流程。
如果您使用两个系统的锅炉板,您将拥有一个AccountController
,其中将存在以下方法:
// // GET: /Account/ExternalLoginCallback [HttpGet] [AllowAnonymous] public async Task 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");
要为我们从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");
- 从基础asp.net标识用户创建inheritance用户
- Identity UserManager.AddToRole抛出exception
- 如何在aspnet身份中进行会话管理?
- 刷新ASP.Net核心标识中的用户cookie票证
- CreateUserIdenityAsync返回自定义IdentityUser的“UserId not found”exception
- 在ASP.NET中的IdentityUserRole 2.0中获取角色名称
- 将MyDbContext合并到Asp.net IdentityDbContext
- MVC 5:我应该从IdentityUser类inheritance我的用户吗?
- 使用具有entity framework6的存储库模式更新记录