Skip to content
This repository has been archived by the owner on Jun 16, 2021. It is now read-only.

More Okta updates to TCK #330

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,6 @@ class CookieIT extends AbstractIT {
} else {
assertTrue accessTokenCookie.maxAge * 1000L + now - accessTokenTtl < 2000
}

def refreshTokenCookie = response.detailedCookies.get("refresh_token")
def refreshTokenTtl = JwtUtils.parseJwt(refreshTokenCookie.value).getBody().getExpiration().time
// some integrations use max-age and some use expires
if (refreshTokenCookie.expiryDate) {
assertEquals refreshTokenCookie.expiryDate.time, refreshTokenTtl
} else {
assertTrue refreshTokenCookie.maxAge * 1000L + now - refreshTokenTtl < 2000
}
}

/** Passing refresh token as access token should fail
Expand Down
3 changes: 2 additions & 1 deletion src/main/groovy/com/stormpath/tck/errors/ErrorsIT.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.testng.annotations.Test
import static com.jayway.restassured.RestAssured.given
import static com.stormpath.tck.util.FrameworkConstants.MeRoute
import static com.stormpath.tck.util.FrameworkConstants.MissingRoute
import static org.hamcrest.core.StringStartsWith.startsWith;

class ErrorsIT extends AbstractIT {

Expand Down Expand Up @@ -52,6 +53,6 @@ class ErrorsIT extends AbstractIT {
.then()
.statusCode(401)
// 401 with Accept JSON header does not return JSON
.header("WWW-Authenticate", "Bearer realm=\"My Application\"")
.header("WWW-Authenticate", startsWith("Bearer"))
}
}
10 changes: 5 additions & 5 deletions src/main/groovy/com/stormpath/tck/forgot/ChangePasswordIT.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,14 @@ class ChangePasswordIT extends AbstractIT {
deleteOnClassTeardown(account.href)

given()
.body([email: account.email])
.contentType(ContentType.URLENC)
.param("email", account.email)
.when()
.post(ForgotRoute)
.then()
.statusCode(200)

// TODO - will need to make this configurable for Okta
String rawChangePasswordEmail = account.getEmail("stormpath.com")
String rawChangePasswordEmail = account.getEmail("okta.com")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cannot be hard coded, the tests work against both stormpath and okta (and if sending verification emails through a non-okta domain the from from may be different) i.e. google forces the 'from' field to the sender.
(I hacked up a fix for this yesterday before seeing your PR

String changePasswordHref = StringUtils.extractChangePasswordHref(rawChangePasswordEmail, "sptoken")

def response = given()
Expand Down Expand Up @@ -229,14 +229,14 @@ class ChangePasswordIT extends AbstractIT {
deleteOnClassTeardown(account.href)

given()
.contentType(ContentType.JSON)
.body([email: account.email])
.when()
.post(ForgotRoute)
.then()
.statusCode(200)

// TODO - will need to make this configurable for Okta
String rawChangePasswordEmail = account.getEmail("stormpath.com")
String rawChangePasswordEmail = account.getEmail("okta.com")
String changePasswordHref = StringUtils.extractChangePasswordHref(rawChangePasswordEmail, "sptoken")
String sptoken = StringUtils.extractTokenFromHref(changePasswordHref, "sptoken")

Expand Down
8 changes: 4 additions & 4 deletions src/main/groovy/com/stormpath/tck/oauth2/Oauth2IT.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class Oauth2IT extends AbstractIT {
.extract()
.path("access_token")

assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.href)
assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.email)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be an href || email check ?

}

/** Password grant flow with username/password and access_token cookie present
Expand Down Expand Up @@ -156,7 +156,7 @@ class Oauth2IT extends AbstractIT {
.extract()
.path("access_token")
// @formatter:on
assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.href)
assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.email)
}

/** Password grant flow with email/password
Expand All @@ -178,7 +178,7 @@ class Oauth2IT extends AbstractIT {
.extract()
.path("access_token")

assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.href)
assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.email)
}

/** Refresh grant flow
Expand Down Expand Up @@ -215,7 +215,7 @@ class Oauth2IT extends AbstractIT {
.path("access_token")

assertNotEquals(accessToken, newAccessToken, "The new access token should not equal to the old access token")
assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.href, "The access token should be a valid jwt for the test user")
assertTrue(JwtUtils.extractJwtClaim(accessToken, "sub") == account.email, "The access token should be a valid jwt for the test user")
}

/** Refresh grant flow should fail without valid refresh token
Expand Down
11 changes: 7 additions & 4 deletions src/main/groovy/com/stormpath/tck/util/EnvUtils.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ class EnvUtils {

public static final String stormpathHtmlEnabled = getVal("STORMPATH_TCK_HTML_ENABLED", "true")

public static final String jwtSigningKey
public static final String facebookClientId
public static final String facebookClientSecret

public static final String jwtSigningKeyModulus
public static final String jwtSigningKeyExponent

static {
jwtSigningKey = getVal("JWT_SIGNING_KEY")
jwtSigningKeyModulus = getVal("JWT_SIGNING_KEY_MOD")
jwtSigningKeyExponent = getVal("JWT_SIGNING_KEY_EXP")
facebookClientId = getVal("FACEBOOK_CLIENT_ID")
facebookClientSecret = getVal("FACEBOOK_CLIENT_SECRET")
if (jwtSigningKey == null || facebookClientId == null || facebookClientSecret == null) {
fail("JWT_SIGNING_KEY, FACEBOOK_CLIENT_ID and FACEBOOK_CLIENT_SECRET environment variables are required")
if (jwtSigningKeyModulus == null || jwtSigningKeyExponent == null || facebookClientId == null || facebookClientSecret == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably allow setting both. Or we could just set the keys endpoint and download the keys as needed?

fail("JWT_SIGNING_KEY_MOD, JWT_SIGNING_KEY_EXP, FACEBOOK_CLIENT_ID and FACEBOOK_CLIENT_SECRET environment variables are required. The JWT signing key modulus (n) and exponent (e) can be found at https://<your-org>.oktapreview.com/oauth2/<authServerId>/v1/keys")
}
}

Expand Down
15 changes: 11 additions & 4 deletions src/main/groovy/com/stormpath/tck/util/JwtUtils.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,23 @@ import io.jsonwebtoken.Claims
import io.jsonwebtoken.Jws
import io.jsonwebtoken.Jwts

import java.security.Key
import java.security.KeyFactory
import java.security.spec.RSAPublicKeySpec

class JwtUtils {
static Key getPublicKey() {
def modulus = new BigInteger(1, Base64.getUrlDecoder().decode(EnvUtils.jwtSigningKeyModulus))
def exponent = new BigInteger(1, Base64.getUrlDecoder().decode(EnvUtils.jwtSigningKeyExponent))
return KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent))
}

static String extractJwtClaim(String jwt, String property) {
String secret = EnvUtils.jwtSigningKey
Claims claims = Jwts.parser().setSigningKey(secret.getBytes()).parseClaimsJws(jwt).getBody()
Claims claims = Jwts.parser().setSigningKey(getPublicKey()).parseClaimsJws(jwt).getBody()
return (String) claims.get(property)
}

static Jws<Claims> parseJwt(String jwt) {
String secret = EnvUtils.jwtSigningKey
return Jwts.parser().setSigningKey(secret.getBytes()).parseClaimsJws(jwt)
return Jwts.parser().setSigningKey(getPublicKey()).parseClaimsJws(jwt)
}
}
4 changes: 3 additions & 1 deletion src/main/groovy/com/stormpath/tck/util/TestAccount.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.jayway.restassured.http.ContentType

import static com.jayway.restassured.RestAssured.get
import static com.jayway.restassured.RestAssured.given
Expand Down Expand Up @@ -62,6 +63,7 @@ class TestAccount {

void registerOnServer() {
href = given()
.contentType(ContentType.JSON)
.body(getPropertiesMap())
.when()
.post(RegisterRoute)
Expand Down Expand Up @@ -97,7 +99,7 @@ class TestAccount {
String emailId = null
int count = 0

while (emailId == null && count++ < 30) {
while (emailId == null && count++ < 90) {
def jsonResponse =
get(GUERILLA_MAIL_BASE + "?f=get_email_list&offset=0&sid_token=" + guerillaEmail.getToken()).asString()

Expand Down