Skip to content

Commit

Permalink
Tests for Facebook OAuth login
Browse files Browse the repository at this point in the history
[#146687605] https://www.pivotaltracker.com/story/show/146687605

Signed-off-by: Filip Hanik <fhanik@pivotal.io>
  • Loading branch information
Bharath Sekar authored and pivotal committed Aug 11, 2017
1 parent 3e88b36 commit 467377c
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 20 deletions.
Expand Up @@ -29,6 +29,7 @@
import org.cloudfoundry.identity.uaa.oauth.jwk.JsonWebKeyHelper;
import org.cloudfoundry.identity.uaa.oauth.jwk.JsonWebKeySet;
import org.cloudfoundry.identity.uaa.oauth.jwt.ChainedSignatureVerifier;
import org.cloudfoundry.identity.uaa.oauth.jwt.CommonSigner;
import org.cloudfoundry.identity.uaa.oauth.jwt.Jwt;
import org.cloudfoundry.identity.uaa.oauth.jwt.JwtHelper;
import org.cloudfoundry.identity.uaa.oauth.token.ClaimConstants;
Expand All @@ -46,6 +47,7 @@
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.jwt.crypto.sign.Signer;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
Expand All @@ -58,8 +60,6 @@


import java.net.MalformedURLException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -72,7 +72,6 @@
import static org.cloudfoundry.identity.uaa.oauth.jwk.JsonWebKey.KeyType.MAC;
import static org.cloudfoundry.identity.uaa.oauth.jwk.JsonWebKey.KeyType.RSA;
import static org.cloudfoundry.identity.uaa.oauth.token.ClaimConstants.SUB;
import static org.cloudfoundry.identity.uaa.oauth.token.CompositeAccessToken.ID_TOKEN;
import static org.cloudfoundry.identity.uaa.provider.ExternalIdentityProviderDefinition.*;
import static org.cloudfoundry.identity.uaa.util.TokenValidation.validate;
import static org.cloudfoundry.identity.uaa.util.UaaHttpRequestUtils.isAcceptedInvitationAuthentication;
Expand Down Expand Up @@ -387,7 +386,7 @@ public RestTemplate getRestTemplate(AbstractXOAuthIdentityProviderDefinition con
return restTemplateFactory.getRestTemplate(config.isSkipSslValidation());
}

private String getResponseType(AbstractXOAuthIdentityProviderDefinition config) {
protected String getResponseType(AbstractXOAuthIdentityProviderDefinition config) {
if (RawXOAuthIdentityProviderDefinition.class.isAssignableFrom(config.getClass())) {
if ("signed_request".equals(config.getResponseType()))
return "signed_request";
Expand Down Expand Up @@ -433,7 +432,7 @@ protected Map<String, Object> getClaimsFromToken(String idToken,
return null;
}
//check if data is signed correctly
if(!hmacSHA256(signedRequests[1], secret).equals(signature)) {
if(!hmacSignAndEncode(signedRequests[1], secret).equals(signature)) {
logger.debug("Signature is not correct, possibly the data was tampered with! No claims returned.");
return null;
}
Expand All @@ -457,13 +456,9 @@ protected Map<String, Object> getClaimsFromToken(String idToken,
}
}

//HmacSHA256 implementation
private String hmacSHA256(String data, String key) throws Exception {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
byte[] hmacData = mac.doFinal(data.getBytes("UTF-8"));
return new String(Base64.encodeBase64URLSafe(hmacData), "UTF-8");
protected String hmacSignAndEncode(String data, String key) throws Exception {
Signer signer = new CommonSigner("",key);
return new String(Base64.encodeBase64URLSafe(signer.sign(data.getBytes("UTF-8"))), "UTF-8");
}

private TokenValidation validateToken(String idToken, AbstractXOAuthIdentityProviderDefinition config) {
Expand Down Expand Up @@ -536,7 +531,6 @@ private String getTokenFromCode(XOAuthCodeToken codeToken, AbstractXOAuthIdentit
body.add("code", codeToken.getCode());
body.add("redirect_uri", codeToken.getRedirectUrl());

//DRE: Add client_id and secret for Salesforce
logger.debug("Adding new client_id and client_secret for token exchange");
body.add("client_id", config.getRelyingPartyId());
body.add("client_secret", config.getRelyingPartySecret());
Expand Down Expand Up @@ -574,7 +568,6 @@ private String getTokenFromCode(XOAuthCodeToken codeToken, AbstractXOAuthIdentit
}
);
logger.debug(String.format("Request completed with status:%s", responseEntity.getStatusCode()));
//DRE: Read proper field from response depending on configuration (id_token, signed_request etc)
return responseEntity.getBody().get(getResponseType(config));
} catch (HttpServerErrorException | HttpClientErrorException ex) {
throw ex;
Expand Down
Expand Up @@ -36,6 +36,7 @@
import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning;
import org.cloudfoundry.identity.uaa.provider.OIDCIdentityProviderDefinition;
import org.cloudfoundry.identity.uaa.provider.RawXOAuthIdentityProviderDefinition;
import org.cloudfoundry.identity.uaa.user.*;
import org.cloudfoundry.identity.uaa.util.JsonUtils;
import org.cloudfoundry.identity.uaa.util.RestTemplateFactory;
Expand Down Expand Up @@ -72,6 +73,8 @@
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Instant;
Expand Down Expand Up @@ -271,6 +274,41 @@ public void run() {
}
}

@Test
public void get_response_type_for_oauth2() {
RawXOAuthIdentityProviderDefinition signed = new RawXOAuthIdentityProviderDefinition();
signed.setResponseType("signed_request");
RawXOAuthIdentityProviderDefinition token = new RawXOAuthIdentityProviderDefinition();
OIDCIdentityProviderDefinition oidcIdentityProviderDefinition = new OIDCIdentityProviderDefinition();

assertEquals("signed_request", xoAuthAuthenticationManager.getResponseType(signed));
assertEquals("token", xoAuthAuthenticationManager.getResponseType(token));
assertEquals("id_token", xoAuthAuthenticationManager.getResponseType(oidcIdentityProviderDefinition));
}

@Test
public void unknown_config_class() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Unknown type for provider.");

xoAuthAuthenticationManager.getResponseType(new AbstractXOAuthIdentityProviderDefinition() {
@Override
public URL getAuthUrl() {
return super.getAuthUrl();
}
});
}

@Test
public void verify_hmac_256_signature() throws Exception {
String key = "key";
String data = "data";
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
byte[] hmacData = mac.doFinal(data.getBytes("UTF-8"));
assertThat(new String(Base64.encodeBase64URLSafe(hmacData)), equalTo(xoAuthAuthenticationManager.hmacSignAndEncode(data, key)));
}

@Test
public void race_condition_in_get_auth_details() throws Exception {
Expand Down
Expand Up @@ -33,7 +33,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.oauth2.client.test.TestAccounts;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestOperations;
Expand Down Expand Up @@ -97,6 +96,7 @@ public void setUp() throws Exception {
config.setRelyingPartySecret("2a5114552531768058add1f8f5a6b632");
config.setTokenKey("2a5114552531768058add1f8f5a6b632");
config.setResponseType("signed_request");
config.addAttributeMapping("user_name", "user_id");

identityProvider = new IdentityProvider<>();
identityProvider.setName("facebook provider");
Expand Down Expand Up @@ -136,19 +136,20 @@ public void facebook_login() {
IntegrationTestUtils.validateAccountChooserCookie(baseUrl, webDriver);
}

private void login(String zoneUrl, String userName, String password) {
webDriver.get(zoneUrl + "/logout.do");
webDriver.get(zoneUrl + "/");
private void login(String url, String userName, String password) {
webDriver.get(url + "/logout.do");
webDriver.get(url + "/");
Cookie beforeLogin = webDriver.manage().getCookieNamed("JSESSIONID");
assertNotNull(beforeLogin);
assertNotNull(beforeLogin.getValue());
webDriver.findElement(By.linkText(LINK_TEXT)).click();
Assert.assertThat(webDriver.getCurrentUrl(), Matchers.containsString(baseUrl));
Assert.assertThat(webDriver.getCurrentUrl(), Matchers.containsString("www.facebook.com"));

webDriver.findElement(By.name("email")).sendKeys(userName);
webDriver.findElement(By.name("pass")).sendKeys(password);
webDriver.findElement(By.name("login")).click();
Assert.assertThat(webDriver.getCurrentUrl(), Matchers.containsString(zoneUrl));
Assert.assertThat(webDriver.getCurrentUrl(), Matchers.containsString(url));
IntegrationTestUtils.takeScreenShot(webDriver);
assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), Matchers.containsString("Where to?"));
Cookie afterLogin = webDriver.manage().getCookieNamed("JSESSIONID");
assertNotNull(afterLogin);
Expand Down

0 comments on commit 467377c

Please sign in to comment.