Überprüfen Sie das ID-Token eines von AWS Cognito in Java authentifizierten Benutzers

Was du machen willst

Ein mit AWS Amplify Authentication authentifizierter Client (https://aws-amplify.github.io/docs/js/authentication) sendet ein id_token an den Server und überprüft das id_token auf einem von Java implementierten Server.

TL;DR

Implementierung

IdTokenValidator.java

IdTokenValidator.java


package com.exampleawsCognito.jwt;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.interfaces.RSAPublicKey;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

import com.auth0.jwk.GuavaCachedJwkProvider;
import com.auth0.jwk.Jwk;
import com.auth0.jwk.JwkException;
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.interfaces.DecodedJWT;


/**
 *Behandeln Sie ID-Token, die Sie durch die Authentifizierung bei Cognito erhalten haben
 *
 * <p>
 *Quelle, auf die zur Implementierung verwiesen wird
 * https://github.com/awslabs/cognito-proxy-rest-service/blob/master/src/main/kotlin/com/budilov/cognito/services/CognitoService.kt
 * </p>
 *
 * @ThreadSafe
 *
 */
public class IdTokenValidator {
	private static final String AWS_REGION = "ap-northeast-1";
	private static final String AWS_COGNITO_USER_POOL_ID = "my_userpool_id";

	private static JWTVerifier verifier = null;
	private static long verifierExpire = -1;
	private static final long VERIFIER_LIVE_MILISEC = 10 * 60 * 1000; //10 Minuten
	private static final JWT JWT = new JWT();

	/**
	 *Konstrukteur
	 */
	public IdTokenValidator() {
	}

	/**
	 *Überprüfen Sie das ID-Token
	 *
	 * @param idToken ID-Token, das überprüft werden soll
	 * @ID Token-Nutzdaten, wenn die Rückgabeüberprüfung erfolgreich ist
	 *
	 * @löst InvalidTokenException aus Die Authentifizierung ist fehlgeschlagen, da der ID-Token-Wert ungültig ist
	 */
	public DecodedJWT verify(String idToken) throws InvalidTokenException {
		DecodedJWT decodedToken = JWT.decodeJwt(idToken);

		//Stellen Sie sicher, dass es im Cognito-Benutzerpool signiert ist
		String iss = decodedToken.getIssuer();
		if (!jwtTokenIssuer().equals(iss)) {
			throw new InvalidTokenException("Der Aussteller des ID-Tokens ist nicht das Zielsystem. iss=" + iss, idToken);
		}

		//Stellen Sie sicher, dass das ID-Token für "ID" verwendet wird.
		String tokenUse = decodedToken.getClaim("token_use").asString();
		if (!"id".equals(tokenUse)) {
			throw new InvalidTokenException("Der Zweck des ID-Tokens ist nicht ID. Zeichen_use=" + tokenUse, idToken);
		}

		//Überprüfen Sie den Signaturalgorithmus.
		String alg = decodedToken.getAlgorithm();
		if (!"RS256".equals(decodedToken.getAlgorithm())) {
			throw new InvalidTokenException("Der ID-Token-Signaturalgorithmus unterstützt dies nicht. alg=" + alg, idToken);
		}

		//Überprüfen Sie Nutzlast und Signatur.
		DecodedJWT decodedJWT = null;
		if ((decodedJWT = tokenVerify(decodedToken)) == null) {
			throw new InvalidTokenException("ID-Token-Überprüfung fehlgeschlagen.", idToken);
		}

		return decodedJWT;
	}

	/**
	 *Führen Sie die Überprüfung mit der Bibliothek von auth0 durch
	 *
	 * @param kid ID Schlüssel-ID im Token-Header
	 * @Wenn return nicht null ist, wird das decodierte ID-Token angezeigt
	 *
	 * @löst InvalidTokenException aus Validierung fehlgeschlagen
	 */
	private DecodedJWT tokenVerify(DecodedJWT jwToken) throws InvalidTokenException {

		try {
			DecodedJWT verified = getVerifier(jwToken.getKeyId()).verify(jwToken);
			return verified;
		} catch (Exception e) {
			throw new InvalidTokenException(e);
		}
	}

	/**
	 *Holen Sie sich eine Instanz von JWTVerifier.
	 *
	 * <p>
	 *JWTVerifier ist ver.Da es ab 3 threadsicher wurde, wird es wiederverwendet.
	 *Es sollte jedoch regelmäßig aktualisiert werden, da das zum Signieren verwendete RSA-Schlüsselpaar möglicherweise aktualisiert wird.
	 * </p>
	 *
	 * @param kid Schlüssel-ID, die zum Signieren verwendet wird
	 *
	 * @return
	 *
	 * @throws MalformedURLException
	 * @throws JwkException
	 */
	private JWTVerifier getVerifier(String kid) throws MalformedURLException, JwkException {
		if (verifier != null && System.currentTimeMillis() < verifierExpire) {
			//Wenn es innerhalb des Ablaufdatums liegt, verwenden Sie es so wie es ist
			return verifier;
		}
		synchronized (JWT) {
			//Ich habe die Sperre erhalten, überprüfen Sie sie für alle Fälle erneut und erstellen Sie dann die Instanz
			if (verifier != null && System.currentTimeMillis() < verifierExpire) {
				return verifier;
			}

			UrlJwkProvider http = new UrlJwkProvider(new URL(jwksUrl()));
			GuavaCachedJwkProvider provider = new GuavaCachedJwkProvider(http);
			Jwk jwk = provider.get(kid);

			Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
			verifier = JWT.require(algorithm)
					.withIssuer(jwtTokenIssuer())
					.build();

			//Verlängern Sie die Lebensdauer von JWTVerifier
			verifierExpire = System.currentTimeMillis() + VERIFIER_LIVE_MILISEC;

			Calendar expire = GregorianCalendar.getInstance();
			expire.setTimeInMillis(verifierExpire);
			Logger.info("Erstellt eine Instanz von JWTVerifier. Frist"
					+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(expire.getTime()));

		}

		return verifier;

	}

	/**
	 *Holen Sie sich den Aussteller des ID-Tokens
	 *
	 * @return
	 */
	private String jwtTokenIssuer() {
		return String.format("https://cognito-idp.%s.amazonaws.com/%s", AWS_REGION, AWS_COGNITO_USER_POOL_ID);
	}

	/**
	 *JSON-Web-Token(JWT)Holen Sie sich die URL des Sets.
	 *
	 * @return
	 */
	private String jwksUrl() {
		return jwtTokenIssuer() + "/.well-known/jwks.json";
	}

}

InvalidTokenException.java

InvalidTokenException.class


public class InvalidTokenException extends Exception {

    public InvalidTokenException(String message, String idToken) {
        super(message + " token is " + idToken);
    }

    public InvalidTokenException(Throwable e) {
        super(e);
    }
}

Benutzerseite


    try{
        //TODO IdTokenValidator ist threadsicher, machen Sie es also statisch
        DecodedJWT payload = new IdTokenValidator().verify(idToken);
        String cognitoUserName = payload.getClaim("cognito:username").asString();

        //Erforderliche Verarbeitung

    }catch (InvalidTokenException e) {
        Logger.error("Überprüfung des ID-Tokens fehlgeschlagen", e);
        badRequest("Der Wert von IdToken ist ungültig");
    }

Referenz

Recommended Posts

Überprüfen Sie das ID-Token eines von AWS Cognito in Java authentifizierten Benutzers
So erhalten Sie die ID eines Benutzers, der sich in Swift bei Firebase authentifiziert hat
Messen Sie die Größe eines Ordners mit Java
Eine kurze Erklärung der fünf Arten von Java Static
Finden Sie mit Kotlin die Anzahl der Tage in einem Monat
Untersuchen Sie die Liste der in AWS Lambda + Java verfügbaren Schriftarten
Eine Geschichte über das Erreichen der League Of Legends-API mit JAVA
Lassen Sie uns eine TODO-App in Java 5 erstellen. Schalten Sie die Anzeige von TODO um
Stellen Sie die Sensorinformationen von Raspberry Pi in Java grafisch dar und überprüfen Sie sie mit einem Webbrowser
Erhöhen Sie dynamisch die Anzahl der Elemente in einem zweidimensionalen Java-Array (mehrdimensionales Array).
Holen Sie sich das Ergebnis von POST in Java
Holen Sie sich eine Liste der S3-Dateien mit ListObjectsV2Request (AWS SDK für Java)
Die Geschichte, zu vergessen, eine Datei in Java zu schließen und zu scheitern
Die Geschichte eines Game Launcher mit automatischer Ladefunktion [Java]
Lassen Sie uns das Ergebnis der Analyse von Java-Bytecode in einem Klassendiagramm ausdrücken
Die Identität der Schienenparameter [: id]
Beispielprogramm, das den Hashwert einer Datei in Java zurückgibt
Teilen Sie eine Zeichenfolge in Java mit ". (Dot)"
So ermitteln Sie den absoluten Pfad eines in Java ausgeführten Verzeichnisses
Die Geschichte des Schreibens von Java in Emacs
Erstellen wir eine Taschenrechner-App mit Java ~ Erstellen Sie einen Anzeigebereich im Fenster
Bis Sie ein Java-Programm mit dem für Windows lokalen AWS SDK ausführen
Code zum Löschen aller Dateien mit dem angegebenen Präfix in AWS S3 (Java)
Die Geschichte des einfachen String-Vergleichs in Java
[Java] Behandlung von Java Beans in der Methodenkette
Die Geschichte eines gewöhnlichen Othello in Java
Lesen Sie eine Zeichenfolge in einer PDF-Datei mit Java
Erstellen Sie eine CSR mit erweiterten Informationen in Java
Über die Idee anonymer Klassen in Java
Eine Geschichte über das JDK in der Java 11-Ära
Die Geschichte des Lernens von Java in der ersten Programmierung
Spüren Sie den Lauf der Zeit auch in Java
Berechnen Sie die Ähnlichkeitsbewertung von Zeichenketten mit JAVA
Importieren Sie Dateien derselben Hierarchie in Java
Ein Java-Benutzer hat vor über einem Dutzend Jahren versucht, die Funktionen von Java8 (Generics) zu untersuchen.
[Java] Ganzzahlige Informationen von Zeichen in der Textdatei, die mit der Methode read () erfasst wurden
Speichern von Dateien mit der angegebenen Erweiterung unter dem in Java angegebenen Verzeichnis in der Liste
Schreiben Sie einen Test, indem Sie die Geschichte von Mr. Nabeats in der Welt mit Rubin umsetzen
Richten Sie signierte Cookies (für CloudFront) mit benutzerdefinierten Richtlinien mithilfe des AWS SDK für Java ein
[Java] Schneiden Sie einen Teil der Zeichenfolge mit Matcher und regulären Ausdrücken aus
Zusammenfassung der Verwendung des im IE festgelegten Proxy-Sets bei der Verbindung mit Java
Senden Sie einen Job an AWS Batch mit Java (Eclipse)
CI die Architektur von Java / Kotlin-Anwendungen mit ArchUnit
Ein kurzer Überblick über Java, das in Klasse 4 gelernt wurde
Die Geschichte, einen Reverse-Proxy mit ProxyServlet zu erstellen
Überwachen Sie den internen Status von Java-Programmen mit Kubernetes
Überprüfen Sie das Verhalten von Java Intrinsic Locks mit bpftrace
Ein Hinweis zum Initialisieren von Feldern im Java-Lernprogramm
[Java] Holen Sie sich die Datei unabhängig von der Umgebung in das JAR
Implementieren Sie Singleton mit Enum schnell in Java
[Java] Beim Schreiben der Quelle ... Memorandum ①
Ausgabe true mit if (a == 1 && a == 2 && a == 3) in Java (Invisible Identifier)
Ein kurzer Überblick über Java, das in Klasse 3 gelernt wurde
Ein kurzer Überblick über Java, das in Klasse 2 gelernt wurde
Ändern Sie die Speicherqualität von JPEG-Bildern in Java
Eine Übersicht über das native Java-Framework Quarkus von Kubernetes
Die Geschichte von dto, dao-like mit Java, SQLite
Fassen Sie die zusätzlichen Elemente der optionalen Klasse in Java 9 zusammen