|
18 | 18 | // [START iap_validate_jwt]
|
19 | 19 |
|
20 | 20 | import com.google.api.client.http.HttpRequest;
|
21 |
| -import com.google.common.base.Preconditions; |
22 |
| -import com.nimbusds.jose.JWSHeader; |
23 |
| -import com.nimbusds.jose.JWSVerifier; |
24 |
| -import com.nimbusds.jose.crypto.ECDSAVerifier; |
25 |
| -import com.nimbusds.jose.jwk.ECKey; |
26 |
| -import com.nimbusds.jose.jwk.JWK; |
27 |
| -import com.nimbusds.jose.jwk.JWKSet; |
28 |
| -import com.nimbusds.jwt.JWTClaimsSet; |
29 |
| -import com.nimbusds.jwt.SignedJWT; |
30 |
| -import java.net.URL; |
31 |
| -import java.security.interfaces.ECPublicKey; |
32 |
| -import java.time.Clock; |
33 |
| -import java.time.Instant; |
34 |
| -import java.util.Date; |
35 |
| -import java.util.HashMap; |
36 |
| -import java.util.Map; |
| 21 | +import com.google.api.client.json.webtoken.JsonWebToken; |
| 22 | +import com.google.auth.oauth2.TokenVerifier; |
37 | 23 |
|
38 | 24 | /** Verify IAP authorization JWT token in incoming request. */
|
39 | 25 | public class VerifyIapRequestHeader {
|
40 | 26 |
|
41 |
| - private static final String PUBLIC_KEY_VERIFICATION_URL = |
42 |
| - "https://www.gstatic.com/iap/verify/public_key-jwk"; |
43 |
| - |
44 | 27 | private static final String IAP_ISSUER_URL = "https://cloud.google.com/iap";
|
45 | 28 |
|
46 |
| - // using a simple cache with no eviction for this sample |
47 |
| - private final Map<String, JWK> keyCache = new HashMap<>(); |
48 |
| - |
49 |
| - private static Clock clock = Clock.systemUTC(); |
50 |
| - |
51 |
| - private ECPublicKey getKey(String kid, String alg) throws Exception { |
52 |
| - JWK jwk = keyCache.get(kid); |
53 |
| - if (jwk == null) { |
54 |
| - // update cache loading jwk public key data from url |
55 |
| - JWKSet jwkSet = JWKSet.load(new URL(PUBLIC_KEY_VERIFICATION_URL)); |
56 |
| - for (JWK key : jwkSet.getKeys()) { |
57 |
| - keyCache.put(key.getKeyID(), key); |
58 |
| - } |
59 |
| - jwk = keyCache.get(kid); |
60 |
| - } |
61 |
| - // confirm that algorithm matches |
62 |
| - if (jwk != null && jwk.getAlgorithm().getName().equals(alg)) { |
63 |
| - return ECKey.parse(jwk.toJSONString()).toECPublicKey(); |
64 |
| - } |
65 |
| - return null; |
66 |
| - } |
67 |
| - |
68 | 29 | // Verify jwt tokens addressed to IAP protected resources on App Engine.
|
69 | 30 | // The project *number* for your Google Cloud project via 'gcloud projects describe $PROJECT_ID'
|
70 | 31 | // The project *number* can also be retrieved from the Project Info card in Cloud Console.
|
@@ -96,38 +57,21 @@ boolean verifyJwtForComputeEngine(
|
96 | 57 | Long.toUnsignedString(projectNumber), Long.toUnsignedString(backendServiceId)));
|
97 | 58 | }
|
98 | 59 |
|
99 |
| - private boolean verifyJwt(String jwtToken, String expectedAudience) throws Exception { |
100 |
| - |
101 |
| - // parse signed token into header / claims |
102 |
| - SignedJWT signedJwt = SignedJWT.parse(jwtToken); |
103 |
| - JWSHeader jwsHeader = signedJwt.getHeader(); |
104 |
| - |
105 |
| - // header must have algorithm("alg") and "kid" |
106 |
| - Preconditions.checkNotNull(jwsHeader.getAlgorithm()); |
107 |
| - Preconditions.checkNotNull(jwsHeader.getKeyID()); |
108 |
| - |
109 |
| - JWTClaimsSet claims = signedJwt.getJWTClaimsSet(); |
110 |
| - |
111 |
| - // claims must have audience, issuer |
112 |
| - Preconditions.checkArgument(claims.getAudience().contains(expectedAudience)); |
113 |
| - Preconditions.checkArgument(claims.getIssuer().equals(IAP_ISSUER_URL)); |
114 |
| - |
115 |
| - // claim must have issued at time in the past |
116 |
| - Date currentTime = Date.from(Instant.now(clock)); |
117 |
| - Preconditions.checkArgument(claims.getIssueTime().before(currentTime)); |
118 |
| - // claim must have expiration time in the future |
119 |
| - Preconditions.checkArgument(claims.getExpirationTime().after(currentTime)); |
120 |
| - |
121 |
| - // must have subject, email |
122 |
| - Preconditions.checkNotNull(claims.getSubject()); |
123 |
| - Preconditions.checkNotNull(claims.getClaim("email")); |
124 |
| - |
125 |
| - // verify using public key : lookup with key id, algorithm name provided |
126 |
| - ECPublicKey publicKey = getKey(jwsHeader.getKeyID(), jwsHeader.getAlgorithm().getName()); |
127 |
| - |
128 |
| - Preconditions.checkNotNull(publicKey); |
129 |
| - JWSVerifier jwsVerifier = new ECDSAVerifier(publicKey); |
130 |
| - return signedJwt.verify(jwsVerifier); |
| 60 | + private boolean verifyJwt(String jwtToken, String expectedAudience) { |
| 61 | + TokenVerifier tokenVerifier = TokenVerifier.newBuilder() |
| 62 | + .setAudience(expectedAudience) |
| 63 | + .setIssuer(IAP_ISSUER_URL) |
| 64 | + .build(); |
| 65 | + try { |
| 66 | + JsonWebToken jsonWebToken = tokenVerifier.verify(jwtToken); |
| 67 | + |
| 68 | + // Verify that the token contain subject and email claims |
| 69 | + JsonWebToken.Payload payload = jsonWebToken.getPayload(); |
| 70 | + return payload.getSubject() != null && payload.get("email") != null; |
| 71 | + } catch (TokenVerifier.VerificationException e) { |
| 72 | + System.out.println(e.getMessage()); |
| 73 | + return false; |
| 74 | + } |
131 | 75 | }
|
132 | 76 | }
|
133 | 77 | // [END iap_validate_jwt]
|
0 commit comments