check(Http::clientIp())) { Http::fail(429, 'rate_limited', 'Zu viele Provisionierungsversuche.'); } $masterToken = Http::bearerToken(); if ($masterToken === null) { Http::fail( 401, 'missing_master_token', 'Master-Token fehlt. Erwartet im Header X-Master-Token oder als Authorization: Bearer .' ); } $data = Http::body(); $name = Http::str('client_name') ?? Http::str('name') ?? 'Auto-provisioniertes Sub-Token'; $instanceIdentity = Http::str('instance_id') ?? Http::str('hostname'); $environment = Http::str('environment') ?? 'all'; $requestedScopes = $data['scopes'] ?? []; if (is_string($requestedScopes)) { $requestedScopes = array_map('trim', explode(',', $requestedScopes)); } if (!is_array($requestedScopes)) { $requestedScopes = []; } $manager = new TokenManager($db); try { $subToken = $manager->provisionSubToken( $masterToken, $name, $instanceIdentity, $requestedScopes, $environment ); } catch (InvalidArgumentException $e) { Logger::warning('Provisionierung abgelehnt', [ 'ip' => Http::clientIp(), 'reason' => $e->getMessage(), ]); Http::fail(403, 'provision_denied', $e->getMessage()); } Http::ok([ 'sub_token' => $subToken['raw_token'], 'token_id' => $subToken['token_id'], 'name' => $subToken['name'], 'scopes' => $subToken['scopes'], 'environment' => $subToken['environment'], 'expires_at' => $subToken['expires_at'], 'type' => 'sub', 'created_at' => gmdate('Y-m-d H:i:s'), 'message' => 'Sub-Token erstellt. Der Wert wird nur einmal ausgeliefert - bitte sicher speichern.', ], 201);