Skip to content

Commit

Permalink
[SDK-4394] Add organization name validation (#507)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamjmcgrath authored Jul 25, 2023
2 parents c5131b6 + 423f9b3 commit 2860768
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 15 deletions.
2 changes: 1 addition & 1 deletion auth0/authentication/async_token_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ async def verify(
token (str): The JWT to verify.
nonce (str, optional): The nonce value sent during authentication.
max_age (int, optional): The max_age value sent during authentication.
organization (str, optional): The expected organization ID (org_id) claim value. This should be specified
organization (str, optional): The expected organization ID (org_id) or orgnization name (org_name) claim value. This should be specified
when logging in to an organization.
Returns:
Expand Down
36 changes: 25 additions & 11 deletions auth0/authentication/token_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def verify(
token (str): The JWT to verify.
nonce (str, optional): The nonce value sent during authentication.
max_age (int, optional): The max_age value sent during authentication.
organization (str, optional): The expected organization ID (org_id) claim value. This should be specified
organization (str, optional): The expected organization ID (org_id) or orgnization name (org_name) claim value. This should be specified
when logging in to an organization.
Returns:
Expand Down Expand Up @@ -402,16 +402,30 @@ def _verify_payload(

# Organization
if organization:
if "org_id" not in payload or not isinstance(payload["org_id"], str):
raise TokenValidationError(
"Organization (org_id) claim must be a string present in the ID"
" token"
)
if payload["org_id"] != organization:
raise TokenValidationError(
"Organization (org_id) claim mismatch in the ID token; expected"
' "{}", found "{}"'.format(organization, payload["org_id"])
)
if organization.startswith("org_"):
if "org_id" not in payload or not isinstance(payload["org_id"], str):
raise TokenValidationError(
"Organization (org_id) claim must be a string present in the ID"
" token"
)
if payload["org_id"] != organization:
raise TokenValidationError(
"Organization (org_id) claim mismatch in the ID token; expected"
' "{}", found "{}"'.format(organization, payload["org_id"])
)
else:
if "org_name" not in payload or not isinstance(
payload["org_name"], str
):
raise TokenValidationError(
"Organization (org_name) claim must be a string present in the ID"
" token"
)
if payload["org_name"] != organization.lower():
raise TokenValidationError(
"Organization (org_name) claim mismatch in the ID token; expected"
' "{}", found "{}"'.format(organization, payload["org_name"])
)

# Authorized party
if isinstance(payload["aud"], list) and len(payload["aud"]) > 1:
Expand Down
47 changes: 44 additions & 3 deletions auth0/test/authentication/test_token_verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,48 @@ def test_passes_when_org_present_and_matches(self):
tv._clock = MOCKED_CLOCK
tv.verify(token, organization="org_123")

def test_fails_when_org_specified_but_not_present(self):
def test_fails_when_org_name_specified_but_not_present(self):
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoMHxzZGs0NThma3MiLCJhdWQiOiJ0b2tlbnMtdGVzdC0xMjMiLCJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJleHAiOjE1ODc3NjUzNjEsImlhdCI6MTU4NzU5MjU2MX0.wotJnUdD5IfdZMewF_-BnHc0pI56uwzwr5qaSXvSu9w"
self.assert_fails_with_error(
token,
"Organization (org_name) claim must be a string present in the ID token",
signature_verifier=SymmetricSignatureVerifier(HMAC_SHARED_SECRET),
organization="org-123",
)

def test_fails_when_org_name_specified_but_not_string(self):
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoMHxzZGs0NThma3MiLCJhdWQiOiJ0b2tlbnMtdGVzdC0xMjMiLCJvcmdfbmFtZSI6NDIsImlzcyI6Imh0dHBzOi8vdG9rZW5zLXRlc3QuYXV0aDAuY29tLyIsImV4cCI6MTU4Nzc2NTM2MSwiaWF0IjoxNTg3NTkyNTYxfQ.RXu-dz1u2pftk_iInk1To8z9g1B6TVA-5FAwoCx85T0"
self.assert_fails_with_error(
token,
"Organization (org_name) claim must be a string present in the ID token",
signature_verifier=SymmetricSignatureVerifier(HMAC_SHARED_SECRET),
organization="org-123",
)

def test_fails_when_org_name_specified_but_does_not_match(self):
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoMHxzZGs0NThma3MiLCJhdWQiOiJ0b2tlbnMtdGVzdC0xMjMiLCJvcmdfbmFtZSI6Im9yZy1hYmMiLCJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJleHAiOjE1ODc3NjUzNjEsImlhdCI6MTU4NzU5MjU2MX0.P_ldJGEaFg58cARwGMtog_KTsqv7cGJZXoS9xdTEkvQ"
self.assert_fails_with_error(
token,
'Organization (org_name) claim mismatch in the ID token; expected "org-123",'
' found "org-abc"',
signature_verifier=SymmetricSignatureVerifier(HMAC_SHARED_SECRET),
organization="org-123",
)

def test_succeeds_when_org_name_specified_matches(self):
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoMHxzZGs0NThma3MiLCJhdWQiOiJ0b2tlbnMtdGVzdC0xMjMiLCJvcmdfbmFtZSI6Im9yZy0xMjMiLCJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJleHAiOjE1ODc3NjUzNjEsImlhdCI6MTU4NzU5MjU2MX0.P8Kba8Fgamyiw1qw_lBfp2OAzWn6NOLL6fBCDQhGvyc"
sv = SymmetricSignatureVerifier(HMAC_SHARED_SECRET)
tv = TokenVerifier(
signature_verifier=sv,
issuer=expectations["issuer"],
audience=expectations["audience"],
)
tv._clock = MOCKED_CLOCK
response = tv.verify(token)
self.assertIn("org_name", response)
self.assertEqual("org-123", response["org_name"])

def test_fails_when_org_id_specified_but_not_present(self):
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoMHxzZGs0NThma3MiLCJhdWQiOiJ0b2tlbnMtdGVzdC0xMjMiLCJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJleHAiOjE1ODc3NjUzNjEsImlhdCI6MTU4NzU5MjU2MX0.wotJnUdD5IfdZMewF_-BnHc0pI56uwzwr5qaSXvSu9w"
self.assert_fails_with_error(
token,
Expand All @@ -515,7 +556,7 @@ def test_fails_when_org_specified_but_not_present(self):
organization="org_123",
)

def test_fails_when_org_specified_but_not_(self):
def test_fails_when_org_id_specified_but_not_string(self):
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoMHxzZGs0NThma3MiLCJhdWQiOiJ0b2tlbnMtdGVzdC0xMjMiLCJvcmdfaWQiOjQyLCJpc3MiOiJodHRwczovL3Rva2Vucy10ZXN0LmF1dGgwLmNvbS8iLCJleHAiOjE1ODc3NjUzNjEsImlhdCI6MTU4NzU5MjU2MX0.fGL1_akaHikdovS7NRYla3flne1xdtCjP0ei_CRxO6k"
self.assert_fails_with_error(
token,
Expand All @@ -524,7 +565,7 @@ def test_fails_when_org_specified_but_not_(self):
organization="org_123",
)

def test_fails_when_org_specified_but_does_not_match(self):
def test_fails_when_org_id_specified_but_does_not_match(self):
token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhdXRoMHxzZGs0NThma3MiLCJhdWQiOiJ0b2tlbnMtdGVzdC0xMjMiLCJvcmdfaWQiOiJvcmdfMTIzIiwiaXNzIjoiaHR0cHM6Ly90b2tlbnMtdGVzdC5hdXRoMC5jb20vIiwiZXhwIjoxNTg3NzY1MzYxLCJpYXQiOjE1ODc1OTI1NjF9.hjSPgJpg0Dn2z0giCdGqVLD5Kmqy_yMYlSkgwKD7ahQ"
self.assert_fails_with_error(
token,
Expand Down

0 comments on commit 2860768

Please sign in to comment.