简体   繁体   English

如何使用刷新令牌续订访问令牌?

[英]How to renew the access token using the refresh token?

I am using ASP.NET MVC 5 with OWIN . 我正在使用带有OWIN的 ASP.NET MVC 5

I have done a lot of research and haven't found how to renew the access token using the refresh token. 我做了很多研究,但没有找到如何使用刷新令牌续订访问令牌。

My scenario is: The first time the user accesses my app, he or she grants access to the account I read the refresh token returned from the API. 我的方案是:用户第一次访问我的应用时,他或她授予访问我读取API返回的刷新令牌的帐户的权限。 When the users come back to my app, I need to refresh the access token based on the "Refresh Token". 当用户返回我的应用程序时,我需要根据“刷新令牌”刷新访问令牌。

Could anybody provide some code? 有人可以提供一些代码吗?

Here is what I've achieved till now: 这是我到目前为止所取得的成就:

Startup.Auth.cs: Startup.Auth.cs:

    var googleOAuth2AuthenticationOptions = new GoogleOAuth2AuthenticationOptions
    {
        Caption = "Google+",
        ClientId = Parameters.Instance.Authentication.oAuth.GooglePlus.ClientId,
        ClientSecret = Parameters.Instance.Authentication.oAuth.GooglePlus.ClientSecret,
        CallbackPath = new PathString("/oauth-login-return"),
        Provider = new GoogleOAuth2AuthenticationProvider
        {
            OnAuthenticated = async context =>
            {
                context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirstValue(ClaimTypes.Name)));
                context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Identity.FindFirstValue(ClaimTypes.Email)));
                context.Identity.AddClaim(new Claim("picture", context.User.GetValue("picture").ToString()));
                context.Identity.AddClaim(new Claim("profile", context.User.GetValue("profile").ToString()));
                context.Identity.AddClaim(
                    new Claim(Parameters.Instance.Authentication.oAuth.GooglePlus.AccessTokenClaimType,
                        context.AccessToken));
            }
        }
    };
    googleOAuth2AuthenticationOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
    googleOAuth2AuthenticationOptions.Scope.Add("https://www.googleapis.com/auth/userinfo.email");

AuthenticationController: AuthenticationController:

[HttpPost]
[AllowAnonymous]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
    RedirectIfAuthenticated();

    return new ChallengeResult(provider, Url.Content("~/oauth-login-callback"));
}

[ActionName("oauth-login-back")]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
}

// Used for XSRF protection when adding external logins
private const string XsrfKey = "XsrfId";

private IAuthenticationManager AuthenticationManager
{
    get
    {
        return HttpContext.GetOwinContext().Authentication;
    }
}

private class ChallengeResult : HttpUnauthorizedResult
{
    public ChallengeResult(string provider, string redirectUri)
        : this(provider, redirectUri, null)
    {
    }

    private ChallengeResult(string provider, string redirectUri, string userId)
    {
        LoginProvider = provider;
        RedirectUri = redirectUri;
        UserId = userId;
    }

    private string LoginProvider { get; set; }

    private string RedirectUri { get; set; }

    private string UserId { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        var properties = new AuthenticationProperties { RedirectUri = RedirectUri };
        if (UserId != null)
        {
            properties.Dictionary[XsrfKey] = UserId;
        }
        context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
    }
}

This question isn't duplicate AT ALL. 这个问题并非重复。 I hope this help others not spending days like I have spent. 我希望这能帮助别人不要像我花的那样度过几天。

After almost 4 days I have found out how to get a fresh access token in the google api using OWIN. 差不多4天后,我发现了如何使用OWIN在google api中获取新的访问令牌。

I'm going to post the solution, but first, I MUST say that what helped me to start getting a clue about my error was setting up the Debug Symbols for the Katana project. 我将发布解决方案,但首先,我必须说,帮助我开始弄清楚我的错误的是设置Katana项目的调试符号。 See this link: http://www.symbolsource.org/Public/Home/VisualStudio 请看以下链接: http//www.symbolsource.org/Public/Home/VisualStudio

This image show how to configure Debug Symbols Servers. 此图显示了如何配置调试符号服务器。 在此输入图像描述

And this one shows the Katana Debug Symbols being loaded. 这一个显示正在加载的Katana调试符号。 在此输入图像描述

After that, I found out that my problem was that Google API was returning 403: Forbidden 之后,我发现我的问题是Google API正在返回403:Forbidden

"Access Not Configured. Please use Google Developers Console to activate the API for your project" “未配置访问权限。请使用Google Developers Console激活项目的API”

Then, found on stack overflow this post: "Access Not Configured. Please use Google Developers Console to activate the API for your project." 然后,发现堆栈溢出这篇文章: “访问未配置。请使用Google Developers Console激活项目的API。”

more specifically this Answer: https://stackoverflow.com/a/24401189/833846 更具体地说,这个答案: https//stackoverflow.com/a/24401189/833846

After that, I went to Google Developers Console and setup up Google+ API 之后,我访问了Google Developers Console并设置了Google+ API

And then, voillá! 然后,voillá! It worked. 有效。

Now, the code to get a fresh access token using the refresh token (I haven't found any way to accomplish that using the OWIN API). 现在,使用刷新令牌获取新访问令牌的代码(我还没有找到任何方法来使用OWIN API实现这一点)。

public static class TokenValidator
{
    /// <summary>
    /// Obtém um novo access token na API do google.
    /// </summary>
    /// <param name="clientId"></param>
    /// <param name="clientSecret"></param>
    /// <param name="refreshToken"></param>
    /// <returns></returns>
    public static GoogleRefreshTokenModel ValidateGoogleToken(string clientId, string clientSecret, string refreshToken)
    {
        const string url = "https://accounts.google.com/o/oauth2/token";

        var parameters = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("client_id", clientId),
            new KeyValuePair<string, string>("client_secret", clientSecret),
            new KeyValuePair<string, string>("grant_type", "refresh_token"),
            new KeyValuePair<string, string>("refresh_token", refreshToken)
        };

        var content = GetContentAsync(url, "POST",  parameters);

        var token = JsonConvert.DeserializeObject<GoogleRefreshTokenModel>(content);

        return token;
    }

    private static string GetContentAsync(string url, 
        string method = "POST",
        IEnumerable<KeyValuePair<string, string>> parameters = null)
    {
        return method == "POST" ? PostAsync(url, parameters) : GetAsync(url, parameters);
    }

    private static string PostAsync(string url, IEnumerable<KeyValuePair<string, string>> parameters = null)
    {
        var uri = new Uri(url);

        var request = WebRequest.Create(uri) as HttpWebRequest;
        request.Method = "POST";
        request.KeepAlive = true;
        request.ContentType = "application/x-www-form-urlencoded";

        var postParameters = GetPostParameters(parameters);

        var bs = Encoding.UTF8.GetBytes(postParameters);
        using (var reqStream = request.GetRequestStream())
        {
            reqStream.Write(bs, 0, bs.Length);
        }

        using (var response = request.GetResponse())
        {
            var sr = new StreamReader(response.GetResponseStream());
            var jsonResponse = sr.ReadToEnd();
            sr.Close();

            return jsonResponse;
        }
    }

    private static string GetPostParameters(IEnumerable<KeyValuePair<string, string>> parameters = null)
    {
        var postParameters = string.Empty;
        foreach (var parameter in parameters)
        {
            postParameters += string.Format("&{0}={1}", parameter.Key,
                HttpUtility.HtmlEncode(parameter.Value));
        }
        postParameters = postParameters.Substring(1);

        return postParameters;
    }

    private static string GetAsync(string url, IEnumerable<KeyValuePair<string, string>> parameters = null)
    {
        url += "?" + GetQueryStringParameters(parameters);

        var forIdsWebRequest = WebRequest.Create(url);
        using (var response = (HttpWebResponse)forIdsWebRequest.GetResponse())
        {
            using (var data = response.GetResponseStream())
            using (var reader = new StreamReader(data))
            {
                var jsonResponse = reader.ReadToEnd();

                return jsonResponse;
            }
        }
    }

    private static string GetQueryStringParameters(IEnumerable<KeyValuePair<string, string>> parameters = null)
    {
        var queryStringParameters = string.Empty;
        foreach (var parameter in parameters)
        {
            queryStringParameters += string.Format("&{0}={1}", parameter.Key,
                HttpUtility.HtmlEncode(parameter.Value));
        }
        queryStringParameters = queryStringParameters.Substring(1);

        return queryStringParameters;
    }
}

IMPORTANT 1: To get a refresh token you must set the "access_type" to "offline" in the " ExecuteResult " method, this way: 重要事项1:要获取刷新令牌,必须在“ ExecuteResult ”方法中将“access_type”设置为“offline”,这样:

properties.Dictionary["access_type"] = "offline";

IMPORTANT 2: Once you get your refresh token, you must store it and in some secure source. 重要信息2:获得刷新令牌后,您必须将其存储在某个安全源中。 Google API won't issue you a new refresh token, unless you set "approval_prompt" to "force" before you call the line (in the same method): Google API不会向您发送新的刷新令牌,除非您在调用该行之前将“approval_prompt”设置为“强制”(使用相同的方法):

context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);

I also recommend taking a look at: 我还建议你看看:

Google API Offline Access Google API离线版访问

Google OAUTH 2.0 Playground Google OAUTH 2.0 Playground

Google API Discovery Check Google API发现检查

Spent the last two days figuring out how to renew the access token myself. 花了最后两天搞清楚如何更新访问令牌。 The answer is posted in another thread here: 答案发布在另一个帖子中:

How Google API V 3.0 .Net library and Google OAuth2 Handling refresh token Google API V 3.0 .Net库和Google OAuth2如何处理刷新令牌

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 续订Facebook访问令牌 - Renew Facebook Access Token 如何刷新访问令牌 - How to refresh access token 每次请求都更新访问令牌 - Renew access token with every request 如果您刚被授予ClientId和ClientSecret以及NO Refresh Token,那么为API续订Access Token的最佳做法是什么? - What is the best practice to renew Access Token for an API if you are just granted ClientId and ClientSecret and NO Refresh Token? 在asp.net core mvc中通过refresh_token无声更新access_token - Silent renew access_token via refresh_token in asp.net core mvc 有没有办法以编程方式更新Box刷新令牌? - Is there a way to programmatically renew a Box refresh token? 如何在 C# 中使用 FacebookClient 过期时以编程方式更新页面访问令牌? - How to renew Page Access Token programmatically when expired using FacebookClient in C#? 使用JWT令牌使访问令牌过期时刷新令牌调用 - Refresh Token call when Access token expired using JWT token 如何使用访问令牌和刷新令牌从Google API访问用户日历列表和事件 - How to access users calendar list and events from google api using access token and refresh token 如何使用 IHttpClientFactory 刷新令牌 - How to Refresh a token using IHttpClientFactory
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM