Могу ли я получить постоянное значение «iss» для токена id_token Google OpenIDConnect?

Я использую аутентификацию Google OpenIDConnect и хочу проверить JWT id_token, возвращенный Google. . Однако документация кажется противоречивой в отношении того, какое значение возвращает Google для утверждения iss (эмитент) в токене идентификатора.

Одна страница говорит: "iss: всегда account.google. com", но на другой странице написано: "Ценность iss в токен идентификатора равен accounts.google.com или https://accounts.google.com", а комментарий в примере кода поясняет:

// If you retrieved the token on Android using the Play Services 8.3 API or newer, set
// the issuer to "https://accounts.google.com". Otherwise, set the issuer to
// "accounts.google.com". If you need to verify tokens from multiple sources, build
// a GoogleIdTokenVerifier for each issuer and try them both.

У меня есть серверное приложение, а не приложение для Android, поэтому я не использую Play Services.

Чтобы еще больше замутить воду, сама спецификация OpenIDConnect содержит примечание тот:

Разработчики должны иметь в виду, что на момент написания этой статьи развернутая реализация Google OpenID Connect выпускает токены идентификаторов, в которых отсутствует требуемый префикс схемы https:// в значении утверждения iss (эмитента). Реализации проверяющей стороны, желающие работать с Google, должны иметь код для обхода этого до тех пор, пока их реализация не будет обновлена. Любой такой обходной код должен быть написан таким образом, чтобы не сломаться в такой момент, когда Google добавляет отсутствующий префикс к своим значениям эмитента.

Этот документ датирован 8 ноября 2014 года. С тех пор Google стандартизировал значение iss, или мне действительно нужно проверить их оба? Комментарий выше, кажется, указывает на то, что только Play Services>=8.3 получает iss с https://, а во всех остальных случаях значение будет просто accounts.google.com. Это правда?


person bjmc    schedule 27.07.2016    source источник
comment
Только что столкнулся с этим с сервером ресурсов Spring Security 5 и issuer-uri. Печально, что спустя 4 года после даты документа это все еще проблема.   -  person ReservedDeveloper    schedule 17.12.2018


Ответы (2)


Вы должны проверить обе возможности. Это то, что сработало для меня...

Расшифруйте токен, чтобы получить эмитента. Если эмитент не равен ни одному из https://accounts.google.com или accounts.google.com, вы можете остановиться на этом. Это недопустимый токен.

Если эмитент равен любой из приведенных выше строк Google, передайте то же самое декодированное значение эмитента на этап проверки.

Ниже приведена реализация, которую я написал на JavaScript для некоторого промежуточного программного обеспечения Node.js Express:

function authorize(req, res, next) {
    try {
        var token       = req.headers.authorization;
        var decoded     = jwt.decode(token, { complete: true });
        var keyID       = decoded.header.kid;
        var algorithm   = decoded.header.alg;
        var pem         = getPem(keyID);
        var iss         = decoded.payload.iss;

        if (iss === 'accounts.google.com' || iss === 'https://accounts.google.com') {
            var options = {
                audience: CLIENT_ID,
                issuer: iss,
                algorithms: [algorithm]
            }

            jwt.verify(token, pem, options, function(err) {
                if (err) {
                    res.writeHead(401);
                    res.end();
                } else {
                    next();
                }
            });            

        } else {
            res.writeHead(401);
            res.end();
        }
    } catch (err) {
        res.writeHead(401);
        res.end();
    }
}

Обратите внимание, что эта функция использует модули узлов jsonwebtoken и jwk-to-pem. Я опустил детали функции getPem, которая в конечном итоге преобразует веб-ключ json в формат pem.

person ThisClark    schedule 25.01.2017

Начнем с того, что я определенно согласен с тем, что документация Google — дело темное.

Существует несколько различных способов проверки целостности токена идентификатора на стороне сервера (кстати, это страница, которую вы ищете):

  1. "Вручную" - постоянно скачивать публичные ключи Google, проверять подпись, а затем каждое поле, включая iss; главное преимущество (хоть и маленькое на мой взгляд) я здесь вижу в том, что можно минимизировать количество запросов, отправляемых в гугл).
  2. «Автоматически» — выполните GET на конечной точке Google, чтобы проверить этот токен — самый простой способ: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
  3. Использование клиентской библиотеки Google API - накладные расходы могут быть того не стоит, C# не имеет официальной библиотеки и т. д.

Я предлагаю вам выбрать второй вариант и позволить Google побеспокоиться об алгоритме проверки.

person Alexandru Marculescu    schedule 28.07.2016
comment
И на этой странице в данный момент все еще написано: значение iss в токене идентификатора равно accounts.google.com или https://accounts.google.com. - person Pieter Ennes; 28.07.2016
comment
согласованный; если вы пойдете по этому пути, вам, вероятно, придется проверить обе возможности - person Alexandru Marculescu; 28.07.2016
comment
Спасибо, это не совсем отвечает на мой вопрос, потому что вы обычно говорите о том, как проверить «id_token» Google. Я специально спрашиваю о поле «iss». Звучит так, как будто вы говорите: «Нет, невозможно получить постоянное значение, вам нужно просто проверить обе возможности». - person bjmc; 29.07.2016