如何使用owin和Mvc 5从httpcontext获取访问令牌

18

我在IdentityServer 4中实施了一个IDP。我的Web应用程序客户端(在Mvc 5中实现)经过身份验证后,现在我需要从请求中获取访问令牌。 在.Net Core中执行此操作的一种方法是使用Microsoft.AspNetCore.Authentication.AuthenticationTokenExtensions,示例如下:

HttpContext.Authentication.GetTokenAsync("acccess_token")

我希望能在我的 .net Mvc5 网页应用客户端中做同样的事情,但是我找不到任何 NuGet 包或命名空间有类似的实现。能够在 MVC5 中而不是 .net Core 中做到这一点非常重要。有人之前遇到过这个问题吗?

PS- 还值得一提的是我正在使用 OpenIdConnect


1
你能否使用下面的答案解决问题? - Incredible
抱歉,我发布了这个问题太久了,以至于我忘记选择了哪个解决方案。 - Txugo
4个回答

23
最近发布的Katana 4.1.0版本现在支持SaveTokens属性(从ASP.NET Core中回退)。
为了获取访问令牌:
  1. Microsoft.Owin.Security.OpenIdConnect软件包更新到4.1.0或更高版本
  2. 在Startup类中配置SaveTokens
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    // Other options removed for readability
    SaveTokens = true,

    // Required for the authorization code flow to exchange for tokens automatically
    RedeemCode = true
});
  1. 在你的控制器中读取访问令牌:
var result = await Request.GetOwinContext().Authentication.AuthenticateAsync("Cookies");
string token = result.Properties.Dictionary["access_token"];

3
为什么Request.GetOwinContext().Authentication.AuthenticateAsync可能返回null?即使设置了SaveTokens和RedeemCode为true,您有什么建议吗? - Hos
@kape - 这个能在 .Net Framework 4.7.1 上运行吗?我已经按照上述属性进行了设置,但中间件仍然无法自动兑换代码。请查看我的问题:https://dev59.com/17joa4cB1Zd3GeqPHO6a - nari447
1
+1 这是一种可怕的复杂方式来访问access_token。我在半打SO链接和更多的微软文档中花了一天的时间,这是我找到的读取未加密access_token的解决方案?谢谢!我需要将其传递给Graph API。这也适用于HttpContext。HttpContext.Current.GetOwinContext().Authentication.AuthenticateAsync("Cookies") - Luminous
发布 .NET CORE 解决方案的链接。https://dev59.com/kVUL5IYBdhLWcg3wSmYo#50623141 - Luminous
@Hos,我找到了解决方案。我认为你和我一样,在SignInAsAuthenticationType或AuthenticationType中打错了一个字母,因此使用“Cookies”无法正常工作。 - Константин Золин
首先,对于这个解决方案要点赞。这在任何微软文档中都没有提到,但却非常有效。现在我能够从“GetOwinContext().Authentication.AuthenticateAsync("Cookies")”获取access_token、id_token和refresh_token了,但问题是如何从同一属性中获取access_token的发行和过期时间?ExpireUtC给出了Id token的时间……但是否有任何代码可以明确地给出access_token的过期时间? - Mahajan344

1

在您的控制器中,您可以使用以下代码获取令牌:

var token = ActionContext.Request.Headers.Authorization.Parameter;

1
你能为这个问题添加一些背景信息吗? - Ross Brasseaux

0
OpenIdConnectAuthenticationNotifications事件中,AutenticationTicket及其claims已准备就绪(无需调用userinfo端点)。 为了使该票据(claimsprincipal)可用于httpcontext.current.user,请在SecurityTokenValidated事件内执行以下操作(ReplaceIdentity只是一个自定义扩展方法,用于替换具有相同类型的标识的声明):
Notifications = new OpenIdConnectAuthenticationNotifications
{
    SecurityTokenValidated = (notification) =>
    {
        notification.AuthenticationTicket.Identity.AddClaim(new Claim("id_token", notification.ProtocolMessage.IdToken));
        notification.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", notification.ProtocolMessage.AccessToken));
        
        notification.OwinContext.Authentication.User.ReplaceIdentity(notification.AuthenticationTicket.Identity);

        return Task.CompletedTask;
    }

实现这个结果花了我三天的测试...但是效果非常好,您将可以在HttpContext.Current.User中获得用户身份和其他身份。

-1

我之前花了一些时间才明白,我们需要将一个字符串作为AuthenticateAsync的参数发送,该参数用于AuthenticationType和SignInAsAuthenticationType。 我强烈建议使用CookieAuthenticationDefaults.AuthenticationType,因为它可以避免打错字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接