紀錄驗證 Google 第三方登入傳入的RSA 256 JWT token 的程式碼
, 其官方網站有公開 Public key 的 JWK,
JWK網址是:https://www.googleapis.com/oauth2/v3/certs
有兩種驗證的方法:
首先是第一種,
1. 使用第三方 JWK 驗證相關的 Library 來做驗證 (不限只能驗證 google 的 JWT)。
範例如下:
Maven 的 pom.xml :
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.18.2</version> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>jwks-rsa</artifactId> <version>0.20.0</version> </dependency>
可能會需要 javax.xml.bind 這個 lib,因為 jdk 8 以上沒有 jaxb 模塊,詳見: 真正解决方案:java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
<!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api --> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency>
Java:
package test; import java.io.IOException; import java.net.URL; import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.interfaces.RSAPublicKey; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import com.auth0.jwk.Jwk; import com.auth0.jwk.JwkException; import com.auth0.jwk.JwkProvider; import com.auth0.jwk.UrlJwkProvider; import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; import net.sf.json.JSONObject; public class JWTTest { public static void main(String[] args) throws IOException, GeneralSecurityException, JwkException { String token = "someGoogleJwtToken"; verifyToken(token); } public static verifyToken(String token) { try { DecodedJWT jwt = JWT.decode(token); JwkProvider provider = new UrlJwkProvider(new URL("https://www.googleapis.com/oauth2/v3/certs")); RSAPublicKey publicKey = (RSAPublicKey) provider.get(jwt.getKeyId()).getPublicKey(); Algorithm algorithm = Algorithm.RSA256(publicKey, null); JWTVerifier verifier = JWT.require(algorithm) // more validations if needed .build(); jwt = verifier.verify(token); System.out.println("User Id: " + jwt.getSubject()); System.out.println("Email: " + jwt.getClaim("email").asString()); } catch (Exception e) { System.out.println("Exception in verifying " + e.toString()); } } }
再來是第二種,
2. 使用 Google 提供的 LIbrary 來做驗證。
範例如下:
Maven 的 pom.xml :
<dependency> <groupId>com.google.api-client</groupId> <artifactId>google-api-client</artifactId> <version>1.32.1</version> </dependency>
Java:
package test; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.Collections; import com.auth0.jwk.JwkException; 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; import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; import com.google.api.client.json.gson.GsonFactory; public class GoogleJWTTest2 { public static void main(String[] args) throws IOException, GeneralSecurityException, JwkException { String token = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImZjYmQ3ZjQ4MWE4MjVkMTEzZTBkMDNkZDk0ZTYwYjY5ZmYxNjY1YTIiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2NTE4MzA3OTQsImF1ZCI6Ijk2MjE1NTMyNDMyMy1vY3U5MzNkazFiYzY0dGhkM3JrdnVsaXI5MHVya3Nuby5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjEwMjA1NTY1MzA0MDM0ODc0MzExMyIsImVtYWlsIjoiaHVnb2dvNzY0NkBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiOTYyMTU1MzI0MzIzLW9jdTkzM2RrMWJjNjR0aGQzcmt2dWxpcjkwdXJrc25vLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IumDreeAmumahiIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHaExOWHdxT2l2cXAyOHdRY3lNZ3FGZERUU0dyYW1sSDQwTDRTejEzZz1zOTYtYyIsImdpdmVuX25hbWUiOiLngJrpmoYiLCJmYW1pbHlfbmFtZSI6IumDrSIsImlhdCI6MTY1MTgzMTA5NCwiZXhwIjoxNjUxODM0Njk0LCJqdGkiOiJmZDFlY2VmMThiNzAyZDIyNzQwNjRjZjdmMzMwOTExZDBlYzQ4NDI0In0.OFc3-NIiSsChOJWgF_SJZ9yWhSpAhY95PSllh7gSqS8YYiBJD6DIZCvbHnL2SLU69lv2kntoR-hG1aQU07ppgGN5xuqJAagvKJ8KSSkxJxSR5qOLFNMBYPghp0zgFybNEAQDTbj3E5zRlemX7w9irEMqkMliRAMDYE3aUkcOrho9X2vd9wJDrkwKmMaLfXa71MVPwIYpsOrg2Gq82nHLw24eM47VRTp3m1sqXdKz9WHgfW2_2y9GB0qn3E8Fo99wBgegRyAlz6UvbTzDNQOUdrvuSALXcrOZzog5rrfW0MinxdVfRbSNRKL0VGMJWzuGefxNqEV-Fu0CTPIqliXf1A"; verifyToken(token); } public static boolean verifyToken(String token) { try { GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder( GoogleNetHttpTransport.newTrustedTransport(), new GsonFactory()) // Specify the CLIENT_ID of the app that accesses the backend: // .setAudience(Collections.singletonList( // "962155324323-ocu933dk1bc64thd3rkvulir90urksno.apps.googleusercontent.com")) // 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(token); 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"); System.out.println(email); // Use or store profile information // ... } else { System.out.println("Invalid ID token."); } return true; } catch (Exception e) { System.out.println("Exception in verifying " + e.toString()); return false; } } }