Skip to content

Commit

Permalink
Merge b71ea26 into 66257b7
Browse files Browse the repository at this point in the history
  • Loading branch information
pcmxgti committed Dec 1, 2023
2 parents 66257b7 + b71ea26 commit 2ae32ad
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 28 deletions.
9 changes: 8 additions & 1 deletion tests/unit/test_okta.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,9 @@ def test_create_authz_cookies():
"org": "acme",
"authorization_endpoint": "pytesturl",
"token_endpoint": "tokeneurl",
"nonce": "pytest",
"issuer": "pytest",
"ln": "pytest",
}
assert okta.create_authz_cookies(pytest_oauth2_config, pytest_oauth2_session_data) is None
from tokendito import okta
Expand Down Expand Up @@ -708,7 +711,9 @@ def test_get_oauth2_configuration(mocker):
"grant_types_supported": "authorization_code",
"request_parameter_supported": "pytest",
}
pytest_config = Config(okta={"client_id": "test_client_id", "org": "acme"})
pytest_config = Config(
okta={"client_id": "test_client_id", "org": "acme", "username": "pytest"}
)
mocker.patch.object(HTTP_client, "get", return_value=response)
assert okta.get_oauth2_configuration(pytest_config)["org"] == "acme"

Expand Down Expand Up @@ -739,6 +744,8 @@ def test_validate_oauth2_configuration():
"scopes_supported": "pytest",
"response_types_supported": "code",
"request_parameter_supported": "pytest",
"ln": "pytest",
"nonce": "pytest",
}
assert okta.validate_oauth2_configuration(pytest_oauth2_config) is None

Expand Down
69 changes: 42 additions & 27 deletions tokendito/okta.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import re
import sys
import time
from urllib.parse import urlencode
from urllib.parse import quote
from urllib.parse import urlparse

import bs4
Expand Down Expand Up @@ -149,7 +149,6 @@ def send_saml_request(saml_request):
Submit SAML request to IdP, and get the response back.
:param saml_request: dict with IdP post_url, relay_state, and saml_request
:param cookies: session cookies with `sid`
:returns: dict with with SP post_url, relay_state, and saml_response
"""
# Define the payload and headers for the request
Expand Down Expand Up @@ -194,20 +193,33 @@ def create_authz_cookies(oauth2_config, oauth2_session_data):
Needed for SAML2 flow for OIE.
"""
session_token = HTTP_client.session.cookies.get("sessionToken")
try:
oauth2_url = f"{oauth2_config['org']}/oauth2/v1"
oauth2_config_reformatted = {
"responseType": "code",
"state": oauth2_session_data["state"],
"nonce": oauth2_config["nonce"],
"scopes": [
"openid",
"profile",
"email",
"okta.users.read.self",
"okta.users.manage.self",
"okta.internal.enduser.read",
"okta.internal.enduser.manage",
"okta.enduser.dashboard.read",
"okta.enduser.dashboard.manage",
],
"clientId": oauth2_config["client_id"],
"authorizeUrl": oauth2_config["authorization_endpoint"],
"tokenUrl": oauth2_config["token_endpoint"],
"scope": "openid",
"sessionToken": session_token,
"userInfoUrl": f"{oauth2_url}/userinfo",
"revokeUrl": f"{oauth2_url}/revoke",
"logoutUrl": f"{oauth2_url}/logout",
"urls": {
"issuer": oauth2_config["issuer"],
"authorizeUrl": oauth2_config["authorization_endpoint"],
"userInfoUrl": f"{oauth2_url}/userinfo",
"tokenUrl": oauth2_config["token_endpoint"],
"revokeUrl": f"{oauth2_url}/revoke",
"logoutUrl": f"{oauth2_url}/logout",
},
"ignoreSignature": False,
}
except KeyError as e:
logger.error(f"Missing key in config:{e}")
Expand All @@ -217,11 +229,13 @@ def create_authz_cookies(oauth2_config, oauth2_session_data):
domain = urlparse(oauth2_config["org"]).netloc
cookiejar.set(
"okta-oauth-redirect-params",
f"{{{urlencode(oauth2_config_reformatted)}}}",
quote(json.dumps(oauth2_config_reformatted, separators=(",", ":")), safe="{}:[]/"),
domain=domain,
path="/",
)
cookiejar.set("okta-oauth-state", oauth2_session_data["state"], domain=domain, path="/")
cookiejar.set("okta-oauth-nonce", oauth2_config["nonce"], domain=domain, path="/")
cookiejar.set("ln", oauth2_config["ln"], domain=domain, path="/")
HTTP_client.add_cookies(cookiejar) # add cookies


Expand All @@ -242,7 +256,6 @@ def send_saml_response(config, saml_response):
}
url = saml_response["post_url"]

logger.debug(f"{base64.b64decode(saml_response['response'])}")
# Log the SAML response details.
logger.debug(f"Sending SAML response to {url}")
# Use the HTTP client to make a POST request.
Expand All @@ -264,20 +277,18 @@ def send_saml_response(config, saml_response):
params = {"stateToken": state_token}
headers = {
"accept": "text/html,application/xhtml+xml,application/xml",
"content-type": "application/json",
}
response = HTTP_client.get(
# myurl, allow_redirects=False, params={"stateToken": state_token}
f"{config.okta['org']}/login/token/redirect",
params=params,
headers=headers,
)
logger.warning(
f"""
State token from {url}: {state_token}. TODO: need to go from this state token
to an idx cookies.
"""
)
if "idx" not in response.cookies:
logger.error(
f"Session cookie idx for {config.okta['org']} not found. Please file a bug."
)
logger.debug(f"Response: {response.text}")
sys.exit(2)


def get_session_token(config, primary_auth, headers):
Expand Down Expand Up @@ -595,6 +606,8 @@ def get_oauth2_configuration(config):
oauth2_config = response.json()
oauth2_config["org"] = config.okta["org"]
oauth2_config["client_id"] = get_client_id(config)
oauth2_config["ln"] = config.okta["username"]
oauth2_config["nonce"] = "TODO"
validate_oauth2_configuration(oauth2_config)
return oauth2_config

Expand All @@ -614,6 +627,8 @@ def validate_oauth2_configuration(oauth2_config):
"scopes_supported",
"client_id",
"org",
"ln",
"nonce",
} # the authorization server must have these config elements
for item in mandadory_oauth2_config_items:
if item not in oauth2_config:
Expand Down Expand Up @@ -676,15 +691,15 @@ def idp_authenticate(config):
logger.error("Okta auth failed: unknown type.")
sys.exit(1)

if is_saml2_authentication(auth_properties):
# We may loop thru the saml2 servers until
# we find the authentication server.
saml2_authenticate(config, auth_properties)
elif local_authentication_enabled(auth_properties):
if local_authentication_enabled(auth_properties):
session_token = local_authenticate(config)
# authentication sends us a token
# which we then put in our session cookies
create_authn_cookies(config.okta["org"], session_token)
elif is_saml2_authentication(auth_properties):
# We may loop thru the saml2 servers until
# we find the authentication server.
saml2_authenticate(config, auth_properties)
else:
logger.error(f"{auth_properties['type']} login via IdP Discovery is not curretly supported")
sys.exit(1)
Expand Down Expand Up @@ -714,8 +729,8 @@ def access_control(config):
oauth2_config = get_oauth2_configuration(config)
oauth2_session_data = generate_oauth2_session_data(config.okta["org"])
create_authz_cookies(oauth2_config, oauth2_session_data)
# The flow says to initially call /authorize here, but that doesnt do anything...
# idp_authorize(oauth2_config, oauth2_session_data)
# The flow says to initially call /authorize here, but that doesnt do anything.
# We call it later, after we are authenticated.

idp_authenticate(config)

Expand Down

0 comments on commit 2ae32ad

Please sign in to comment.