JjwtIdTokenFactory implements IdTokenFactory { @Override public Optional<String> create(String host, String clientId, Identity identity, Long ttl, DateTime instant) { List<IdentityKeyPair> keys = keyStore.getKeys(); if (keys == null || keys.isEmpty()) { return Optional.absent(); } IdentityKeyPair signingKey = randomKey(keys); Map<String, Object> claims = new LinkedHashMap<>(); claims.put("iss", host); claims.put("aud", clientId); claims.put("sub", identity.id()); claims.put("name", identity.name()); claims.put("email", identity.email()); claims.put("given_name", identity.givenName()); claims.put("family_name", identity.familyName()); claims.putAll(identity.claims()); return Optional.of(Jwts.builder() .setHeaderParam("cid", signingKey.keyId) .setClaims(claims) .setIssuedAt(new Date(instant.timestamp())) .setExpiration(new Date(instant.timestamp() + ttl)) .signWith(SignatureAlgorithm.RS256, signingKey.privateKey) .compact()); } JjwtIdTokenFactory(KeyStore keyStore); @Override Optional<String> create(String host, String clientId, Identity identity, Long ttl, DateTime instant);  }
@Test public void createNewIdToken() throws Exception { final KeyStore keyStore = context.mock(KeyStore.class); final DateTime instant = new DateTime().plusSeconds(60); final KeyPair keyPair = PemKeyGenerator.generatePair(); context.checking(new Expectations() {{ oneOf(keyStore).getKeys(); will(returnValue(Collections.singletonList(new IdentityKeyPair("::any key::", keyPair.getPrivate(), keyPair.getPublic())))); }}); JjwtIdTokenFactory factory = new JjwtIdTokenFactory(keyStore); Optional<String> possibleIdToken = factory.create( "::any host::", "::any client::", aNewIdentity().withId("123").build(), 10L, instant ); Jws<Claims> jwt = Jwts.parser().setSigningKey(keyPair.getPublic()).parseClaimsJws(possibleIdToken.get()); assertThat(jwt.getBody().getAudience(), is(equalTo("::any client::"))); assertThat(jwt.getBody().getIssuer(), is(equalTo("::any host::"))); assertThat(jwt.getBody().getSubject(), is(equalTo("123"))); }
@Test public void idTokensAreDifferentForEachClient() throws Exception { final KeyStore keyStore = context.mock(KeyStore.class); final DateTime anyInstantTime = newDateTime(2017, 5, 14, 11, 0, 0); final KeyPair firstKeyPair = PemKeyGenerator.generatePair(); final KeyPair secondKeyPair = PemKeyGenerator.generatePair(); context.checking(new Expectations() {{ oneOf(keyStore).getKeys(); will(returnValue(Collections.singletonList( new IdentityKeyPair("::first key::", firstKeyPair.getPrivate(), firstKeyPair.getPublic())))); oneOf(keyStore).getKeys(); will(returnValue(Collections.singletonList( new IdentityKeyPair("::second key::", secondKeyPair.getPrivate(), secondKeyPair.getPublic())))); }}); JjwtIdTokenFactory factory = new JjwtIdTokenFactory(keyStore); Optional<String> firstIdToken = factory.create( "::any host::", "::client 1::", aNewIdentity().withId("123").build(), 10L, anyInstantTime ); Optional<String> secondIdToken = factory.create( "::any host::", "::client 2::", aNewIdentity().withId("123").build(), 10L, anyInstantTime ); assertThat(firstIdToken.get(), is(not(equalTo(secondIdToken.get())))); }
@Test public void noCertificatesAreAvailableForSigningOfKey() throws Exception { final KeyStore keyStore = context.mock(KeyStore.class); context.checking(new Expectations() {{ oneOf(keyStore).getKeys(); will(returnValue(Collections.emptyList())); }}); JjwtIdTokenFactory factory = new JjwtIdTokenFactory(keyStore); Optional<String> possibleIdToken = factory.create("::any host::", "::any client::", aNewIdentity().withId("123").build(), 10L, new DateTime()); assertThat(possibleIdToken.isPresent(), is(false)); }