define('SSO_CLIENT_ID', '');
define('SSO_CLIENT_SECRET', '');
define('SSO_METADATA', 'https://PROVIDER.COM/.well-known/openid-configuration');
define('SSO_REDIRECT_URI', URL_PUBLIC . 'sso/callback');
public static function action_signin() {
AuthUser::load();
if (AuthUser::isLoggedIn()) {
redirect('/admin');
return;
}
$metadata = self::http(SSO_METADATA);
$_SESSION['state'] = bin2hex(random_bytes(5));
$_SESSION['code_verifier'] = bin2hex(random_bytes(50));
$code_challenge = self::base64_urlencode(hash('sha256', $_SESSION['code_verifier'], true));
$authorize_url = $metadata->authorization_endpoint.'?'.http_build_query([
'response_type' => 'code',
'client_id' => SSO_CLIENT_ID,
'redirect_uri' => SSO_REDIRECT_URI,
'state' => $_SESSION['state'],
'scope' => 'openid email profile',
'code_challenge' => $code_challenge,
'code_challenge_method' => 'S256',
]);
redirect($authorize_url);
}
public static function action_callback() {
if(!isset($_SESSION['state']) || !isset($_GET['state']) || $_SESSION['state'] != $_GET['state']) {
die('Authorization server returned an invalid state parameter');
}
if(isset($_GET['error'])) {
die('Authorization server returned an error: '.htmlspecialchars($_GET['error']));
}
$metadata = self::http(SSO_METADATA);
$response = self::http($metadata->token_endpoint, [
'grant_type' => 'authorization_code',
'code' => $_GET['code'],
'redirect_uri' => SSO_REDIRECT_URI,
'client_id' => SSO_CLIENT_ID,
'client_secret' => SSO_CLIENT_SECRET,
'code_verifier' => $_SESSION['code_verifier'],
]);
if (isset($response->error)) {
die('Authorization server returned an error: '.htmlspecialchars($response->error));
}
$userinfo = self::http($metadata->userinfo_endpoint, [
'access_token' => $response->access_token,
]);
if (!isset($userinfo->sub)) {
die('Error fetching access token');
}
$login = self::createOrLogin($userinfo);
if (!$login) {
die('Authentication request was not successful');
}
redirect('/dashboard');
}