diff options
author | Vitaly Takmazov | 2021-04-12 19:09:44 +0300 |
---|---|---|
committer | Vitaly Takmazov | 2021-04-12 19:09:44 +0300 |
commit | deb873a5f4ea6429fa5974c0dfe62b9e0544d9fb (patch) | |
tree | 2b26f90cdfcd36b6d50bbcf33f55682b34ad1419 /src/main/java/com/github | |
parent | 8a4691ce820d26943a33095055c372461ae3bad6 (diff) |
Verify Google JWT tokens without Google libraries
Diffstat (limited to 'src/main/java/com/github')
-rw-r--r-- | src/main/java/com/github/scribejava/apis/GoogleTokenVerifier.java | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/main/java/com/github/scribejava/apis/GoogleTokenVerifier.java b/src/main/java/com/github/scribejava/apis/GoogleTokenVerifier.java new file mode 100644 index 00000000..35a9d832 --- /dev/null +++ b/src/main/java/com/github/scribejava/apis/GoogleTokenVerifier.java @@ -0,0 +1,66 @@ +package com.github.scribejava.apis; + +import java.net.MalformedURLException; +import java.net.URL; +import java.text.ParseException; +import java.util.Map; +import java.util.Optional; + +import com.nimbusds.jose.JOSEException; +import com.nimbusds.jose.JWSAlgorithm; +import com.nimbusds.jose.jwk.source.JWKSource; +import com.nimbusds.jose.jwk.source.RemoteJWKSet; +import com.nimbusds.jose.proc.BadJOSEException; +import com.nimbusds.jose.proc.JWSKeySelector; +import com.nimbusds.jose.proc.JWSVerificationKeySelector; +import com.nimbusds.jose.proc.SecurityContext; +import com.nimbusds.jwt.proc.ConfigurableJWTProcessor; +import com.nimbusds.jwt.proc.DefaultJWTClaimsVerifier; +import com.nimbusds.jwt.proc.DefaultJWTProcessor; + +public class GoogleTokenVerifier { + + public static Optional<String> validateToken(String idToken) { + + // Create a JWT processor for the access tokens + ConfigurableJWTProcessor<SecurityContext> jwtProcessor = + new DefaultJWTProcessor<>(); + + // The public RSA keys to validate the signatures will be sourced from the + // OAuth 2.0 server's JWK set, published at a well-known URL. The RemoteJWKSet + // object caches the retrieved keys to speed up subsequent look-ups and can + // also handle key-rollover + JWKSource<SecurityContext> keySource = + null; + try { + keySource = new RemoteJWKSet<>(new URL("https://www.googleapis.com/oauth2/v3/certs")); + } catch (MalformedURLException e) { + return Optional.empty(); + } + + // The expected JWS algorithm of the access tokens (agreed out-of-band) + JWSAlgorithm expectedJWSAlg = JWSAlgorithm.RS256; + + // Configure the JWT processor with a key selector to feed matching public + // RSA keys sourced from the JWK set URL + JWSKeySelector<SecurityContext> keySelector = + new JWSVerificationKeySelector<>(expectedJWSAlg, keySource); + + jwtProcessor.setJWSKeySelector(keySelector); + + // Set the required JWT claims for access tokens issued by the server + jwtProcessor.setJWTClaimsSetVerifier(new DefaultJWTClaimsVerifier<>()); + + // Process the token + Map<String, Object> claimsSet; + try { + claimsSet = jwtProcessor.process(idToken, null).toJSONObject(); + } catch (BadJOSEException | JOSEException | ParseException e) { + return Optional.empty(); + } + + String email = (String)claimsSet.get("email"); + boolean verified = claimsSet.get("email_verified").equals(true); + return verified ? Optional.of(email) : Optional.empty(); + } +} |