Files
mahak-authenticate-bridge/src/app/Http/Controllers/AuthenticateController.php
T

135 lines
4.1 KiB
PHP

<?php
namespace Dabestaniha\AuthenticateBridge\App\Http\Controllers;
use Dabestaniha\AuthenticateBridge\App\Http\Requests\MahakAuthenticateRequest;
use Dabestaniha\AuthenticateBridge\App\Support\JwtDecoder;
use RuntimeException;
use Throwable;
use UnexpectedValueException;
class AuthenticateController extends InvocableController
{
private array $debugContext = [];
public function __invoke(MahakAuthenticateRequest $request)
{
$token = $request->string('token');
if (mahak_debug_enabled()) {
$this->debugContext['jwt_timestamps'] = $this->inspectJwtTimestamps($token);
}
$payload = $this->decrypt_jwt_token($token);
$identifier_name = get_configured_option('user-identifier');
$identifier_value = $payload[$identifier_name] ?? null;
$name = $payload['name'] ?? config('mahak.translates.new-user');
$user_id = $this->find_or_create_user($identifier_name, $identifier_value, $name);
$this->login_user($user_id);
$redirect_path = get_configured_option('after-login-route');
wp_redirect(home_url($redirect_path));
exit();
}
public function decrypt_jwt_token(string $token): array
{
$jwt_secret = get_configured_option('jwt-secret');
$decoded = JwtDecoder::decodeHs256($token, $jwt_secret);
$data = $decoded['data'] ?? null;
if (!is_array($data)) {
throw new UnexpectedValueException('JWT data must be an object.');
}
return $data;
}
public function find_or_create_user(string $identifier_name, string $identifier_value, string $name): int
{
$user = get_user_by($identifier_name, $identifier_value);
if ($user) {
return $user->ID;
}
$random_password = wp_generate_password(12, true);
$username = $identifier_value;
$email = $identifier_name === 'email' ? $identifier_value : '';
if (username_exists($username)) {
$username .= '_'.wp_generate_password(4, false);
}
$user_id = wp_create_user($username, $random_password, $email);
if (is_wp_error($user_id)) {
throw new RuntimeException(
'WordPress could not create the user: '.$user_id->get_error_message()
);
}
$updated_user_id = wp_update_user([
'ID' => $user_id,
'display_name' => $name,
]);
if (is_wp_error($updated_user_id)) {
throw new RuntimeException(
'WordPress could not update the user: '.$updated_user_id->get_error_message()
);
}
return $user_id;
}
protected function handleException(Throwable $exception): void
{
$status = $exception->getCode() === 403 ? 403 : 500;
$fallbackView = $exception instanceof UnexpectedValueException ? 'invalid-token' : 'server-error';
mahak_render_error($exception, $status, $fallbackView, $this->debugContext);
}
private function inspectJwtTimestamps(string $token): array
{
$segments = explode('.', $token);
if (count($segments) !== 3) {
return [];
}
$encodedPayload = strtr($segments[1], '-_', '+/');
$encodedPayload .= str_repeat('=', (4 - strlen($encodedPayload) % 4) % 4);
$json = base64_decode($encodedPayload, true);
$payload = $json === false ? null : json_decode($json, true);
if (!is_array($payload)) {
return [];
}
$timestamps = [];
foreach (['iat', 'nbf', 'exp'] as $claim) {
if (array_key_exists($claim, $payload)) {
$value = is_scalar($payload[$claim]) ? (string) $payload[$claim] : '[non-scalar]';
$timestamps[$claim] = strlen($value) > 64 ? substr($value, 0, 64).'…' : $value;
}
}
return $timestamps;
}
public function login_user(int $user_id): bool
{
wp_set_auth_cookie($user_id);
wp_set_current_user($user_id);
do_action('wp_login', get_userdata($user_id)->user_login, get_userdata($user_id));
return true;
}
}