谷歌登录 - “access_token” vs “id_token” vs “code”

Posted

技术标签:

【中文标题】谷歌登录 - “access_token” vs “id_token” vs “code”【英文标题】:Google SignIn - "access_token" vs "id_token" vs "code" 【发布时间】:2018-09-16 16:06:53 【问题描述】:

在我们的网站上,我们曾经在使用 Google 登录登录用户时使用 access_token。首先,我们将用户重定向到 google,用户将 access_token 带给我们,我们验证该令牌以确保用户是实际的 Google 用户。

然后,我们的 android 应用需要 Google 登录功能,因此我希望 Android 开发人员将 access_token 带给我们。他回答说不能。我搜索了一下,发现几乎没有关于 access_token 的文档。在文档中,谷歌说我使用“id_token”。

好的,我希望开发者给我带来 id_token,我已经成功验证了令牌的完整性。然后我想为网站实现相同的功能。

我的 c# 代码是:

string googleId = GoogleJsonWebSignature.ValidateAsync(idToken).Result.Subject;

当我在本地运行它时它可以工作,但是当我在生产环境中尝试时,它给出了一个错误:JWT 尚未有效

id_token 是发送到后端并验证的正确方式吗?我也找到了另一个选择:code

代码类似于 A/12112312......

Access_token 类似于 ya29.somemorestring

我的问题是,哪个是正确的发送到后端?顺便说一句,我认为 access_token 有点被弃用或类似的东西。

【问题讨论】:

【参考方案1】:

是的,您应该使用 id_token。您可以使用以下方法在客户端获取 id_token:

var id_token = googleUser.getAuthResponse().id_token;

并在服务器端使用验证它(在 try/catch 块中执行以捕获任何错误):

token = await GoogleJsonWebSignature.ValidateAsync(idToken);

JWT 尚未生效错误是由于您的服务器上的时间很慢。即使慢了几秒钟也会导致这个问题。为了确保它一直有效,您需要实现一个自定义时钟,它可以从某个地方获取准确的时间。这是一个使用 NNTP 的示例:

public class AccurateClock : Google.Apis.Util.IClock

    const int UpdateIntervalMinutes = 60;
    const string NntpServer = "time.nist.gov";

    private TimeSpan _timeOffset;
    private DateTime _lastChecked;

    public AccurateClock()
    
        _timeOffset = TimeSpan.FromSeconds(0);
        _lastChecked = DateTime.MinValue;
    

    private DateTime GetTime()
    
        try
        
            if (DateTime.Now.Subtract(_lastChecked).TotalMinutes >= UpdateIntervalMinutes)
            
                // Update offset 
                var client = new TcpClient(NntpServer, 13);
                DateTime serverTime;
                using (var streamReader = new StreamReader(client.GetStream()))
                
                    var response = streamReader.ReadToEnd();
                    var utcDateTimeString = response.Substring(7, 17);
                    serverTime = DateTime.ParseExact(utcDateTimeString, "yy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
                
                _timeOffset = DateTime.UtcNow.Subtract(serverTime);
                _lastChecked = DateTime.Now;
            
            var accurateTime = DateTime.UtcNow.Subtract(_timeOffset);
            return accurateTime;
        
        catch (Exception ex)
        
            return DateTime.UtcNow;
        

    

    public DateTime Now
    
        get
        
            return GetTime().ToLocalTime();
        
    

    public DateTime UtcNow
    
        get
        

            return GetTime();
        
    

然后您将自定义时钟传递给验证方法。

token = await GoogleJsonWebSignature.ValidateAsync(idToken, new AccurateClock());

请注意:这将在每次创建类时更新正确时间和本地机器时间之间的差异,因此您确实希望在您使用的任何 IOC 容器中将其注册为单例并将引用传递给验证器代替。然后它将每小时使用 NNTP 重新检查时间。如果您不使用 IOC 容器,则可以将类设为静态。

【讨论】:

根据问题标题,您还应该提及所有三个术语的区别。【参考方案2】:

id_token 是一个 JWT 令牌,用于验证和提取“电子邮件”、“姓名”等信息。这实际上是您在常规情况下所需要的。

codeaccess_token 是当用户当前不使用您的应用但您的应用想要代表他们执行任何操作时流程的一部分。 Google 称之为离线访问https://developers.google.com/identity/sign-in/web/server-side-flow

【讨论】:

以上是关于谷歌登录 - “access_token” vs “id_token” vs “code”的主要内容,如果未能解决你的问题,请参考以下文章

google plus login vs google login,有啥区别?

既生瑜何生亮 access_token VS refresh_token

OAuth 2 access_token vs OpenId Connect id_token

Python web 开发微博授权登录,获取access_token

access_token 怎么获取

微信第三方登录接口流程