Вход в Google — access_token, id_token и код

На нашем веб-сайте мы использовали access_token при регистрации людей с помощью Google Sign In. Во-первых, мы перенаправляем пользователя в Google, пользователь приносит нам access_token, и мы проверяем этот токен, чтобы убедиться, что пользователь является фактическим пользователем Google.

Затем нам понадобилась функция входа в Google для нашего приложения для Android, поэтому я хотел, чтобы разработчик Android предоставил нам access_token. Он ответил, что не может. Я искал об этом, не найдя почти никакой документации о access_token. В документации Google говорит мне использовать «id_token».

Хорошо, я хотел, чтобы разработчик принес мне id_token, и я успешно проверил целостность токена. Затем я захотел реализовать то же самое для веб-сайтов.

Мой код С#:

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

Это работало, когда я запускал его локально, но когда я пробовал в рабочей среде, он выдавал ошибку: JWT еще недействителен

Является ли id_token правильным способом отправки на сервер и проверки? Я также нашел другой вариант: code.

Код что-то вроде A/12112312......

Access_token — это что-то вроде ya29.somemorestring

Мой вопрос: какой из них правильно отправить на сервер? Кстати, я думаю, что access_token устарел или что-то в этом роде.


person Burak Yavuzalp    schedule 06.04.2018    source источник


Ответы (2)


Да, вы должны использовать 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());

Обратите внимание: это будет обновлять разницу между правильным временем и временем локальной машины каждый раз, когда создается класс, поэтому вы действительно хотите зарегистрировать его как Singleton в любом контейнере IOC, который вы используете, и вместо этого передать ссылку на валидатор. Затем он будет перепроверять время с помощью NNTP каждый час. Если вы не используете контейнер IOC, вы можете сделать класс статическим.

person Ben Noblet    schedule 09.04.2018
comment
В соответствии с заголовком вопроса вы также должны указать разницу во всех трех терминах. - person Amit Kumar Gupta; 29.09.2018

id_token — это токен JWT, который вы проверяете и извлекаете такую ​​информацию, как адрес электронной почты, имя и т. д. На самом деле это то, что вам нужно в обычном случае.

code и access_token являются частью потока, когда пользователь не использует ваше приложение в данный момент, но ваше приложение хочет выполнять какие-либо действия от его имени. Google называет это офлайн-доступом https://developers.google.com/identity/sign-in/web/server-side-flow

person Petr Schukin    schedule 30.01.2021