【问题标题】:OAuth 2 Google API refresh token is nullOAuth 2 Google API 刷新令牌为空
【发布时间】:2015-02-25 08:55:11
【问题描述】:

我正在开发一个 Asp.NET MVC5 App following this Google sample code。

我希望应用程序经过身份验证并由用户创建访问令牌(配置阶段),稍后我需要能够使用刷新令牌(无需用户干预,类似“离线”的东西)。

控制器:

public async Task<ActionResult> IndexAsync(CancellationToken cancellationToken)
{
    var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
                        AuthorizeAsync(cancellationToken);

        if (result.Credential != null)
        {
          var service = new Google.Apis.Admin.Directory.directory_v1.DirectoryService(new BaseClientService.Initializer
                        {
                            HttpClientInitializer = result.Credential,
                            ApplicationName = "My Application"
                        });
                      return View();
        }
        else
        {
             return new RedirectResult(result.RedirectUri);
        }
}         

流元数据实现。 (我使用 FiledataStore 稍作修改(GoogleFileDataStore))

public class AppFlowMetadata : FlowMetadata
    {
        //Move to settings
        static readonly string clientId = "xxxccnvofsdfsfoj.apps.googleusercontent.com";
        static readonly string clientsecret = "xxxxxxxxxxLvtC6Qbqpp4x_";
        static readonly string datastore = "AdminSDK.Api.Auth.Store";


         private static readonly IAuthorizationCodeFlow flow =
            new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = new ClientSecrets
                    {
                        ClientId = clientId,
                        ClientSecret = clientsecret
                    },
                    Scopes = new[] { DirectoryService.Scope.AdminDirectoryUser, DirectoryService.Scope.AdminDirectoryUserAliasReadonly },
                    DataStore = new GoogleFileDataStore(datastore)
                });


        public override string GetUserId(Controller controller)
        {           
            return ConfigHelper.UserID.ToString();
        }

        public override IAuthorizationCodeFlow Flow
        {
            get { return flow; }
        }
    }

当我调用 IndexAsync 控制器时,由于用户之前没有访问令牌,它会在用户登录 Google 帐户后创建一个新的。
这是一个示例访问令牌,

{"access_token":"ya29.5gBOszGO-oYJJt4YZfF6FeaZth1f69_.....","token_type":"Bearer","expires_in":3600,"Issued":"2014-12-24T16:02:32.014+05:30"}

问题1:为什么这里没有存储Refreshtoken?如何检索刷新令牌? 问题2:如果我拿到了refreshtoken,我应该如何修改代码创建一个新的access token并调用API(当accesstoken过期时)? [我提到了this question,但是对于缺少刷新令牌没有正确的答案。

【问题讨论】:

    标签: asp.net-mvc google-api-dotnet-client


    【解决方案1】:

    找到了谷歌API离线访问获取刷新令牌并使用刷新令牌创建新的accesstoken的解决方案,

    问题1:为什么这里没有存储Refreshtoken?如何检索刷新令牌?

    我必须在请求中将 access_type 设置为离线(默认为在线)。 as mentioned here

    我必须为 GoogleAuthorizationCodeFlow 类编写自己的实现。感谢this post.

     public class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
        {
            public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }
    
            public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
            {
                return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
                {
                    ClientId = ClientSecrets.ClientId,
                    Scope = string.Join(" ", Scopes),
                    RedirectUri = redirectUri,
                    AccessType = "offline",
                    ApprovalPrompt = "force"
                };
            }
        };
    

    问题2:..我应该修改代码以创建新的访问令牌并调用 API 吗?

        //try to get results
        var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
                        AuthorizeAsync(cancellationToken);
    
    
        //// This bit checks if the token is out of date, 
        //// and refreshes the access token using the refresh token.
        if (result.Credential.Token.IsExpired(SystemClock.Default))
        {
               Google.Apis.Auth.OAuth2.Responses.TokenResponse token = new Google.Apis.Auth.OAuth2.Responses.TokenResponse();
               //If the token is expired recreate the token
               token = await result.Credential.Flow.RefreshTokenAsync(ConfigHelper.UserID.ToString(), result.Credential.Token.RefreshToken, CancellationToken.None);
    
                //Get the authorization details back
                result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);
         }
    

    这对我有用!希望这对其他人有所帮助....

    【讨论】:

    • 这不是 Google 文档的一部分吗?此外,与我们必须使用 .NET 库跳过的循环相比,其他库中的脱机访问和刷新令牌似乎微不足道。浪费了这么多时间寻找解决方案,很高兴你发布了它!
    猜你喜欢
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-12-20
    • 2021-11-01
    • 1970-01-01
    相关资源
    最近更新 更多