indieauth/index.php

145 lines
4.1 KiB
PHP
Raw Normal View History

2024-07-15 19:16:00 +00:00
<?php
2024-07-17 18:50:39 +00:00
/* Multi-user IndieAuth endpoint using server envvars from SSO
2024-07-15 19:16:00 +00:00
* Based on https://github.com/inklings-io/selfauth
*/
require_once 'functions.php';
require_once 'config.php';
$error = null;
// Verification of codes.
$code = filter_input_regexp( INPUT_POST, 'code', '@^[0-9a-f]+:[0-9a-f]{64}:@' );
if ( ! is_null($code) ){
$redirect_uri = filter_input( INPUT_POST, 'redirect_uri', FILTER_VALIDATE_URL );
$client_id = filter_input( INPUT_POST, 'client_id', FILTER_VALIDATE_URL );
if ( ! (
is_string($code) &&
is_string($redirect_uri) &&
2024-07-17 18:50:39 +00:00
is_string($client_id)
2024-07-15 19:16:00 +00:00
) ) {
2024-07-17 18:50:39 +00:00
$error = 'Invalid request';
2024-07-15 19:16:00 +00:00
http_response_code(400);
include 'form.php';
die();
}
$code_parts = explode(':', $code, 3);
2024-07-17 18:50:39 +00:00
$suffix_parts = explode(':', base64_url_decode( $code_parts[2] ), 2 );
$user = $suffix_parts[0];
if ( ! verify_signed_code( APP_KEY, $user . $redirect_uri . $client_id, $code ) ) {
$error = 'Invalid code';
http_response_code(400);
include 'form.php';
die();
}
$response = array('me' => USER_URLS[$user]);
2024-07-15 19:16:00 +00:00
$accept_header = $_SERVER['HTTP_ACCEPT'] ?: '*/*';
2024-07-17 18:50:39 +00:00
if ( '' !== $suffix_parts[1] ) {
$response['scope'] = $suffix_parts[1];
2024-07-15 19:16:00 +00:00
}
$json = get_q_value('application/json', $accept_header);
$form = get_q_value('application/x-www-form-urlencoded', $accept_header);
if ( 0 === $json && 0 === $form ){
$error = 'Client does not accept JSON or Form encoded responses';
http_response_code(406);
include 'form.php';
die();
} elseif ( $json >= $form ){
header('Content-Type: application/json');
exit( json_encode($response) );
} else {
header('Content-Type: application/x-www-form-urlencoded');
exit( http_build_query($response) );
}
}
// No code submitted,
// Check login
2024-07-17 18:50:39 +00:00
$user = $_SERVER["REMOTE_USER"];
if ( is_null($user) ) {
2024-07-15 19:16:00 +00:00
$error = 'Not logged in. Login on the <a href="https://auth.cool110.xyz/">SSO portal</a>';
http_response_code(403);
include 'form.php';
die();
2024-07-17 18:50:39 +00:00
} elseif ( ! array_key_exists( $user, USER_URLS ) ){
$error = 'Account not provisioned';
2024-07-15 19:16:00 +00:00
http_response_code(403);
include 'form.php';
die();
}
// Filter client data
$me = filter_input( INPUT_GET, 'me', FILTER_VALIDATE_URL );
$client_id = filter_input( INPUT_GET, 'client_id', FILTER_VALIDATE_URL );
$redirect_uri = filter_input( INPUT_GET, 'redirect_uri', FILTER_VALIDATE_URL );
$state = filter_input_regexp( INPUT_GET, 'state', '@^[\x20-\x7E]*$@' );
$response_type = filter_input_regexp( INPUT_GET, 'response_type', '@^(id|code)?$@' );
$scope = filter_input_regexp( INPUT_GET, 'scope', '@^([\x21\x23-\x5B\x5D-\x7E]+( [\x21\x23-\x5B\x5D-\x7E]+)*)?$@' );
if ( ! is_string($client_id) ) {
$error .= 'Invalid Client ID<br />';
}
if ( ! is_string($redirect_uri) ){
$error .= 'Invalid redirect URI<br />';
}
if ( false === $state ) {
$error .= 'Invalid state<br />';
}
if ( false === $response_type ) {
$error .= 'Invalid response type<br />';
}
if ( $error ){
http_response_code(400);
include 'form.php';
die();
}
$csrf_code = filter_input( INPUT_POST, '_csrf', FILTER_UNSAFE_RAW );
// If form submitted
if ( ! is_null($csrf_code) ) {
if ( !verify_signed_code( APP_KEY, $client_id . $redirect_uri . $state, $csrf_code ) ){
$error = 'Invalid CSFR code';
http_response_code(400);
include 'form.php';
die();
}
$scope = filter_input_regexp( INPUT_POST, 'scopes', '@^[\x21\x23-\x5B\x5D-\x7E]+$@', FILTER_REQUIRE_ARRAY );
if ( ! is_null($scope) ) {
if ( false === $scope || in_array( false, $scope, true ) ) {
$error = 'Provided scopes contain illegal characters';
}
$scope = implode( ' ', $scope );
}
2024-07-17 18:50:39 +00:00
$suffix = $user . ':' . $scope;
$code = create_signed_code( APP_KEY, $user . $redirect_uri . $client_id, 5 * 60, $suffix );
2024-07-15 19:16:00 +00:00
$final_redir = $redirect_uri;
if ( strpos($redirect_uri, '?') === false ) {
$final_redir .= '?';
} else {
$final_redir .= '&';
}
$parameters = array(
'code' => $code,
2024-07-17 18:50:39 +00:00
'me' => USER_URLS[$user]
2024-07-15 19:16:00 +00:00
);
if ( ! is_null($state) ) {
$parameters['state'] = $state;
}
$final_redir .= http_build_query($parameters);
header('Location: ' . $final_redir, true, 302);
} else {
$csrf_code = create_signed_code(APP_KEY, $client_id . $redirect_uri . $state, 2 * 60);
include 'form.php';
}