1

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

One page говорит, «ISS: всегда accounts.google.com», но another page говорит: «Значение ISS в ID маркера равно 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.

Для дальнейшего мутить воду, the OpenIDConnect specification itself содержит примечание, что:

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

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

ответ

0

Для начала я определенно соглашусь с тем, что документация Google является темным бизнесом.

Там есть несколько различных способов, в которых можно проверить целостность ID маркера на стороне сервера (кстати this это страница, которую вы ищете):

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

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

+0

И на этой странице в настоящий момент говорится: «Значение iss в токене ID равно« accounts.google.com »или' https: // accounts.google.com'. " –

+0

согласовано; если вы спуститесь по этому пути, вам, вероятно, придется проверять обе возможности. –

+1

Спасибо, это не совсем ответит на мой вопрос, потому что вы вообще говорите, как проверить идентификатор Google id_token. Я специально спрашиваю о поле «iss». Похоже, вы говорите: «Нет, нет никакого способа получить постоянную ценность, вам нужно просто проверить обе возможности». – bjmc

0

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

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

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

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

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.