/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wildfly.security.auth.realm.token; import com.nimbusds.jose.JOSEObjectType; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSHeader; import com.nimbusds.jose.JWSObject; import com.nimbusds.jose.JWSSigner; import com.nimbusds.jose.Payload; import com.nimbusds.jose.crypto.RSASSASigner; import mockit.integration.junit4.JMockit; import org.junit.Test; import org.junit.runner.RunWith; import org.wildfly.security.auth.realm.token.validator.JwtValidator; import org.wildfly.security.auth.server.RealmIdentity; import org.wildfly.security.evidence.BearerTokenEvidence; import org.wildfly.security.pem.Pem; import org.wildfly.security.sasl.test.BaseTestCase; import org.wildfly.security.util.ByteStringBuilder; import javax.json.Json; import javax.json.JsonObjectBuilder; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import static org.junit.Assert.*; /** * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> */ @RunWith(JMockit.class) public class JwtSecurityRealmTest extends BaseTestCase { @Test public void testUsingGeneratedPublicKey() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); ByteStringBuilder publicKeyPem = new ByteStringBuilder(); Pem.generatePemPublicKey(publicKeyPem, keyPair.getPublic()); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder() .issuer("elytron-oauth2-realm") .audience("my-app-valid") .publicKey(publicKeyPem.toArray()).build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(new BearerTokenEvidence(createJwt(keyPair, 10, 0))); assertNotNull(realmIdentity); assertTrue(realmIdentity.exists()); assertEquals("elytron@jboss.org", realmIdentity.getRealmIdentityPrincipal().getName()); } @Test public void testEmptyConfiguration() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); ByteStringBuilder publicKeyPem = new ByteStringBuilder(); Pem.generatePemPublicKey(publicKeyPem, keyPair.getPublic()); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder().build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(new BearerTokenEvidence(createJwt(keyPair, 10, 0))); assertNotNull(realmIdentity); assertTrue(realmIdentity.exists()); assertEquals("elytron@jboss.org", realmIdentity.getRealmIdentityPrincipal().getName()); } @Test public void testWithMultipleAudience() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder() .issuer("elytron-oauth2-realm") .audience("third-app", "another-app-valid", "my-app") .publicKey(keyPair.getPublic()).build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(new BearerTokenEvidence(createJwt(keyPair))); assertNotNull(realmIdentity); assertTrue(realmIdentity.exists()); assertEquals("elytron@jboss.org", realmIdentity.getRealmIdentityPrincipal().getName()); } @Test public void testInvalidSignature() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); BearerTokenEvidence evidence = new BearerTokenEvidence(createJwt(keyPair)); KeyPair anotherKeyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder() .issuer("elytron-oauth2-realm") .audience("my-app-valid") .publicKey(anotherKeyPair.getPublic()).build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(evidence); assertNotNull(realmIdentity); assertFalse(realmIdentity.exists()); } @Test public void testInvalidIssuer() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); BearerTokenEvidence evidence = new BearerTokenEvidence(createJwt(keyPair)); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder() .issuer("different-issuer") .audience("my-app-valid") .publicKey(keyPair.getPublic()).build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(evidence); assertNotNull(realmIdentity); assertFalse(realmIdentity.exists()); } @Test public void testInvalidAudience() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); BearerTokenEvidence evidence = new BearerTokenEvidence(createJwt(keyPair)); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder() .issuer("elytron-oauth2-realm") .audience("different-audience") .publicKey(keyPair.getPublic()).build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(evidence); assertNotNull(realmIdentity); assertFalse(realmIdentity.exists()); } @Test public void testTokenExpired() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); BearerTokenEvidence evidence = new BearerTokenEvidence(createJwt(keyPair, -1)); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder() .issuer("elytron-oauth2-realm") .audience("different-audience") .publicKey(keyPair.getPublic()).build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(evidence); assertNotNull(realmIdentity); assertFalse(realmIdentity.exists()); } @Test public void testTokenNotBefore() throws Exception { KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair(); BearerTokenEvidence evidence = new BearerTokenEvidence(createJwt(keyPair, 10, 10)); TokenSecurityRealm securityRealm = TokenSecurityRealm.builder() .principalClaimName("sub") .validator(JwtValidator.builder() .issuer("elytron-oauth2-realm") .audience("different-audience") .publicKey(keyPair.getPublic()).build()) .build(); RealmIdentity realmIdentity = securityRealm.getRealmIdentity(evidence); assertNotNull(realmIdentity); assertFalse(realmIdentity.exists()); } private String createJwt(KeyPair keyPair, int expirationOffset) throws Exception { return createJwt(keyPair, expirationOffset, -1); } private String createJwt(KeyPair keyPair, int expirationOffset, int notBeforeOffset) throws Exception { PrivateKey privateKey = keyPair.getPrivate(); JWSSigner signer = new RSASSASigner(privateKey); JsonObjectBuilder claimsBuilder = Json.createObjectBuilder() .add("active", true) .add("sub", "elytron@jboss.org") .add("iss", "elytron-oauth2-realm") .add("aud", Json.createArrayBuilder().add("my-app-valid").add("third-app-valid").add("another-app-valid").build()) .add("exp", (System.currentTimeMillis() / 1000) + expirationOffset); if (notBeforeOffset > 0) { claimsBuilder.add("nbf", (System.currentTimeMillis() / 1000) + notBeforeOffset); } JWSObject jwsObject = new JWSObject(new JWSHeader.Builder(JWSAlgorithm.RS256) .type(new JOSEObjectType("jwt")).build(), new Payload(claimsBuilder .build().toString())); jwsObject.sign(signer); String s = jwsObject.serialize(); return s; } private String createJwt(KeyPair keyPair) throws Exception { return createJwt(keyPair, 60); } }