授权代码交换不适用于Google OAuth2

时间:2017-12-06 08:56:28

标签: c# oauth-2.0 google-oauth2

我正在根据this tutorial在后端实施Google登录。

我有一个JS客户端:

Handler

<script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script> function start() { gapi.load('auth2', function() { auth2 = gapi.auth2.init({ client_id: 'MY_CLIENT_ID', scope: 'profile email https://www.googleapis.com/auth/plus.me', }); }); } <button id="signinButton">Login Google</button> <script> $('#signinButton').click(function() { auth2.grantOfflineAccess().then(signInCallback); }); </script> 函数中,我将signInCallback发送到服务器。

在服务器上,我需要从authResult['code']生成id_tokenaccess_token。我的后端是用ASP.NET CORE编写的。

本教程有Java和Python的后端实现示例。在服务器上,我正在执行以下操作:

serverAuthCode

我总是得到一个错误(随机)的错误请求:

  • redirect_uri_mismatch

  • invalid_grant

我是否对请求做错了?

1 个答案:

答案 0 :(得分:0)

您的代码与我与其他OAuth2成功使用的方法完全相同 / OIDC提供商。唯一的例外是Accept标题,因此您可以将其添加到您的代码中(不确定它是否会修复您的随机行为,但可能值得尝试)。

_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

为了完整起见,这是我使用的方法:

public async Task<TokenResponse> ExchangeCodeForTokens(Uri tokenEndpoint, string code, Uri redirectUri, string clientId, string clientSecret)
{
    var content = new FormUrlEncodedContent(new Dictionary<string, string>
    {
        {"grant_type", "authorization_code"},
        {"code", code},
        {"redirect_uri", redirectUri.ToString()},
        {"client_id", clientId},
        {"client_secret", clientSecret}
    });

    using (var client = _httpClientFactory())
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var response = await client.PostAsync(tokenEndpoint, content);
        var responseContent = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
            throw new OpenIdConnectException($"Request to token endpoint {tokenEndpoint} not successful: {responseContent}");

        var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(responseContent);
        if (tokenResponse == null)
            throw new OpenIdConnectException($"Request to token endpoint {tokenEndpoint} did not return a valid response: {responseContent}");

        return tokenResponse;
    }
}

TokenResponse的位置:

public class TokenResponse
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    [JsonProperty("expires_in")]
    public int ExpiresInSeconds { get; set; }

    [JsonProperty("refresh_token")]
    public string RefreshToken { get; set; }

    [JsonProperty("id_token")]
    public string IdToken { get; set; }

    [JsonProperty("token_type")]
    public string TokenType { get; set; }

    [JsonIgnore]
    public TimeSpan ExpiresIn => TimeSpan.FromSeconds(ExpiresInSeconds);
}