Если вы используете вход в Google с приложением или сайтом, который взаимодействует с внутренним сервером, вам может потребоваться идентифицировать текущего пользователя, вошедшего в систему на сервере. Чтобы сделать это безопасно, после успешного входа пользователя в систему отправьте токен идентификатора пользователя на свой сервер по протоколу HTTPS. Затем на сервере проверьте целостность токена идентификатора и используйте информацию пользователя, содержащуюся в токене, для установления сеанса или создания новой учетной записи.
Отправьте идентификационный токен на свой сервер
После успешного входа пользователя в систему получите токен идентификатора пользователя:
function onSignIn(googleUser) { var id_token = googleUser.getAuthResponse().id_token; ... }
Затем отправьте токен идентификатора на свой сервер с помощью запроса HTTPS POST:
var xhr = new XMLHttpRequest(); xhr.open('POST', 'https://yourbackend.example.com/tokensignin'); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onload = function() { console.log('Signed in as: ' + xhr.responseText); }; xhr.send('idtoken=' + id_token);
Проверьте целостность идентификационного токена
После получения токена идентификатора с помощью HTTPS POST необходимо проверить целостность токена.
To verify that the token is valid, ensure that the following criteria are satisfied:
- The ID token is properly signed by Google. Use Google's public keys
(available in
JWK or
PEM format)
to verify the token's signature. These keys are regularly rotated; examine
the
Cache-Control
header in the response to determine when you should retrieve them again. - The value of
aud
in the ID token is equal to one of your app's client IDs. This check is necessary to prevent ID tokens issued to a malicious app being used to access data about the same user on your app's backend server. - The value of
iss
in the ID token is equal toaccounts.google.com
orhttps://accounts.google.com
. - The expiry time (
exp
) of the ID token has not passed. - If you want to restrict access to only members of your G Suite domain,
verify that the ID token has an
hd
claim that matches your G Suite domain name.
Rather than writing your own code to perform these verification steps, we strongly
recommend using a Google API client library for your platform, or a general-purpose
JWT library. For development and debugging, you can call our tokeninfo
validation endpoint.
Использование клиентской библиотеки Google API
Использование одной из клиентских библиотек Google API (например, Java , Node.js , PHP , Python ) — рекомендуемый способ проверки токенов Google ID в производственной среде.
Чтобы проверить токен идентификатора в Java, используйте объект GoogleIdTokenVerifier . Например:
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; ... GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) // Specify the CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3)) .build(); // (Receive idTokenString by HTTPS POST) GoogleIdToken idToken = verifier.verify(idTokenString); if (idToken != null) { Payload payload = idToken.getPayload(); // Print user identifier String userId = payload.getSubject(); System.out.println("User ID: " + userId); // Get profile information from payload String email = payload.getEmail(); boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); String name = (String) payload.get("name"); String pictureUrl = (String) payload.get("picture"); String locale = (String) payload.get("locale"); String familyName = (String) payload.get("family_name"); String givenName = (String) payload.get("given_name"); // Use or store profile information // ... } else { System.out.println("Invalid ID token."); }
Метод GoogleIdTokenVerifier.verify()
проверяет подпись JWT, утверждение aud
, утверждение iss
и утверждение exp
.
Если вы хотите ограничить доступ только для членов вашего домена G Suite, также проверьте утверждение hd
, проверив имя домена, возвращаемое методом Payload.getHostedDomain()
.
Чтобы проверить токен идентификатора в Node.js, используйте библиотеку Google Auth для Node.js. Установите библиотеку:
npm install google-auth-library --saveЗатем вызовите функциюverifyIdToken
verifyIdToken()
. Например: const {OAuth2Client} = require('google-auth-library'); const client = new OAuth2Client(); async function verify() { const ticket = await client.verifyIdToken({ idToken: token, audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend // Or, if multiple clients access the backend: //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3] }); const payload = ticket.getPayload(); const userid = payload['sub']; // If request specified a G Suite domain: // const domain = payload['hd']; } verify().catch(console.error);
verifyIdToken
проверяет подпись JWT, утверждение aud
, утверждение exp
и утверждение iss
.
Если вы хотите ограничить доступ только для членов вашего домена G Suite, также убедитесь, что утверждение hd
соответствует вашему доменному имени G Suite.
Чтобы проверить токен идентификатора в PHP, используйте клиентскую библиотеку Google API для PHP . Установите библиотеку (например, с помощью Composer):
composer require google/apiclientЗатем вызовите функциюverifyIdToken
verifyIdToken()
. Например: require_once 'vendor/autoload.php'; // Get $id_token via HTTPS POST. $client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken($id_token); if ($payload) { $userid = $payload['sub']; // If request specified a G Suite domain: //$domain = $payload['hd']; } else { // Invalid ID token }
verifyIdToken
проверяет подпись JWT, утверждение aud
, утверждение exp
и утверждение iss
.
Если вы хотите ограничить доступ только для членов вашего домена G Suite, также убедитесь, что утверждение hd
соответствует вашему доменному имени G Suite.
Чтобы проверить токен идентификатора в Python, используйте функциюverify_oauth2_token . Например:
from google.oauth2 import id_token from google.auth.transport import requests # (Receive token by HTTPS POST) # ... try: # Specify the CLIENT_ID of the app that accesses the backend: idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]: # raise ValueError('Could not verify audience.') # If auth request is from a G Suite domain: # if idinfo['hd'] != GSUITE_DOMAIN_NAME: # raise ValueError('Wrong hosted domain.') # ID token is valid. Get the user's Google Account ID from the decoded token. userid = idinfo['sub'] except ValueError: # Invalid token pass
verify_oauth2_token
проверяет подпись JWT, утверждение aud
и утверждение exp
. Вы также должны проверить утверждение hd
(если применимо), проверив объект, который verify_oauth2_token
. Если несколько клиентов обращаются к внутреннему серверу, также вручную проверьте утверждение aud
.
Вызов конечной точки tokeninfo
Простой способ проверить подпись токена идентификатора для отладки — использовать конечную точку tokeninfo
. Вызов этой конечной точки включает в себя дополнительный сетевой запрос, который выполняет большую часть проверки за вас, пока вы тестируете правильную проверку и извлечение полезной нагрузки в своем собственном коде. Он не подходит для использования в рабочем коде, поскольку запросы могут регулироваться или иным образом подвергаться периодическим ошибкам.
Чтобы проверить токен идентификатора с помощью конечной точки tokeninfo
, выполните HTTPS-запрос POST или GET к конечной точке и передайте свой токен идентификатора в параметре id_token
. Например, чтобы проверить токен «XYZ123», выполните следующий запрос GET:
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
Если токен правильно подписан и утверждения iss
и exp
имеют ожидаемые значения, вы получите ответ HTTP 200, тело которого содержит утверждения токена идентификатора в формате JSON. Вот пример ответа:
{ // These six fields are included in all Google ID Tokens. "iss": "https://accounts.google.com", "sub": "110169484474386276334", "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "iat": "1433978353", "exp": "1433981953", // These seven fields are only included when the user has granted the "profile" and // "email" OAuth scopes to the application. "email": "testuser@gmail.com", "email_verified": "true", "name" : "Test User", "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg", "given_name": "Test", "family_name": "User", "locale": "en" }
Если вы являетесь клиентом G Suite, вас также может заинтересовать утверждение hd
, которое указывает размещенный домен пользователя. Это можно использовать для ограничения доступа к ресурсу только членам определенных доменов. Отсутствие этого утверждения указывает на то, что пользователь не принадлежит к домену, размещенному в G Suite.
Создать учетную запись или сеанс
После того как вы проверили токен, проверьте, есть ли пользователь уже в вашей базе данных пользователей. Если да, установите для пользователя сеанс с аутентификацией. Если пользователя еще нет в вашей базе данных пользователей, создайте новую запись пользователя на основе информации в полезных данных токена идентификатора и установите сеанс для пользователя. Вы можете запросить у пользователя любую дополнительную информацию профиля, которая вам понадобится, когда вы обнаружите вновь созданного пользователя в вашем приложении.
Защита учетных записей ваших пользователей с помощью перекрестной защиты учетных записей
Когда вы полагаетесь на Google для входа в систему, вы автоматически получаете доступ ко всем функциям безопасности и инфраструктуре, созданной Google для защиты данных пользователя. Однако в том маловероятном случае, если учетная запись Google пользователя будет взломана или произойдет какое-либо другое существенное событие безопасности, ваше приложение также может быть уязвимо для атаки. Чтобы лучше защитить свои учетные записи от любых серьезных событий безопасности, используйте защиту перекрестных учетных записей для получения предупреждений безопасности от Google. Когда вы получаете эти события, вы получаете представление о важных изменениях в безопасности учетной записи Google пользователя, а затем можете принять меры в своей службе для защиты своих учетных записей.