using Google.Apis.Auth;
using System;
using System.Threading;
using System.Threading.Tasks;
public class IAPTokenVerification
{
/// <summary>
/// Verifies a signed jwt token and returns its payload.
/// </summary>
/// <param name="signedJwt">The token to verify.</param>
/// <param name="expectedAudience">The audience that the token should be meant for.
/// Validation will fail if that's not the case.</param>
/// <param name="cancellationToken">The cancellation token to propagate cancellation requests.</param>
/// <returns>A task that when completed will have as its result the payload of the verified token.</returns>
/// <exception cref="InvalidJwtException">If verification failed. The message of the exception will contain
/// information as to why the token failed.</exception>
public async Task<JsonWebSignature.Payload> VerifyTokenAsync(
string signedJwt, string expectedAudience, CancellationToken cancellationToken = default)
{
SignedTokenVerificationOptions options = new SignedTokenVerificationOptions
{
// Use clock tolerance to account for possible clock differences
// between the issuer and the verifier.
IssuedAtClockTolerance = TimeSpan.FromMinutes(1),
ExpiryClockTolerance = TimeSpan.FromMinutes(1),
TrustedAudiences = { expectedAudience }
};
return await JsonWebSignature.VerifySignedTokenAsync(signedJwt, options, cancellationToken: cancellationToken);
}
}
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const iapJwt = 'SOME_ID_TOKEN'; // JWT from the "x-goog-iap-jwt-assertion" header
let expectedAudience = null;
if (projectNumber && projectId) {
// Expected Audience for App Engine.
expectedAudience = `/projects/${projectNumber}/apps/${projectId}`;
} else if (projectNumber && backendServiceId) {
// Expected Audience for Compute Engine
expectedAudience = `/projects/${projectNumber}/global/backendServices/${backendServiceId}`;
}
const oAuth2Client = new OAuth2Client();
async function verify() {
// Verify the id_token, and access the claims.
const response = await oAuth2Client.getIapPublicKeys();
const ticket = await oAuth2Client.verifySignedJwtWithCertsAsync(
iapJwt,
response.pubkeys,
expectedAudience,
['https://cloud.google.com/iap']
);
// Print out the info contained in the IAP ID token
console.log(ticket);
}
verify().catch(console.error);
namespace Google\Cloud\Samples\Iap;
# Imports Google auth libraries for IAP validation
use Google\Auth\AccessToken;
/**
* Validate a JWT passed to your App Engine app by Identity-Aware Proxy.
*
* @param string $iapJwt The contents of the X-Goog-IAP-JWT-Assertion header.
* @param string $cloudProjectNumber The project *number* for your Google
* Cloud project. This is returned by 'gcloud projects describe $PROJECT_ID',
* or in the Project Info card in Cloud Console.
* @param string $cloud_project Your Google Cloud Project ID.
*
* @return (user_id, user_email).
*/
function validate_jwt_from_app_engine($iapJwt, $cloudProjectNumber, $cloudProjectId)
{
$expectedAudience = sprintf(
'/projects/%s/apps/%s',
$cloudProjectNumber,
$cloudProjectId
);
return validate_jwt($iapJwt, $expectedAudience);
}
/**
* Validate a JWT passed to your Compute / Container Engine app by Identity-Aware Proxy.
*
* @param string $iapJwt The contents of the X-Goog-IAP-JWT-Assertion header.
* @param string $cloudProjectNumber The project *number* for your Google
* Cloud project. This is returned by 'gcloud projects describe $PROJECT_ID',
* or in the Project Info card in Cloud Console.
* @param string $backendServiceId The ID of the backend service used to access the
* application. See https://cloud.google.com/iap/docs/signed-headers-howto
* for details on how to get this value.
*/
function validate_jwt_from_compute_engine($iapJwt, $cloudProjectNumber, $backendServiceId)
{
$expectedAudience = sprintf(
'/projects/%s/global/backendServices/%s',
$cloudProjectNumber,
$backendServiceId
);
validate_jwt($iapJwt, $expectedAudience);
}
/**
* Validate a JWT passed to your app by Identity-Aware Proxy.
*
* @param string $iapJwt The contents of the X-Goog-IAP-JWT-Assertion header.
* @param string $expectedAudience The expected audience of the JWT with the following formats:
* App Engine: /projects/{PROJECT_NUMBER}/apps/{PROJECT_ID}
* Compute Engine: /projects/{PROJECT_NUMBER}/global/backendServices/{BACKEND_SERVICE_ID}
*/
function validate_jwt($iapJwt, $expectedAudience)
{
// Validate the signature using the IAP cert URL.
$token = new AccessToken();
$jwt = $token->verify($iapJwt, [
'certsLocation' => AccessToken::IAP_CERT_URL
]);
if (!$jwt) {
return print('Failed to validate JWT: Invalid JWT');
}
// Validate token by checking issuer and audience fields.
assert($jwt['iss'] == 'https://cloud.google.com/iap');
assert($jwt['aud'] == $expectedAudience);
print('Printing user identity information from ID token payload:');
printf('sub: %s', $jwt['sub']);
printf('email: %s', $jwt['email']);
}
from google.auth.transport import requests
from google.oauth2 import id_token
def validate_iap_jwt(iap_jwt, expected_audience):
"""Validate an IAP JWT.
Args:
iap_jwt: The contents of the X-Goog-IAP-JWT-Assertion header.
expected_audience: The Signed Header JWT audience. See
https://cloud.google.com/iap/docs/signed-headers-howto
for details on how to get this value.
Returns:
(user_id, user_email, error_str).
"""
try:
decoded_jwt = id_token.verify_token(
iap_jwt, requests.Request(), audience=expected_audience,
certs_url='https://www.gstatic.com/iap/verify/public_key')
return (decoded_jwt['sub'], decoded_jwt['email'], '')
except Exception as e:
return (None, None, '**ERROR: JWT validation error {}**'.format(e))
# iap_jwt = "The contents of the X-Goog-Iap-Jwt-Assertion header"
# project_number = "The project *number* for your Google Cloud project"
# project_id = "Your Google Cloud project ID"
# backend_service_id = "Your Compute Engine backend service ID"
require "googleauth"
audience = nil
if project_number && project_id
# Expected audience for App Engine
audience = "/projects/#{project_number}/apps/#{project_id}"
elsif project_number && backend_service_id
# Expected audience for Compute Engine
audience = "/projects/#{project_number}/global/backendServices/#{backend_service_id}"
end
# The client ID as the target audience for IAP
payload = Google::Auth::IDTokens.verify_iap iap_jwt, aud: audience
puts payload
if audience.nil?
puts "Audience not verified! Supply a project_number and project_id to verify"
end