使用签名的 Identity-Aware Proxy (IAP) 标头帮助保护应用安全。
包含此代码示例的文档页面
如需查看上下文中使用的代码示例,请参阅以下文档:
代码示例
C#
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);
}
}
Go
import (
"context"
"fmt"
"io"
"google.golang.org/api/idtoken"
)
// validateJWTFromAppEngine validates a JWT found in the
// "x-goog-iap-jwt-assertion" header.
func validateJWTFromAppEngine(w io.Writer, iapJWT, projectNumber, projectID string) error {
// iapJWT := "YmFzZQ==.ZW5jb2RlZA==.and0" // req.Header.Get("X-Goog-IAP-JWT-Assertion")
// projectNumber := "123456789"
// projectID := "your-project-id"
ctx := context.Background()
aud := fmt.Sprintf("/projects/%s/apps/%s", projectNumber, projectID)
payload, err := idtoken.Validate(ctx, iapJWT, aud)
if err != nil {
return fmt.Errorf("idtoken.Validate: %v", err)
}
// payload contains the JWT claims for further inspection or validation
fmt.Fprintf(w, "payload: %v", payload)
return nil
}
// validateJWTFromComputeEngine validates a JWT found in the
// "x-goog-iap-jwt-assertion" header.
func validateJWTFromComputeEngine(w io.Writer, iapJWT, projectNumber, backendServiceID string) error {
// iapJWT := "YmFzZQ==.ZW5jb2RlZA==.and0" // req.Header.Get("X-Goog-IAP-JWT-Assertion")
// projectNumber := "123456789"
// backendServiceID := "backend-service-id"
ctx := context.Background()
aud := fmt.Sprintf("/projects/%s/global/backendServices/%s", projectNumber, backendServiceID)
payload, err := idtoken.Validate(ctx, iapJWT, aud)
if err != nil {
return fmt.Errorf("idtoken.Validate: %v", err)
}
// payload contains the JWT claims for further inspection or validation
fmt.Fprintf(w, "payload: %v", payload)
return nil
}
Java
import com.google.api.client.http.HttpRequest;
import com.google.api.client.json.webtoken.JsonWebToken;
import com.google.auth.oauth2.TokenVerifier;
/** Verify IAP authorization JWT token in incoming request. */
public class VerifyIapRequestHeader {
private static final String IAP_ISSUER_URL = "https://cloud.google.com/iap";
// Verify jwt tokens addressed to IAP protected resources on App Engine.
// The project *number* for your Google Cloud project via 'gcloud projects describe $PROJECT_ID'
// The project *number* can also be retrieved from the Project Info card in Cloud Console.
// projectId is The project *ID* for your Google Cloud Project.
boolean verifyJwtForAppEngine(HttpRequest request, long projectNumber, String projectId)
throws Exception {
// Check for iap jwt header in incoming request
String jwt = request.getHeaders().getFirstHeaderStringValue("x-goog-iap-jwt-assertion");
if (jwt == null) {
return false;
}
return verifyJwt(
jwt,
String.format("/projects/%s/apps/%s", Long.toUnsignedString(projectNumber), projectId));
}
boolean verifyJwtForComputeEngine(
HttpRequest request, long projectNumber, long backendServiceId) throws Exception {
// Check for iap jwt header in incoming request
String jwtToken = request.getHeaders()
.getFirstHeaderStringValue("x-goog-iap-jwt-assertion");
if (jwtToken == null) {
return false;
}
return verifyJwt(
jwtToken,
String.format(
"/projects/%s/global/backendServices/%s",
Long.toUnsignedString(projectNumber), Long.toUnsignedString(backendServiceId)));
}
private boolean verifyJwt(String jwtToken, String expectedAudience) {
TokenVerifier tokenVerifier = TokenVerifier.newBuilder()
.setAudience(expectedAudience)
.setIssuer(IAP_ISSUER_URL)
.build();
try {
JsonWebToken jsonWebToken = tokenVerifier.verify(jwtToken);
// Verify that the token contain subject and email claims
JsonWebToken.Payload payload = jsonWebToken.getPayload();
return payload.getSubject() != null && payload.get("email") != null;
} catch (TokenVerifier.VerificationException e) {
System.out.println(e.getMessage());
return false;
}
}
}
PHP
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 $iap_jwt The contents of the X-Goog-IAP-JWT-Assertion header.
* @param string $cloud_project_number 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($iap_jwt, $cloud_project_number, $cloud_project_id)
{
$expected_audience = sprintf(
'/projects/%s/apps/%s',
$cloud_project_number,
$cloud_project_id
);
return validate_jwt($iap_jwt, $expected_audience);
}
/**
* Validate a JWT passed to your Compute / Container Engine app by Identity-Aware Proxy.
*
* @param string $iap_jwt The contents of the X-Goog-IAP-JWT-Assertion header.
* @param string $cloud_project_number 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 $backend_service_id 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.
*
* @return (user_id, user_email).
*/
function validate_jwt_from_compute_engine($iap_jwt, $cloud_project_number, $backend_service_id)
{
$expected_audience = sprintf(
'/projects/%s/global/backendServices/%s',
$cloud_project_number,
$backend_service_id
);
return validate_jwt($iap_jwt, $expected_audience);
}
function validate_jwt($iap_jwt, $expected_audience)
{
// Validate the signature using the IAP cert URL.
$token = new AccessToken();
$jwt = $token->verify($iap_jwt, [
'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'] == $expected_audience);
// Return the user identity (subject and user email) if JWT verification is successful.
return array('sub' => $jwt['sub'], 'email' => $jwt['email']);
}
Python
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))
Ruby
# 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