Die JWT von Tink ermöglicht die Erstellung und Überprüfung von JSON-Webdateien Tokens (JWT).
Die folgenden Beispiele zeigen, wie JWTs mithilfe eines öffentlichen Schlüsselsatzes im JWK verifiziert werden Format festlegen, einem häufig verwendeten Format für die Freigabe eines öffentlichen Schlüsselsatzes für andere Parteien.
C++
// A utility for creating, signing and verifying JSON Web Tokens (JWT). #include <iostream> #include <memory> #include <ostream> #include <string> #include <utility> #include "absl/flags/flag.h" #include "absl/flags/parse.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" #include "tink/config/global_registry.h" #include "util/util.h" #include "tink/jwt/jwk_set_converter.h" #include "tink/jwt/jwt_public_key_verify.h" #include "tink/jwt/jwt_signature_config.h" #include "tink/jwt/jwt_validator.h" #include "tink/keyset_handle.h" #include "tink/util/status.h" ABSL_FLAG(std::string, jwk_set_filename, "", "Path to the JWK set file"); ABSL_FLAG(std::string, audience, "", "Expected audience in the token"); ABSL_FLAG(std::string, token_filename, "", "Path to the token file"); namespace { using ::crypto::tink::JwkSetToPublicKeysetHandle; using ::crypto::tink::JwtPublicKeyVerify; using ::crypto::tink::JwtValidator; using ::crypto::tink::KeysetHandle; using ::crypto::tink::util::Status; using ::crypto::tink::util::StatusOr; void ValidateParams() { // ... } } // namespace namespace tink_cc_examples { // JWT verify example CLI implementation. Status JwtVerify(const std::string& jwk_set_filename, absl::string_view audience, const std::string& token_filename) { Status result = crypto::tink::JwtSignatureRegister(); if (!result.ok()) return result; // Read the JWK set from file and convert it. StatusOr<std::string> jwk_set = ReadFile(jwk_set_filename); if (!jwk_set.ok()) return jwk_set.status(); StatusOr<std::unique_ptr<KeysetHandle>> keyset_handle = JwkSetToPublicKeysetHandle(*jwk_set); // Read the token. StatusOr<std::string> token = ReadFile(token_filename); if (!token.ok()) return token.status(); StatusOr<JwtValidator> validator = crypto::tink::JwtValidatorBuilder().ExpectAudience(audience).Build(); if (!validator.ok()) return validator.status(); StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verifier = (*keyset_handle) ->GetPrimitive<crypto::tink::JwtPublicKeyVerify>( crypto::tink::ConfigGlobalRegistry()); if (!jwt_verifier.ok()) return jwt_verifier.status(); return (*jwt_verifier)->VerifyAndDecode(*token, *validator).status(); } } // namespace tink_cc_examples int main(int argc, char** argv) { absl::ParseCommandLine(argc, argv); ValidateParams(); std::string jwk_set_filename = absl::GetFlag(FLAGS_jwk_set_filename); std::string audience = absl::GetFlag(FLAGS_audience); std::string token_filename = absl::GetFlag(FLAGS_token_filename); std::clog << "Using keyset in " << jwk_set_filename << " to "; std::clog << " verify a token with expected audience '" << audience << '\n'; CHECK_OK( tink_cc_examples::JwtVerify(jwk_set_filename, audience, token_filename)); return 0; }
Go
func Example_verifyWithJWKS() { // A signed token with the subject 'example subject', audience 'example audience'. // and expiration on 2023-03-23. token := `eyJhbGciOiJFUzI1NiIsICJraWQiOiJaOXBRRXcifQ.eyJhdWQiOiJleGFtcGxlIGF1ZGllbmNlIiwgImV4cCI6MTY3OTUzMzIwMCwgInN1YiI6ImV4YW1wbGUgc3ViamVjdCJ9.ZvI0T84fJ1aouiB7n62kHOmbm0Hpfiz0JtYs15XVDT8KyoVYZ8hu_DGJUN47BqZIbuOI-rdu9TxJvutj8uF3Ow` // A public keyset in the JWK set format. publicJWKset := `{ "keys":[ { "alg":"ES256", "crv":"P-256", "key_ops":["verify"], "kid":"Z9pQEw", "kty":"EC", "use":"sig", "x":"bjQTXrTcw_1HKiiZm2Hqv41w7Vd44M9koyY_-VsP-SA", "y":"XqAzBfS0uQQwoemIKhNw4x8FsJxChCN1qT3_IsxMda0" } ] }` // Create a keyset handle from publicJWKset. publicKeysetHandle, err := jwt.JWKSetToPublicKeysetHandle([]byte(publicJWKset)) if err != nil { log.Fatal(err) } // Retrieve the Verifier primitive from publicKeysetHandle. verifier, err := jwt.NewVerifier(publicKeysetHandle) if err != nil { log.Fatal(err) } // Verify the signed token. For this example, we use a fixed date. Usually, you would // either not set FixedNow, or set it to the current time. audience := "example audience" validator, err := jwt.NewValidator(&jwt.ValidatorOpts{ ExpectedAudience: &audience, FixedNow: time.Date(2023, 3, 23, 0, 0, 0, 0, time.UTC), }) if err != nil { log.Fatal(err) } verifiedJWT, err := verifier.VerifyAndDecode(token, validator) if err != nil { log.Fatal(err) } // Extract subject claim from the token. if !verifiedJWT.HasSubject() { log.Fatal(err) } extractedSubject, err := verifiedJWT.Subject() if err != nil { log.Fatal(err) } fmt.Println(extractedSubject) // Output: example subject }
Java
package jwt; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.crypto.tink.KeysetHandle; import com.google.crypto.tink.jwt.JwkSetConverter; import com.google.crypto.tink.jwt.JwtPublicKeyVerify; import com.google.crypto.tink.jwt.JwtSignatureConfig; import com.google.crypto.tink.jwt.JwtValidator; import com.google.crypto.tink.jwt.VerifiedJwt; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.List; /** * A command-line utility for verifying JSON Web Tokens (JWTs). * * <p>It requires the following arguments: * * <ul> * <li>public-jwkset-file: Name of the input file containing the public keyset in JWK set format. * <li>audience: The audience claim to be used in the token * <li>token-file: name of the input file containing the signed JWT. */ public final class JwtVerify { public static void main(String[] args) throws Exception { if (args.length != 3) { System.err.printf("Expected 3 parameters, got %d\n", args.length); System.err.println( "Usage: java JwtVerify public-jwk-set-file audience token-file"); System.exit(1); } Path publicJwkSetFile = Paths.get(args[0]); String audience = args[1]; Path tokenFile = Paths.get(args[2]); // Register all JWT signature key types with the Tink runtime. JwtSignatureConfig.register(); // Read the public keyset in JWK set format into a KeysetHandle. KeysetHandle publicKeysetHandle = JwkSetConverter.toPublicKeysetHandle( new String(Files.readAllBytes(publicJwkSetFile), UTF_8)); List<String> lines = Files.readAllLines(tokenFile, UTF_8); if (lines.size() != 1) { System.err.printf("The signature file should contain only one line, got %d", lines.size()); System.exit(1); } String signedToken = lines.get(0).trim(); // Get the primitive. JwtPublicKeyVerify verifier = publicKeysetHandle.getPrimitive(JwtPublicKeyVerify.class); // Use the primitive to verify a token. JwtValidator validator = JwtValidator.newBuilder().expectAudience(audience).build(); VerifiedJwt verifiedJwt = verifier.verifyAndDecode(signedToken, validator); long seconds = ChronoUnit.SECONDS.between(Instant.now(), verifiedJwt.getExpiration()); System.out.println("Token is valid and expires in " + seconds + " seconds."); } private JwtVerify() {} }
Python
"""A utility for verifying Json Web Tokens (JWT).""" import datetime from absl import app from absl import flags from absl import logging import tink from tink import jwt FLAGS = flags.FLAGS _PUBLIC_JWK_SET_PATH = flags.DEFINE_string( 'public_jwk_set_path', None, 'Path to public keyset in JWK set format.') _AUDIENCE = flags.DEFINE_string('audience', None, 'Audience to be used in the token') _TOKEN_PATH = flags.DEFINE_string('token_path', None, 'Path to the signature file.') def main(argv): del argv # Unused. # Initialise Tink jwt.register_jwt_signature() with open(_PUBLIC_JWK_SET_PATH.value, 'rt') as public_jwk_set_file: try: text = public_jwk_set_file.read() keyset_handle = jwt.jwk_set_to_public_keyset_handle(text) except tink.TinkError as e: logging.exception('Error reading public JWK set: %s', e) return 1 now = datetime.datetime.now(tz=datetime.timezone.utc) try: jwt_verify = keyset_handle.primitive(jwt.JwtPublicKeyVerify) except tink.TinkError as e: logging.exception('Error creating JwtPublicKeyVerify: %s', e) return 1 # Verify token with open(_TOKEN_PATH.value, 'rt') as token_file: token = token_file.read() validator = jwt.new_validator(expected_audience=_AUDIENCE.value) try: verified_jwt = jwt_verify.verify_and_decode(token, validator) expires_in = verified_jwt.expiration() - now logging.info('Token is valid and expires in %s seconds', expires_in.seconds) return 0 except tink.TinkError as e: logging.info('JWT verification failed: %s', e) return 1 if __name__ == '__main__': flags.mark_flags_as_required(['audience', 'token_path']) app.run(main)