Adding negative tests for SAML authentication in OAuth # Conflicts: # systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/87c7e02a Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/87c7e02a Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/87c7e02a Branch: refs/heads/3.0.x-fixes Commit: 87c7e02a9f9ed689e7b7dbbc569e46024bdcb77c Parents: 80e4f1f Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Fri Dec 11 16:35:13 2015 +0000 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Fri Dec 11 16:37:14 2015 +0000 ---------------------------------------------------------------------- .../jaxrs/security/oauth2/JAXRSOAuth2Test.java | 277 ++++++++++++++++++- .../security/oauth2/SamlCallbackHandler.java | 17 +- 2 files changed, 289 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/87c7e02a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java index 664752f..2bb18c5 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/JAXRSOAuth2Test.java @@ -38,12 +38,23 @@ import org.apache.cxf.rs.security.oauth2.client.OAuthClientUtils; import org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant; import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken; import org.apache.cxf.rs.security.oauth2.grants.saml.Saml2BearerGrant; +import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; import org.apache.cxf.rs.security.oauth2.saml.Constants; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; import org.apache.cxf.rs.security.saml.SAMLUtils; import org.apache.cxf.rs.security.saml.SAMLUtils.SelfSignInfo; import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; import org.apache.wss4j.common.crypto.Crypto; +<<<<<<< HEAD +======= +import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.common.saml.SAMLCallback; +import org.apache.wss4j.common.saml.SAMLUtil; +import org.apache.wss4j.common.saml.SamlAssertionWrapper; +import org.apache.wss4j.common.saml.builder.SAML1Constants; +import org.apache.wss4j.common.saml.builder.SAML2Constants; +import org.apache.wss4j.common.util.DOM2Writer; +>>>>>>> 706ddbc... Adding negative tests for SAML authentication in OAuth import org.junit.BeforeClass; import org.junit.Test; @@ -57,7 +68,7 @@ public class JAXRSOAuth2Test extends AbstractBusClientServerTestBase { assertTrue("server did not launch correctly", launchServer(BookServerOAuth2.class, true)); } - + @Test public void testSAML2BearerGrant() throws Exception { String address = "https://localhost:" + PORT + "/oauth2/token"; @@ -122,6 +133,198 @@ public class JAXRSOAuth2Test extends AbstractBusClientServerTestBase { assertNotNull(at.getTokenKey()); } +<<<<<<< HEAD +======= + @Test + public void testJWTBearerGrant() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2/token"; + WebClient wc = createWebClient(address); + + // Create the JWT Token + String token = createToken("resourceOwner", "alice", address, true, true); + + JwtBearerGrant grant = new JwtBearerGrant(token); + ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, + new Consumer("alice", "alice"), + grant, + false); + assertNotNull(at.getTokenKey()); + } + + @Test + public void testJWTBearerAuthenticationDirect() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2-auth-jwt/token"; + WebClient wc = createWebClient(address); + + // Create the JWT Token + String token = createToken("resourceOwner", "alice", address, true, true); + + Map<String, String> extraParams = new HashMap<String, String>(); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE, + "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, token); + + ClientAccessToken at = OAuthClientUtils.getAccessToken(wc, + new CustomGrant(), + extraParams); + assertNotNull(at.getTokenKey()); + } + + // + // Some negative tests for authentication + // + + @Test + public void testSAML11() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2-auth/token"; + WebClient wc = createWebClient(address); + + String audienceURI = "https://localhost:" + PORT + "/oauth2-auth/token"; + String assertion = createToken(audienceURI, false, true); + String encodedAssertion = Base64UrlUtility.encode(assertion); + + Map<String, String> extraParams = new HashMap<String, String>(); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_SAML2_BEARER); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodedAssertion); + + try { + OAuthClientUtils.getAccessToken(wc, new CustomGrant(), extraParams); + fail("Failure expected on a SAML 1.1 Assertion"); + } catch (OAuthServiceException ex) { + // expected + } + } + + @Test + public void testSAMLAudRestr() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2-auth/token"; + WebClient wc = createWebClient(address); + + String audienceURI = "https://localhost:" + PORT + "/oauth2-auth/token2"; + String assertion = createToken(audienceURI, true, true); + String encodedAssertion = Base64UrlUtility.encode(assertion); + + Map<String, String> extraParams = new HashMap<String, String>(); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_SAML2_BEARER); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodedAssertion); + + try { + OAuthClientUtils.getAccessToken(wc, new CustomGrant(), extraParams); + fail("Failure expected on a bad audience restriction"); + } catch (OAuthServiceException ex) { + // expected + } + } + + @Test + public void testSAMLBadSubjectName() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2-auth/token"; + WebClient wc = createWebClient(address); + + String audienceURI = "https://localhost:" + PORT + "/oauth2-auth/token"; + + // Create the SAML Assertion + SamlCallbackHandler samlCallbackHandler = new SamlCallbackHandler(true); + samlCallbackHandler.setSubjectName("bob"); + samlCallbackHandler.setAudience(audienceURI); + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback); + + SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback); + if (samlCallback.isSignAssertion()) { + samlAssertion.signAssertion( + samlCallback.getIssuerKeyName(), + samlCallback.getIssuerKeyPassword(), + samlCallback.getIssuerCrypto(), + samlCallback.isSendKeyValue(), + samlCallback.getCanonicalizationAlgorithm(), + samlCallback.getSignatureAlgorithm() + ); + } + + String assertion = samlAssertion.assertionToString(); + + String encodedAssertion = Base64UrlUtility.encode(assertion); + + Map<String, String> extraParams = new HashMap<String, String>(); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_SAML2_BEARER); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodedAssertion); + + try { + OAuthClientUtils.getAccessToken(wc, new CustomGrant(), extraParams); + fail("Failure expected on a bad subject name"); + } catch (OAuthServiceException ex) { + // expected + } + } + + @Test + public void testSAMLUnsigned() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2-auth/token"; + WebClient wc = createWebClient(address); + + String audienceURI = "https://localhost:" + PORT + "/oauth2-auth/token"; + String assertion = createToken(audienceURI, true, false); + String encodedAssertion = Base64UrlUtility.encode(assertion); + + Map<String, String> extraParams = new HashMap<String, String>(); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_SAML2_BEARER); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodedAssertion); + + try { + OAuthClientUtils.getAccessToken(wc, new CustomGrant(), extraParams); + fail("Failure expected on an unsigned token"); + } catch (Exception ex) { + // expected + } + } + + @Test + public void testSAMLHolderOfKey() throws Exception { + String address = "https://localhost:" + PORT + "/oauth2-auth/token"; + WebClient wc = createWebClient(address); + + String audienceURI = "https://localhost:" + PORT + "/oauth2-auth/token"; + + // Create the SAML Assertion + SamlCallbackHandler samlCallbackHandler = new SamlCallbackHandler(true); + samlCallbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY); + samlCallbackHandler.setSubjectName("alice"); + samlCallbackHandler.setAudience(audienceURI); + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback); + + SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback); + if (samlCallback.isSignAssertion()) { + samlAssertion.signAssertion( + samlCallback.getIssuerKeyName(), + samlCallback.getIssuerKeyPassword(), + samlCallback.getIssuerCrypto(), + samlCallback.isSendKeyValue(), + samlCallback.getCanonicalizationAlgorithm(), + samlCallback.getSignatureAlgorithm() + ); + } + + String assertion = samlAssertion.assertionToString(); + + String encodedAssertion = Base64UrlUtility.encode(assertion); + + Map<String, String> extraParams = new HashMap<String, String>(); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_TYPE, Constants.CLIENT_AUTH_SAML2_BEARER); + extraParams.put(Constants.CLIENT_AUTH_ASSERTION_PARAM, encodedAssertion); + + try { + OAuthClientUtils.getAccessToken(wc, new CustomGrant(), extraParams); + fail("Failure expected on a bad subject confirmation method"); + } catch (OAuthServiceException ex) { + // expected + } + } + +>>>>>>> 706ddbc... Adding negative tests for SAML authentication in OAuth private WebClient createWebClient(String address) { JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean(); bean.setAddress(address); @@ -166,6 +369,78 @@ public class JAXRSOAuth2Test extends AbstractBusClientServerTestBase { return wc; } +<<<<<<< HEAD +======= + private String createToken(String audRestr, boolean saml2, boolean sign) throws WSSecurityException { + SamlCallbackHandler samlCallbackHandler = new SamlCallbackHandler(sign); + samlCallbackHandler.setAudience(audRestr); + if (!saml2) { + samlCallbackHandler.setSaml2(false); + samlCallbackHandler.setConfirmationMethod(SAML1Constants.CONF_BEARER); + } + + SAMLCallback samlCallback = new SAMLCallback(); + SAMLUtil.doSAMLCallback(samlCallbackHandler, samlCallback); + + SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback); + if (samlCallback.isSignAssertion()) { + samlAssertion.signAssertion( + samlCallback.getIssuerKeyName(), + samlCallback.getIssuerKeyPassword(), + samlCallback.getIssuerCrypto(), + samlCallback.isSendKeyValue(), + samlCallback.getCanonicalizationAlgorithm(), + samlCallback.getSignatureAlgorithm() + ); + } + + return samlAssertion.assertionToString(); + } + + private String createToken(String issuer, String subject, String audience, + boolean expiry, boolean sign) { + // Create the JWT Token + JwtClaims claims = new JwtClaims(); + claims.setSubject(subject); + if (issuer != null) { + claims.setIssuer(issuer); + } + claims.setIssuedAt(new Date().getTime() / 1000L); + if (expiry) { + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.SECOND, 60); + claims.setExpiryTime(cal.getTimeInMillis() / 1000L); + } + if (audience != null) { + claims.setAudiences(Collections.singletonList(audience)); + } + + if (sign) { + // Sign the JWT Token + Properties signingProperties = new Properties(); + signingProperties.put("rs.security.keystore.type", "jks"); + signingProperties.put("rs.security.keystore.password", "password"); + signingProperties.put("rs.security.keystore.alias", "alice"); + signingProperties.put("rs.security.keystore.file", + "org/apache/cxf/systest/jaxrs/security/certs/alice.jks"); + signingProperties.put("rs.security.key.password", "password"); + signingProperties.put("rs.security.signature.algorithm", "RS256"); + + JwsHeaders jwsHeaders = new JwsHeaders(signingProperties); + JwsJwtCompactProducer jws = new JwsJwtCompactProducer(jwsHeaders, claims); + + JwsSignatureProvider sigProvider = + JwsUtils.loadSignatureProvider(signingProperties, jwsHeaders); + + return jws.signWith(sigProvider); + } + + JwsHeaders jwsHeaders = new JwsHeaders(SignatureAlgorithm.NONE); + JwsJwtCompactProducer jws = new JwsJwtCompactProducer(jwsHeaders, claims); + return jws.getSignedEncodedJws(); + } + +>>>>>>> 706ddbc... Adding negative tests for SAML authentication in OAuth private static class CustomGrant implements AccessTokenGrant { private static final long serialVersionUID = -4007538779198315873L; http://git-wip-us.apache.org/repos/asf/cxf/blob/87c7e02a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/SamlCallbackHandler.java ---------------------------------------------------------------------- diff --git a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/SamlCallbackHandler.java b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/SamlCallbackHandler.java index f383c1e..154d31d 100644 --- a/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/SamlCallbackHandler.java +++ b/systests/rs-security/src/test/java/org/apache/cxf/systest/jaxrs/security/oauth2/SamlCallbackHandler.java @@ -62,6 +62,7 @@ public class SamlCallbackHandler implements CallbackHandler { private String cryptoPropertiesFile = "org/apache/cxf/systest/jaxrs/security/alice.properties"; private String issuerKeyName = "alice"; private String issuerKeyPassword = "password"; + private String subjectName = "alice"; public SamlCallbackHandler(boolean signAssertion) { this.signAssertion = signAssertion; @@ -80,14 +81,14 @@ public class SamlCallbackHandler implements CallbackHandler { } callback.setIssuer(issuer); - String subjectName = m != null ? (String)m.getContextualProperty("saml.subject.name") : null; - if (subjectName == null) { - subjectName = "alice"; + String subject = m != null ? (String)m.getContextualProperty("saml.subject.name") : null; + if (subject == null) { + subject = subjectName; } String subjectQualifier = "www.mock-sts.com"; SubjectBean subjectBean = new SubjectBean( - subjectName, subjectQualifier, confirmationMethod + subject, subjectQualifier, confirmationMethod ); callback.setSubject(subjectBean); @@ -219,5 +220,13 @@ public class SamlCallbackHandler implements CallbackHandler { public void setSaml2(boolean saml2) { this.saml2 = saml2; } + + public String getSubjectName() { + return subjectName; + } + + public void setSubjectName(String subjectName) { + this.subjectName = subjectName; + } }