【问题标题】:ASP.NET MVC - Get Google OAuth tokenASP.NET MVC - 获取 Google OAuth 令牌
【发布时间】:2014-07-23 03:28:16
【问题描述】:

我已经成功地在服务器端使用谷歌的 OAuth 配置了 MVC 5。但是,我也想使用用户的身份验证令牌执行 javascript,并且我不想强迫他们重新验证此功能。

如何保留用户的 OAuth 令牌以在使用客户端 OAuth API 时使用?

具体来说-我想加载登录用户的 youtube 订阅。 This page 有关于如何同时使用服务器和客户端 API 的信息,但我无法找到令牌在服务器回调中的位置。我在AccountControllerExternalLoginCallback 方法中查看了任何信息,但我无法弄清楚哪些数据包含令牌。如果我可以在服务器端对象上找到它,我可以将它们公开给视图以与 javascript 调用一起使用,但我找不到该令牌在哪里。

【问题讨论】:

    标签: asp.net asp.net-mvc oauth youtube-api


    【解决方案1】:

    您可以在 MVC5 Startup.Auth.cs 文件中自定义 GoogleOAuth2AuthenticationOptions 以请求离线访问代码和刷新令牌以用于 Google 的 OAuth2 api。

    在此示例中,我收集从 google 传递到 OWIN OAuth2 中间件的值,并将它们添加到您的 Callback 方法中可访问的声明中。

      var googleCreds = new GoogleOAuth2AuthenticationOptions
            {
                ClientId = "[replace with your google console issued client id]",
                ClientSecret = "[replace with your google console issued client secret]",
    
                Provider = new Microsoft.Owin.Security.Google.GoogleOAuth2AuthenticationProvider
                {
                    OnApplyRedirect = context =>
                    {
    
    
                        string redirect = context.RedirectUri;
                        redirect += "&access_type=offline";
                        redirect += "&approval_prompt=force";
                        redirect += "&include_granted_scopes=true";
    
    
                        context.Response.Redirect(redirect);
    
                    },
                    OnAuthenticated = context =>
                    {
                        TimeSpan expiryDuration = context.ExpiresIn ?? new TimeSpan();
                        context.Identity.AddClaim(new Claim("urn:tokens:google:email", context.Email));
                        context.Identity.AddClaim(new Claim("urn:tokens:google:url", context.GivenName));
                        if (!String.IsNullOrEmpty(context.RefreshToken))
                        {
                            context.Identity.AddClaim(new Claim("urn:tokens:google:refreshtoken", context.RefreshToken));
                        }
                        context.Identity.AddClaim(new Claim("urn:tokens:google:accesstoken", context.AccessToken));
                        if (context.User.GetValue("hd") != null)
                        {
    
                            context.Identity.AddClaim(new Claim("urn:tokens:google:hd", context.User.GetValue("hd").ToString()));
                        }
                        context.Identity.AddClaim(new Claim("urn:tokens:google:accesstokenexpiry", DateTime.UtcNow.Add(expiryDuration).ToString()));
    
                        return System.Threading.Tasks.Task.FromResult<object>(null);
                    }
                }
            };
            googleCreds.Scope.Add("openid");
            googleCreds.Scope.Add("email");
    
            app.UseGoogleAuthentication(googleCreds);
    

    现在您可以通过回调方法访问这些声明值。例如:

       var loginInfo = AuthenticationManager.GetExternalLoginInfo();
    string GoogleAccessCode = String.Empty;
    if (loginInfo.ExternalIdentity.Claims.FirstOrDefault(c => c.Type.Equals("urn:tokens:google:accesstoken")) != null)
                        {
                           GoogleAccessCode = loginInfo.ExternalIdentity.Claims.FirstOrDefault(c => c.Type.Equals("urn:tokens:google:accesstoken")).toString();
                    }
    

    在身份验证序列开始时,或在您完成 AuthenticationManager.GetExternalLoginInfo() 之后,您可以清除浮动的外部身份验证 cookie,以防止任何有问题的重复 cookie 堆积:

     if (Request.Cookies[".AspNet.ExternalCookie"] != null)
                {
                    var c = new System.Web.HttpCookie(".AspNet.ExternalCookie");
                    c.Expires = DateTime.Now.AddDays(-1);
                    Response.Cookies.Add(c);
                }
    

    【讨论】:

    • 谢谢!我今晚会试试这个。
    • 这让我更接近答案,但有时AuthenticationManager.GetExternalLoginInfo(); 只是返回 null,即使在我通过身份验证之后也是如此。有什么想法吗?
    • 中间件提供者设置一个名为“.AspNet.ExternalCookie”的cookie,然后重定向到您的回调方法。如果设置了 cookie,则 AuthenticationManager.GetExternalLoginInfo 请求有效。有时,如果您已经多次测试该序列,则会有多个 cookie 实例,这会导致问题。我目前的做法是在启动初始 ChallengeResult 序列之前或在收到回调之后清除任何名为“.AspNet.ExternalCookie”的 cookie。
    • 如果您仍然定期从 GetExternalLoginInfo() 返回 null,则可能是这个已知的 Owin 错误:stackoverflow.com/questions/22535146/…
    • 感谢您的链接!一段时间后我放弃了,因为我遇到了问题,下周我必须检查一下。
    【解决方案2】:

    在 OAuth 协议中,您的应用请求授权以访问由范围标识的资源,并且假设用户已通过身份验证并获得批准,您的应用会收到允许其访问这些资源的短期访问令牌,并(可选)刷新令牌以允许长期访问。

    在您的情况下,您需要存储用户批准访问其 YouTube 资源时提供的访问令牌。普通令牌仅提供一小时的访问权限,因此还要记录刷新令牌以启用更长的会话。将令牌服务器端添加到 http 标头中,并让您的客户端 javascript 使用它来获得对 google apis 的身份验证访问。

    有关如何实施的示例和基础知识可以从 Google 网站复制很多东西,但认为您最好阅读:

    1. 增量授权Using OAuth 2.0 for Web Server Applications

    2. 离线访问在与上述相同的页面上使用刷新令牌

    3. OAuth 2.0 概述Google APIs Client Library for .NET的帮助

    我现在正在尝试构建一个框架来帮助我为我的用户存储和检索谷歌身份验证器结果,并发现上面的信息和它们包含的链接非常有用,希望它们也能帮助你。

    【讨论】:

    • 我知道我需要存储令牌,但在服务器端的对象中查找令牌本身时遇到了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多