web-dev-qa-db-ja.com

更新トークンを使用してアクセストークンを更新する方法

[〜#〜] owin [〜#〜]とともにASP.NET MVC 5を使用しています。

私は多くの調査を行いましたが、リフレッシュトークンを使用してアクセストークンを更新する方法を見つけていません。

私のシナリオは、ユーザーが初めてアプリにアクセスするときに、APIから返された更新トークンを読み取るアカウントへのアクセスを許可します。ユーザーがアプリに戻ったとき、「更新トークン」に基づいてアクセストークンを更新する必要があります。

誰かがいくつかのコードを提供できますか?

これが私が今までに達成したことです:

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:

[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);
    }
}
15
Marco Alves

この質問は重複していませんAT ALL。これが他の人が私が費やしたような日を費やしていないのを助けることを願っています。

ほぼ4日後、OWINを使用してGoogle APIで新しいアクセストークンを取得する方法を見つけました。

解決策を投稿しますが、最初に、エラーについての手掛かりを得るために私が助けたのは、Katanaプロジェクトのデバッグシンボルを設定することでした。このリンクを参照してください: http://www.symbolsource.org/Public/Home/VisualStudio

この画像は、デバッグシンボルサーバーを構成する方法を示しています。 enter image description here

これは、読み込まれているKatanaデバッグシンボルを示しています。 enter image description here

その後、私の問題はGoogle APIが403:Forbiddenを返していたことであることがわかりました

「アクセスが構成されていません。GoogleDevelopers Consoleを使用してプロジェクトのAPIをアクティブにしてください」

次に、スタックオーバーフローでこの投稿を見つけます: "アクセスが構成されていません。GoogleDevelopers Consoleを使用してプロジェクトのAPIをアクティブにしてください。"

より具体的にはこの回答: https://stackoverflow.com/a/24401189/833846

その後、Google Developers Consoleに行き、Google + 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;
    }
}

重要1:更新トークンを取得するには、「ExecuteResultで「access_type」を「offline」に設定する必要があります "メソッド、この方法:

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

重要2:リフレッシュトークンを取得したら、それを何らかの安全なソースに保存する必要があります。 (同じメソッドで)行を呼び出す前に「approval_Prompt」を「force」に設定しない限り、Google APIは新しい更新トークンを発行しません。

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

また、以下をご覧になることをお勧めします。

Google APIオフラインアクセス

Google OAUTH 2.0 Playground

Google API検出チェック

25
Marco Alves

過去2日間、自分でアクセストークンを更新する方法を考えました。答えはここの別のスレッドに投稿されています:

Google API V 3.0 .NetライブラリとGoogle OAuth2処理の更新トークンの方法

3
Ogglas