<?php
###############################################################################
# okta-test.php
#
#
# @author Anil Kumar <akumar@codepunch.com>
# @link   https://codepunch.com
#
############################################################################### 
/*

Rename this file to okta-test.php
Add your client-id, client-secret and okta domain to the three variable below.
Edit the $metadata_url if your organization has a specific custom authorization 
server
Copy the file to a suitable web accessible location.
Add the URL of this file as a Sign-in redirect URI at Okta for the application
Open this URL from a browser

After testing, delete this file from the web accessible folder(Important)

*/
###############################################################################

$client_id = 'your_okta_app_client_id';
$client_secret = 'your_okta_app_client_secret';
$okta_domain = 'your_okta_domain';

$metadata_url = "https://$okta_domain/.well-known/oauth-authorization-server";

###############################################################################

session_start();

###############################################################################

$protocol = 'http';
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on")
	$protocol = 'https';
$my_url = "$protocol://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$redirecturl = strtok($my_url, '?');

###############################################################################

debug_echo("<h1>OKTA SSO Test Utility</h1>");
$md = curl_get_url($metadata_url);
if($md['status'] == 200) {
	$metadata = json_decode($md['result'], true);
}
else if($md['status'] == 404) {
	debug_echo("Page not found: <b>$metadata_url</b>");
	exit;
}
else {
	debug_echo("Unable to get Meta data from Okta");
	debug_echo($md);
	exit;
}

###############################################################################

if(isset($_REQUEST['code'])) {
	debug_echo("✅ Received authorization code from OKTA");
	debug_echo("Okta Code: <b>" . $_REQUEST['code'] . "</b>");
	debug_echo("<h3>3️⃣ Requesting Access Token</h3>");
	$postdata = [
		'grant_type' => 'authorization_code',
		'code' => $_GET['code'],
		'redirect_uri' => $redirecturl,
		'client_id' => $client_id,
		'client_secret' => "*****************"
	];
	debug_echo("✅ Constructed POST data");
	debug_echo($postdata);
	$postdata['client_secret'] = $client_secret;
	
	debug_echo("➡️ Posting to token endpoint URL");
	$response = curl_post_url($metadata['token_endpoint'], 10, false, false, $postdata);
	if($response['status'] == 200) {
		$response = json_decode($response['result'], true);
		$access_token = $response['access_token'];
		debug_echo("✅ Received Access Token");
		debug_echo("Access Token: <b>" . $access_token . "</b>");
		debug_echo("<h3>4️⃣ Requesting Access Details</h3>");
		debug_echo("➡️ Posting to introspection endpoint URL");
		$token = curl_post_url($metadata['introspection_endpoint'], 10, false, false, [
			'token' => $access_token,
			'client_id' => $client_id,
			'client_secret' => $client_secret,
		]);
		if($token['status'] == 200) {
			$token = json_decode($token['result'], true);
			debug_echo("✅ Received Access Details");
			debug_echo($token);
		}
		else {
			debug_echo($response);
		}
	}
	else {
		debug_echo($response);
	}
	exit;
}

###############################################################################

debug_echo("Redirect URI: <b>" . $redirecturl . "</b>");
debug_echo("<h3>1️⃣ Requesting Okta Meta Data</h3>");
debug_echo("➡️ Getting $metadata_url");
if($md['status'] == 200) {
	debug_echo('✅ Meta data obtained successfully');
	
	debug_echo('Authorization Endpoint: ' . $metadata['authorization_endpoint']);
	debug_echo('Token Endpoint: ' . $metadata['token_endpoint']);
	debug_echo('Introspection Endpoint: ' . $metadata['introspection_endpoint']);
	$_SESSION['state'] = bin2hex(random_bytes(5));
	$authorize_url = $metadata['authorization_endpoint'].'?'.http_build_query([
		'response_type' => 'code',
		'client_id' => $client_id,
		'redirect_uri' => $redirecturl,
		'state' => $_SESSION['state'],
		'scope' => 'openid',
	]);
	
	debug_echo('✅ Constructed Authorization URL');
	debug_echo("Authorization URL: <b>$authorize_url</b>");

	debug_echo("<h3>2️⃣ Requesting OKTA Authentication Code</h3>");
	
	debug_echo("🛑 Please make sure that the URI <b>$redirecturl</b> is configured as a Sign-in redirect URI at Okta for the application with client-id <b>$client_id</b>. Then click the button below to continue.");
	
	echo("<a class=\"btn\" href=\"$authorize_url\" target=\"_blank\">Request Authentication Code From OKTA</a>");
	debug_echo("<p style=\"margin-top:8px; font-size: 13px;\">This will open in a new browser tab.</p>");
}

###############################################################################

function curl_get_url($url, $timeout=10, $httpauth=false, $httpheader=false, $useragent=false) {
	$retv = array('result' => "", 'status' => 0);
	if(function_exists('curl_version'))
	{
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
		
		if($httpauth !== false)
			curl_setopt($ch, CURLOPT_HTTPAUTH, $httpauth);
		if($httpheader !== false)
			curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
		if($useragent !== false && $useragent != "") {
			if($useragent == "?" || $useragent == "-")
				$useragent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13';
			curl_setopt($ch,CURLOPT_USERAGENT,$useragent);
		}
		
		$retv['result'] = curl_exec ($ch);
		$retv['result'] = ($retv['result'] === false) ? "" : $retv['result'];
		$retv['status'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		if (curl_error($ch)) 
			$retv['error'] = curl_error($ch);
		curl_close ($ch);
	}
	return $retv;
}

###############################################################################

function curl_post_url($url, $timeout=10, $httpauth=false, $httpheader=false, $postdata=false) {
	$retv = array('result' => "", 'status' => 0);
	if(function_exists('curl_version'))
	{
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 
		curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
		
		if($httpauth !== false)
			curl_setopt($ch, CURLOPT_HTTPAUTH, $httpauth);
		if($httpheader !== false)
			curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
		
		curl_setopt( $ch, CURLOPT_POST, 1 );
		if($postdata !== false && is_array($postdata))
			$postdata = http_build_query($postdata);
		if($postdata !== false)
			curl_setopt( $ch, CURLOPT_POSTFIELDS, $postdata);
		
		$retv['result'] = curl_exec ($ch);
		$retv['result'] = ($retv['result'] === false) ? "" : $retv['result'];
		$retv['status'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		if (curl_error($ch)) 
			$retv['error'] = curl_error($ch);
		curl_close ($ch);
	}
	return $retv;
}

###############################################################################

function is_cli() {
	if( defined('STDIN') || 
		(empty($_SERVER['REMOTE_ADDR']) && !isset($_SERVER['HTTP_USER_AGENT']) 
		&& count($_SERVER['argv']) > 0))
		return true;
	return false;
}

###############################################################################

$styles_set = false;
function debug_echo($str) {
	global $styles_set;
	if(!$styles_set && !is_cli()) {
		$styles_set = true;
?>
<HTML>
	<HEAD>
		<style>
			*{font-family:Verdana,Sans-Serif;}
			body {
				width: MIN(70VW, 980px);
				overflow: auto;
				overflow-wrap: break-word;
			}
			p {
				margin-bottom:1rem;
				margin-top:0;
			}
			h1 {
				margin-bottom: 36px;
				text-align: center;
				border-bottom: 4px double #808080;
			}
			h3 {
				margin-top: 25px;
				margin-bottom: 36px;
				display: inline-block;
				border-bottom: 1px solid #000000;
			}
			a{
				background-color:#FF0000;
				color:#FFFFFF;
				padding:3px 8px 5px 8px;
				text-decoration:none;
				box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
				border-radius: 2px;
			}
			.btn {
				margin-top: 24px;
				margin-bottom: 16px;
			}
			a:hover{background-color:#800000;}
			hr {
				height: 0;
				border-top: 1px solid #808080;
				width: MIN(70VW, 980px);
				margin-left: 0;
			}
		</style>
	</HEAD>
<?php
	}
	if(is_cli()) {
		if(is_array($str))
			print_r($str);
		else
			echo($str . "\n");
	}
	else {
		if(is_array($str)) {
			echo("<pre>");
			print_r($str);
			echo("</pre>");
		}
		else {
			if(substr($str, 0, 1) != "<")
				echo("<p>" . $str . "</p>");
			else
				echo($str);
		}
	}
}

###############################################################################
