1 // Copyright 2021 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink.testing; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static java.nio.charset.StandardCharsets.UTF_8; 21 import static java.util.concurrent.TimeUnit.SECONDS; 22 import static org.junit.Assert.assertThrows; 23 24 import com.google.crypto.tink.KeyTemplates; 25 import com.google.crypto.tink.internal.KeyTemplateProtoConverter; 26 import com.google.crypto.tink.jwt.JwtHmacKeyManager; 27 import com.google.crypto.tink.jwt.JwtMacConfig; 28 import com.google.crypto.tink.jwt.JwtSignatureConfig; 29 import com.google.crypto.tink.testing.proto.AnnotatedKeyset; 30 import com.google.crypto.tink.testing.proto.CreationRequest; 31 import com.google.crypto.tink.testing.proto.CreationResponse; 32 import com.google.crypto.tink.testing.proto.JwtClaimValue; 33 import com.google.crypto.tink.testing.proto.JwtFromJwkSetRequest; 34 import com.google.crypto.tink.testing.proto.JwtFromJwkSetResponse; 35 import com.google.crypto.tink.testing.proto.JwtGrpc; 36 import com.google.crypto.tink.testing.proto.JwtSignRequest; 37 import com.google.crypto.tink.testing.proto.JwtSignResponse; 38 import com.google.crypto.tink.testing.proto.JwtToJwkSetRequest; 39 import com.google.crypto.tink.testing.proto.JwtToJwkSetResponse; 40 import com.google.crypto.tink.testing.proto.JwtToken; 41 import com.google.crypto.tink.testing.proto.JwtValidator; 42 import com.google.crypto.tink.testing.proto.JwtVerifyRequest; 43 import com.google.crypto.tink.testing.proto.JwtVerifyResponse; 44 import com.google.crypto.tink.testing.proto.KeysetGenerateRequest; 45 import com.google.crypto.tink.testing.proto.KeysetGenerateResponse; 46 import com.google.crypto.tink.testing.proto.KeysetGrpc; 47 import com.google.crypto.tink.testing.proto.KeysetPublicRequest; 48 import com.google.crypto.tink.testing.proto.KeysetPublicResponse; 49 import com.google.crypto.tink.testing.proto.NullValue; 50 import com.google.protobuf.ByteString; 51 import com.google.protobuf.StringValue; 52 import com.google.protobuf.Timestamp; 53 import io.grpc.ManagedChannel; 54 import io.grpc.Server; 55 import io.grpc.inprocess.InProcessChannelBuilder; 56 import io.grpc.inprocess.InProcessServerBuilder; 57 import org.junit.After; 58 import org.junit.Before; 59 import org.junit.Test; 60 import org.junit.runner.RunWith; 61 import org.junit.runners.JUnit4; 62 63 @RunWith(JUnit4.class) 64 public final class JwtServiceImplTest { 65 private Server server; 66 private ManagedChannel channel; 67 KeysetGrpc.KeysetBlockingStub keysetStub; 68 JwtGrpc.JwtBlockingStub jwtStub; 69 70 @Before setUp()71 public void setUp() throws Exception { 72 JwtMacConfig.register(); 73 JwtSignatureConfig.register(); 74 75 String serverName = InProcessServerBuilder.generateName(); 76 server = 77 InProcessServerBuilder.forName(serverName) 78 .directExecutor() 79 .addService(new KeysetServiceImpl()) 80 .addService(new JwtServiceImpl()) 81 .build() 82 .start(); 83 channel = InProcessChannelBuilder.forName(serverName).directExecutor().build(); 84 keysetStub = KeysetGrpc.newBlockingStub(channel); 85 jwtStub = JwtGrpc.newBlockingStub(channel); 86 } 87 88 @After tearDown()89 public void tearDown() throws Exception { 90 assertThat(channel.shutdown().awaitTermination(5, SECONDS)).isTrue(); 91 assertThat(server.shutdown().awaitTermination(5, SECONDS)).isTrue(); 92 } 93 generateKeyset( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] template)94 private static KeysetGenerateResponse generateKeyset( 95 KeysetGrpc.KeysetBlockingStub keysetStub, byte[] template) { 96 KeysetGenerateRequest genRequest = 97 KeysetGenerateRequest.newBuilder().setTemplate(ByteString.copyFrom(template)).build(); 98 return keysetStub.generate(genRequest); 99 } 100 publicKeyset( KeysetGrpc.KeysetBlockingStub keysetStub, byte[] privateKeyset)101 private static KeysetPublicResponse publicKeyset( 102 KeysetGrpc.KeysetBlockingStub keysetStub, byte[] privateKeyset) { 103 KeysetPublicRequest request = 104 KeysetPublicRequest.newBuilder() 105 .setPrivateKeyset(ByteString.copyFrom(privateKeyset)) 106 .build(); 107 return keysetStub.public_(request); 108 } 109 generateToken(String audience, long expSeconds, int expNanos)110 private JwtToken generateToken(String audience, long expSeconds, int expNanos) { 111 return JwtToken.newBuilder() 112 .setTypeHeader(StringValue.newBuilder().setValue("typeHeader")) 113 .setIssuer(StringValue.newBuilder().setValue("issuer")) 114 .addAudiences(audience) 115 .addAudiences(audience + "2") 116 .setJwtId(StringValue.newBuilder().setValue("123abc")) 117 .putCustomClaims("boolean", JwtClaimValue.newBuilder().setBoolValue(true).build()) 118 .putCustomClaims( 119 "null", JwtClaimValue.newBuilder().setNullValue(NullValue.NULL_VALUE).build()) 120 .putCustomClaims("number", JwtClaimValue.newBuilder().setNumberValue(123.456).build()) 121 .putCustomClaims("string", JwtClaimValue.newBuilder().setStringValue("foo").build()) 122 .putCustomClaims( 123 "json_array", 124 JwtClaimValue.newBuilder() 125 .setJsonArrayValue("[123,\"value\",null,[],{\"a\":42}]") 126 .build()) 127 .putCustomClaims( 128 "json_object", 129 JwtClaimValue.newBuilder().setJsonObjectValue("{\"a\":[null,{\"b\":42}]}").build()) 130 .setExpiration(Timestamp.newBuilder().setSeconds(expSeconds).setNanos(expNanos)) 131 .build(); 132 } 133 134 @Test jwtMacCreateKeyset_success()135 public void jwtMacCreateKeyset_success() throws Exception { 136 byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("JWT_HS256")); 137 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 138 assertThat(keysetResponse.getErr()).isEmpty(); 139 CreationResponse response = 140 jwtStub.createJwtMac( 141 CreationRequest.newBuilder() 142 .setAnnotatedKeyset( 143 AnnotatedKeyset.newBuilder() 144 .setSerializedKeyset(keysetResponse.getKeyset()) 145 .build()) 146 .build()); 147 assertThat(response.getErr()).isEmpty(); 148 } 149 150 @Test jwtMacCreateKeyset_fails()151 public void jwtMacCreateKeyset_fails() throws Exception { 152 CreationResponse response = 153 jwtStub.createJwtMac( 154 CreationRequest.newBuilder() 155 .setAnnotatedKeyset( 156 AnnotatedKeyset.newBuilder() 157 .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80})) 158 .build()) 159 .build()); 160 assertThat(response.getErr()).isNotEmpty(); 161 } 162 163 @Test jwtComputeVerifyMac_success()164 public void jwtComputeVerifyMac_success() throws Exception { 165 byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("JWT_HS256")); 166 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 167 assertThat(keysetResponse.getErr()).isEmpty(); 168 byte[] keyset = keysetResponse.getKeyset().toByteArray(); 169 170 long expSecs = 1234 + 100; 171 int expNanos = 567000000; 172 JwtToken token = generateToken("audience", expSecs, expNanos); 173 174 JwtSignRequest signRequest = 175 JwtSignRequest.newBuilder() 176 .setAnnotatedKeyset( 177 AnnotatedKeyset.newBuilder() 178 .setSerializedKeyset(ByteString.copyFrom(keyset)) 179 .build()) 180 .setRawJwt(token) 181 .build(); 182 JwtSignResponse signResponse = jwtStub.computeMacAndEncode(signRequest); 183 assertThat(signResponse.getErr()).isEmpty(); 184 185 JwtValidator validator = 186 JwtValidator.newBuilder() 187 .setExpectedTypeHeader(StringValue.newBuilder().setValue("typeHeader")) 188 .setExpectedIssuer(StringValue.newBuilder().setValue("issuer")) 189 .setExpectedAudience(StringValue.newBuilder().setValue("audience")) 190 .setNow(Timestamp.newBuilder().setSeconds(1234)) 191 .build(); 192 JwtVerifyRequest verifyRequest = 193 JwtVerifyRequest.newBuilder() 194 .setAnnotatedKeyset( 195 AnnotatedKeyset.newBuilder() 196 .setSerializedKeyset(ByteString.copyFrom(keyset)) 197 .build()) 198 .setSignedCompactJwt(signResponse.getSignedCompactJwt()) 199 .setValidator(validator) 200 .build(); 201 202 JwtToken expectedToken = generateToken("audience", expSecs, 0); 203 JwtVerifyResponse verifyResponse = jwtStub.verifyMacAndDecode(verifyRequest); 204 assertThat(verifyResponse.getErr()).isEmpty(); 205 assertThat(verifyResponse.getVerifiedJwt()).isEqualTo(expectedToken); 206 } 207 208 @Test jwtEmptyTokenComputeVerifyMac_success()209 public void jwtEmptyTokenComputeVerifyMac_success() throws Exception { 210 byte[] template = KeyTemplateProtoConverter.toByteArray(JwtHmacKeyManager.hs256Template()); 211 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 212 assertThat(keysetResponse.getErr()).isEmpty(); 213 byte[] keyset = keysetResponse.getKeyset().toByteArray(); 214 215 JwtToken token = JwtToken.getDefaultInstance(); 216 217 JwtSignRequest signRequest = 218 JwtSignRequest.newBuilder() 219 .setAnnotatedKeyset( 220 AnnotatedKeyset.newBuilder() 221 .setSerializedKeyset(ByteString.copyFrom(keyset)) 222 .build()) 223 .setRawJwt(token) 224 .build(); 225 JwtSignResponse signResponse = jwtStub.computeMacAndEncode(signRequest); 226 assertThat(signResponse.getErr()).isEmpty(); 227 228 JwtValidator validator = JwtValidator.newBuilder().setAllowMissingExpiration(true).build(); 229 JwtVerifyRequest verifyRequest = 230 JwtVerifyRequest.newBuilder() 231 .setAnnotatedKeyset( 232 AnnotatedKeyset.newBuilder() 233 .setSerializedKeyset(ByteString.copyFrom(keyset)) 234 .build()) 235 .setSignedCompactJwt(signResponse.getSignedCompactJwt()) 236 .setValidator(validator) 237 .build(); 238 239 JwtVerifyResponse verifyResponse = jwtStub.verifyMacAndDecode(verifyRequest); 240 assertThat(verifyResponse.getErr()).isEmpty(); 241 assertThat(verifyResponse.getVerifiedJwt()).isEqualTo(token); 242 } 243 244 @Test jwtPublicKeySignCreateKeyset_success()245 public void jwtPublicKeySignCreateKeyset_success() throws Exception { 246 byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("JWT_ES256")); 247 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 248 assertThat(keysetResponse.getErr()).isEmpty(); 249 CreationResponse response = 250 jwtStub.createJwtPublicKeySign( 251 CreationRequest.newBuilder() 252 .setAnnotatedKeyset( 253 AnnotatedKeyset.newBuilder() 254 .setSerializedKeyset(keysetResponse.getKeyset()) 255 .build()) 256 .build()); 257 assertThat(response.getErr()).isEmpty(); 258 } 259 260 @Test jwtPublicKeySignCreateKeyset_fails()261 public void jwtPublicKeySignCreateKeyset_fails() throws Exception { 262 CreationResponse response = 263 jwtStub.createJwtPublicKeySign( 264 CreationRequest.newBuilder() 265 .setAnnotatedKeyset( 266 AnnotatedKeyset.newBuilder() 267 .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80}))) 268 .build()); 269 assertThat(response.getErr()).isNotEmpty(); 270 } 271 272 @Test jwtPublicKeyVerifyCreateKeyset_success()273 public void jwtPublicKeyVerifyCreateKeyset_success() throws Exception { 274 byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("JWT_ES256")); 275 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 276 assertThat(keysetResponse.getErr()).isEmpty(); 277 byte[] privateKeyset = keysetResponse.getKeyset().toByteArray(); 278 279 KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset); 280 assertThat(pubResponse.getErr()).isEmpty(); 281 CreationResponse response = 282 jwtStub.createJwtPublicKeyVerify( 283 CreationRequest.newBuilder() 284 .setAnnotatedKeyset( 285 AnnotatedKeyset.newBuilder() 286 .setSerializedKeyset(pubResponse.getPublicKeyset()) 287 .build()) 288 .build()); 289 assertThat(response.getErr()).isEmpty(); 290 } 291 292 @Test jwtPublicKeyVerifyCreateKeyset_fails()293 public void jwtPublicKeyVerifyCreateKeyset_fails() throws Exception { 294 CreationResponse response = 295 jwtStub.createJwtPublicKeyVerify( 296 CreationRequest.newBuilder() 297 .setAnnotatedKeyset( 298 AnnotatedKeyset.newBuilder() 299 .setSerializedKeyset(ByteString.copyFrom(new byte[] {(byte) 0x80})) 300 .build()) 301 .build()); 302 assertThat(response.getErr()).isNotEmpty(); 303 } 304 305 @Test publicKeySignVerify_success()306 public void publicKeySignVerify_success() throws Exception { 307 byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("JWT_ES256")); 308 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 309 assertThat(keysetResponse.getErr()).isEmpty(); 310 byte[] privateKeyset = keysetResponse.getKeyset().toByteArray(); 311 312 KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset); 313 assertThat(pubResponse.getErr()).isEmpty(); 314 byte[] publicKeyset = pubResponse.getPublicKeyset().toByteArray(); 315 316 long expSecs = 1234 + 100; 317 int expNanos = 567000000; 318 JwtToken token = generateToken("audience", expSecs, expNanos); 319 320 JwtSignRequest signRequest = 321 JwtSignRequest.newBuilder() 322 .setAnnotatedKeyset( 323 AnnotatedKeyset.newBuilder() 324 .setSerializedKeyset(ByteString.copyFrom(privateKeyset)) 325 .build()) 326 .setRawJwt(token) 327 .build(); 328 JwtSignResponse signResponse = jwtStub.publicKeySignAndEncode(signRequest); 329 assertThat(signResponse.getErr()).isEmpty(); 330 331 JwtValidator validator = 332 JwtValidator.newBuilder() 333 .setExpectedTypeHeader(StringValue.newBuilder().setValue("typeHeader")) 334 .setExpectedIssuer(StringValue.newBuilder().setValue("issuer")) 335 .setExpectedAudience(StringValue.newBuilder().setValue("audience")) 336 .setNow(Timestamp.newBuilder().setSeconds(1234)) 337 .build(); 338 JwtVerifyRequest verifyRequest = 339 JwtVerifyRequest.newBuilder() 340 .setAnnotatedKeyset( 341 AnnotatedKeyset.newBuilder() 342 .setSerializedKeyset(ByteString.copyFrom(publicKeyset)) 343 .build()) 344 .setSignedCompactJwt(signResponse.getSignedCompactJwt()) 345 .setValidator(validator) 346 .build(); 347 348 JwtToken expectedToken = generateToken("audience", expSecs, 0); 349 JwtVerifyResponse verifyResponse = jwtStub.publicKeyVerifyAndDecode(verifyRequest); 350 assertThat(verifyResponse.getErr()).isEmpty(); 351 assertThat(verifyResponse.getVerifiedJwt()).isEqualTo(expectedToken); 352 } 353 354 @Test signFailsOnBadKeyset()355 public void signFailsOnBadKeyset() throws Exception { 356 byte[] badKeyset = "bad keyset".getBytes(UTF_8); 357 358 JwtToken token = generateToken("audience", 1234, 0); 359 JwtSignRequest signRequest = 360 JwtSignRequest.newBuilder() 361 .setAnnotatedKeyset( 362 AnnotatedKeyset.newBuilder() 363 .setSerializedKeyset(ByteString.copyFrom(badKeyset)) 364 .build()) 365 .setRawJwt(token) 366 .build(); 367 assertThrows( 368 io.grpc.StatusRuntimeException.class, () -> jwtStub.computeMacAndEncode(signRequest)); 369 } 370 371 @Test verifyFailsWhenExpired()372 public void verifyFailsWhenExpired() throws Exception { 373 byte[] template = KeyTemplateProtoConverter.toByteArray(JwtHmacKeyManager.hs256Template()); 374 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 375 assertThat(keysetResponse.getErr()).isEmpty(); 376 byte[] keyset = keysetResponse.getKeyset().toByteArray(); 377 378 JwtToken token = generateToken("audience", 1234 - 10, 0); 379 380 JwtSignRequest signRequest = 381 JwtSignRequest.newBuilder() 382 .setAnnotatedKeyset( 383 AnnotatedKeyset.newBuilder() 384 .setSerializedKeyset(ByteString.copyFrom(keyset)) 385 .build()) 386 .setRawJwt(token) 387 .build(); 388 JwtSignResponse signResponse = jwtStub.computeMacAndEncode(signRequest); 389 assertThat(signResponse.getErr()).isEmpty(); 390 391 JwtValidator validator = 392 JwtValidator.newBuilder() 393 .setExpectedTypeHeader(StringValue.newBuilder().setValue("typeHeader")) 394 .setExpectedIssuer(StringValue.newBuilder().setValue("issuer")) 395 .setExpectedAudience(StringValue.newBuilder().setValue("audience")) 396 .setNow(Timestamp.newBuilder().setSeconds(1234)) 397 .build(); 398 JwtVerifyRequest verifyRequest = 399 JwtVerifyRequest.newBuilder() 400 .setAnnotatedKeyset( 401 AnnotatedKeyset.newBuilder() 402 .setSerializedKeyset(ByteString.copyFrom(keyset)) 403 .build()) 404 .setSignedCompactJwt(signResponse.getSignedCompactJwt()) 405 .setValidator(validator) 406 .build(); 407 408 JwtVerifyResponse verifyResponse = jwtStub.verifyMacAndDecode(verifyRequest); 409 assertThat(verifyResponse.getErr()).isNotEmpty(); 410 } 411 412 @Test verifyFailsWithWrongAudience()413 public void verifyFailsWithWrongAudience() throws Exception { 414 byte[] template = KeyTemplateProtoConverter.toByteArray(JwtHmacKeyManager.hs256Template()); 415 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 416 assertThat(keysetResponse.getErr()).isEmpty(); 417 byte[] keyset = keysetResponse.getKeyset().toByteArray(); 418 419 JwtToken token = generateToken("wrong_audience", 1234 + 100, 0); 420 421 JwtSignRequest signRequest = 422 JwtSignRequest.newBuilder() 423 .setAnnotatedKeyset( 424 AnnotatedKeyset.newBuilder() 425 .setSerializedKeyset(ByteString.copyFrom(keyset)) 426 .build()) 427 .setRawJwt(token) 428 .build(); 429 JwtSignResponse signResponse = jwtStub.computeMacAndEncode(signRequest); 430 assertThat(signResponse.getErr()).isEmpty(); 431 432 JwtValidator validator = 433 JwtValidator.newBuilder() 434 .setExpectedTypeHeader(StringValue.newBuilder().setValue("typeHeader")) 435 .setExpectedIssuer(StringValue.newBuilder().setValue("issuer")) 436 .setExpectedAudience(StringValue.newBuilder().setValue("audience")) 437 .setNow(Timestamp.newBuilder().setSeconds(1234)) 438 .build(); 439 JwtVerifyRequest verifyRequest = 440 JwtVerifyRequest.newBuilder() 441 .setAnnotatedKeyset( 442 AnnotatedKeyset.newBuilder() 443 .setSerializedKeyset(ByteString.copyFrom(keyset)) 444 .build()) 445 .setSignedCompactJwt(signResponse.getSignedCompactJwt()) 446 .setValidator(validator) 447 .build(); 448 449 JwtVerifyResponse verifyResponse = jwtStub.verifyMacAndDecode(verifyRequest); 450 assertThat(verifyResponse.getErr()).isNotEmpty(); 451 } 452 453 @Test verifyFailsWithWrongKey()454 public void verifyFailsWithWrongKey() throws Exception { 455 byte[] template = KeyTemplateProtoConverter.toByteArray(JwtHmacKeyManager.hs256Template()); 456 457 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 458 assertThat(keysetResponse.getErr()).isEmpty(); 459 byte[] keyset = keysetResponse.getKeyset().toByteArray(); 460 461 JwtToken token = generateToken("audience", 1234 + 100, 0); 462 463 JwtSignRequest signRequest = 464 JwtSignRequest.newBuilder() 465 .setAnnotatedKeyset( 466 AnnotatedKeyset.newBuilder() 467 .setSerializedKeyset(ByteString.copyFrom(keyset)) 468 .build()) 469 .setRawJwt(token) 470 .build(); 471 JwtSignResponse signResponse = jwtStub.computeMacAndEncode(signRequest); 472 assertThat(signResponse.getErr()).isEmpty(); 473 474 KeysetGenerateResponse wrongKeysetResponse = generateKeyset(keysetStub, template); 475 assertThat(wrongKeysetResponse.getErr()).isEmpty(); 476 byte[] wrongKeyset = wrongKeysetResponse.getKeyset().toByteArray(); 477 478 JwtValidator validator = 479 JwtValidator.newBuilder() 480 .setExpectedTypeHeader(StringValue.newBuilder().setValue("typeHeader")) 481 .setExpectedIssuer(StringValue.newBuilder().setValue("issuer")) 482 .setExpectedAudience(StringValue.newBuilder().setValue("audience")) 483 .setNow(Timestamp.newBuilder().setSeconds(1234)) 484 .build(); 485 JwtVerifyRequest verifyRequest = 486 JwtVerifyRequest.newBuilder() 487 .setAnnotatedKeyset( 488 AnnotatedKeyset.newBuilder() 489 .setSerializedKeyset(ByteString.copyFrom(wrongKeyset)) 490 .build()) 491 .setSignedCompactJwt(signResponse.getSignedCompactJwt()) 492 .setValidator(validator) 493 .build(); 494 495 JwtVerifyResponse verifyResponse = jwtStub.verifyMacAndDecode(verifyRequest); 496 assertThat(verifyResponse.getErr()).isNotEmpty(); 497 } 498 499 @Test jwtToFromJwt_success()500 public void jwtToFromJwt_success() throws Exception { 501 byte[] template = KeyTemplateProtoConverter.toByteArray(KeyTemplates.get("JWT_ES256")); 502 KeysetGenerateResponse keysetResponse = generateKeyset(keysetStub, template); 503 assertThat(keysetResponse.getErr()).isEmpty(); 504 byte[] privateKeyset = keysetResponse.getKeyset().toByteArray(); 505 506 KeysetPublicResponse pubResponse = publicKeyset(keysetStub, privateKeyset); 507 assertThat(pubResponse.getErr()).isEmpty(); 508 byte[] publicKeyset = pubResponse.getPublicKeyset().toByteArray(); 509 510 JwtToken token = generateToken("audience", 1245, 0); 511 512 JwtSignRequest signRequest = 513 JwtSignRequest.newBuilder() 514 .setAnnotatedKeyset( 515 AnnotatedKeyset.newBuilder() 516 .setSerializedKeyset(ByteString.copyFrom(privateKeyset)) 517 .build()) 518 .setRawJwt(token) 519 .build(); 520 JwtSignResponse signResponse = jwtStub.publicKeySignAndEncode(signRequest); 521 assertThat(signResponse.getErr()).isEmpty(); 522 523 // Convert the public keyset to a JWK set 524 JwtToJwkSetRequest toRequest = 525 JwtToJwkSetRequest.newBuilder().setKeyset(ByteString.copyFrom(publicKeyset)).build(); 526 JwtToJwkSetResponse toResponse = jwtStub.toJwkSet(toRequest); 527 assertThat(toResponse.getErr()).isEmpty(); 528 assertThat(toResponse.getJwkSet()).contains("{\"keys\":[{\"kty\":\"EC\",\"crv\":\"P-256\","); 529 // Convert the public keyset to a JWK set 530 JwtFromJwkSetRequest fromRequest = 531 JwtFromJwkSetRequest.newBuilder().setJwkSet(toResponse.getJwkSet()).build(); 532 JwtFromJwkSetResponse fromResponse = jwtStub.fromJwkSet(fromRequest); 533 assertThat(fromResponse.getErr()).isEmpty(); 534 535 // Use that output keyset to verify the token 536 JwtValidator validator = 537 JwtValidator.newBuilder() 538 .setExpectedTypeHeader(StringValue.newBuilder().setValue("typeHeader")) 539 .setExpectedIssuer(StringValue.newBuilder().setValue("issuer")) 540 .setExpectedAudience(StringValue.newBuilder().setValue("audience")) 541 .setNow(Timestamp.newBuilder().setSeconds(1234)) 542 .build(); 543 JwtVerifyRequest verifyRequest = 544 JwtVerifyRequest.newBuilder() 545 .setAnnotatedKeyset( 546 AnnotatedKeyset.newBuilder().setSerializedKeyset(fromResponse.getKeyset()).build()) 547 .setSignedCompactJwt(signResponse.getSignedCompactJwt()) 548 .setValidator(validator) 549 .build(); 550 JwtVerifyResponse verifyResponse = jwtStub.publicKeyVerifyAndDecode(verifyRequest); 551 assertThat(verifyResponse.getErr()).isEmpty(); 552 } 553 } 554