Skip to content

Commit

Permalink
[SDK-4400] Support Organization Name on Authorize URL (#550)
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmyjames authored Jul 18, 2023
1 parent 084187e commit 553c156
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public AuthorizeUrlBuilder withResponseType(String responseType) {
/**
* Sets the organization query string parameter value used to login to an organization.
*
* @param organization The ID of the organization to log the user in to.
* @param organization The ID or name of the organization to log the user in to.
* @return the builder instance.
*/
public AuthorizeUrlBuilder withOrganization(String organization) {
Expand Down
26 changes: 19 additions & 7 deletions src/main/java/com/auth0/utils/tokens/IdTokenVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,26 @@ public void verify(String token, String nonce, Integer maxAuthenticationAge) thr

// Org verification
if (this.organization != null) {
String orgClaim = decoded.getClaim("org_id").asString();
if (isEmpty(orgClaim)) {
throw new IdTokenValidationException("Organization Id (org_id) claim must be a string present in the ID token");
String org = this.organization.trim();
if (org.startsWith("org_")) {
// org ID
String orgClaim = decoded.getClaim("org_id").asString();
if (isEmpty(orgClaim)) {
throw new IdTokenValidationException("Organization Id (org_id) claim must be a string present in the ID token");
}
if (!this.organization.equals(orgClaim)) {
throw new IdTokenValidationException(String.format("Organization (org_id) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", this.organization, orgClaim));
}
} else {
// org name
String orgNameClaim = decoded.getClaim("org_name").asString();
if (isEmpty(orgNameClaim)) {
throw new IdTokenValidationException("Organization name (org_name) claim must be a string present in the ID token");
}
if (!org.toLowerCase().equals(orgNameClaim)) {
throw new IdTokenValidationException(String.format("Organization (org_name) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", this.organization, orgNameClaim));
}
}
if (!this.organization.equals(orgClaim)) {
throw new IdTokenValidationException(String.format("Organization (org_id) claim mismatch in the ID token; expected \"%s\" but found \"%s\"", this.organization, orgClaim));
}

}

final Calendar cal = Calendar.getInstance();
Expand Down
144 changes: 132 additions & 12 deletions src/test/java/com/auth0/utils/tokens/IdTokenVerifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,87 @@ public void succeedsWithValidTokenUsingDefaultClockAndHttpsDomain() {
}

@Test
public void succeedsWhenOrganizationMatchesExpected() {
public void succeedsWhenOrganizationNamdMatchesExpected() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
.withIssuedAt(getYesterday())
.withExpiresAt(getTomorrow())
.withIssuer("https://" + DOMAIN + "/")
.withClaim("org_name", "my org")
.sign(Algorithm.HMAC256("secret"));

String jwt = JWT.decode(token).getToken();

configureVerifier(jwt)
.withOrganization("my org")
.build()
.verify(jwt);
}

@Test
public void failsWhenOrganizationNameDoesNotMatchExpected() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
.withIssuedAt(getYesterday())
.withExpiresAt(getTomorrow())
.withIssuer("https://" + DOMAIN + "/")
.withClaim("org_name", "my org")
.sign(Algorithm.HMAC256("secret"));

String jwt = JWT.decode(token).getToken();

AssertsUtil.verifyThrows(IdTokenValidationException.class,
() -> configureVerifier(jwt)
.withOrganization("your org")
.build()
.verify(jwt),
"Organization (org_name) claim mismatch in the ID token; expected \"your org\" but found \"my org\"");
}

@Test
public void failsWhenOrganizationNameExpectedButClaimIsNotString() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
.withIssuedAt(getYesterday())
.withExpiresAt(getTomorrow())
.withIssuer("https://" + DOMAIN + "/")
.withClaim("org_name", 42)
.sign(Algorithm.HMAC256("secret"));

String jwt = JWT.decode(token).getToken();

AssertsUtil.verifyThrows(IdTokenValidationException.class, () -> {
configureVerifier(jwt)
.withOrganization("my org")
.build()
.verify(jwt);
},
"Organization name (org_name) claim must be a string present in the ID token");
}

@Test
public void succeedsWhenOrganizationNameNotSpecifiedButIsPresent() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
.withIssuedAt(getYesterday())
.withExpiresAt(getTomorrow())
.withIssuer("https://" + DOMAIN + "/")
.withClaim("org_name", "my org")
.sign(Algorithm.HMAC256("secret"));

String jwt = JWT.decode(token).getToken();

configureVerifier(jwt)
.build()
.verify(jwt);
}

@Test
public void succeedsWhenOrganizationIdMatchesExpected() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
Expand All @@ -439,7 +519,7 @@ public void succeedsWhenOrganizationMatchesExpected() {
}

@Test
public void failsWhenOrganizationDoesNotMatchExpected() {
public void failsWhenOrganizationIdDoesNotMatchExpected() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
Expand All @@ -453,34 +533,74 @@ public void failsWhenOrganizationDoesNotMatchExpected() {

AssertsUtil.verifyThrows(IdTokenValidationException.class,
() -> configureVerifier(jwt)
.withOrganization("org_abc")
.build()
.verify(jwt),
.withOrganization("org_abc")
.build()
.verify(jwt),
"Organization (org_id) claim mismatch in the ID token; expected \"org_abc\" but found \"org_123\"");
}

@Test
public void failsWhenOrganizationExpectedButNotPresent() {
public void failsWhenOrganizationIdDoesNotMatchExpected_caseSensitive() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
.withIssuedAt(getYesterday())
.withExpiresAt(getTomorrow())
.withIssuer("https://" + DOMAIN + "/")
.withClaim("org_id", "oRg_123")
.sign(Algorithm.HMAC256("secret"));

String jwt = JWT.decode(token).getToken();

AssertsUtil.verifyThrows(IdTokenValidationException.class,
() -> configureVerifier(jwt)
.withOrganization("org_123")
.build()
.verify(jwt),
.withOrganization("org_123")
.build()
.verify(jwt),
"Organization (org_id) claim mismatch in the ID token; expected \"org_123\" but found \"oRg_123\"");
}

@Test
public void failsWhenOrganizationIdExpectedButNotPresent() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
.withIssuedAt(getYesterday())
.withExpiresAt(getTomorrow())
.withIssuer("https://" + DOMAIN + "/")
.sign(Algorithm.HMAC256("secret"));

String jwt = JWT.decode(token).getToken();

AssertsUtil.verifyThrows(IdTokenValidationException.class,
() -> configureVerifier(jwt)
.withOrganization("org_123")
.build()
.verify(jwt),
"Organization Id (org_id) claim must be a string present in the ID token");
}

@Test
public void failsWhenOrganizationExpectedButClaimIsNotString() {
public void succeedsWhenOrganizationNameDoesNotMatchExpected_caseInsensitive() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
.withIssuedAt(getYesterday())
.withExpiresAt(getTomorrow())
.withIssuer("https://" + DOMAIN + "/")
.withClaim("org_name", "my org")
.sign(Algorithm.HMAC256("secret"));

String jwt = JWT.decode(token).getToken();

configureVerifier(jwt)
.withOrganization("My org")
.build()
.verify(jwt);
}

@Test
public void failsWhenOrganizationIdExpectedButClaimIsNotString() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
Expand All @@ -497,12 +617,12 @@ public void failsWhenOrganizationExpectedButClaimIsNotString() {
.withOrganization("org_123")
.build()
.verify(jwt);
},
},
"Organization Id (org_id) claim must be a string present in the ID token");
}

@Test
public void succeedsWhenOrganizationNotSpecifiedButIsPresent() {
public void succeedsWhenOrganizationIdNotSpecifiedButIsPresent() {
String token = JWT.create()
.withSubject("auth0|sdk458fks")
.withAudience(AUDIENCE)
Expand Down

0 comments on commit 553c156

Please sign in to comment.