die tenant admin oauth authentifizierung wurde implementiert und funktioniert jetzt. Zudem wurde das marketing frontend dashboard implementiert.
This commit is contained in:
@@ -7,11 +7,13 @@ use App\Models\OAuthCode;
|
||||
use App\Models\RefreshToken;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\TenantToken;
|
||||
use App\Models\User;
|
||||
use App\Support\ApiError;
|
||||
use Firebase\JWT\JWT;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -35,6 +37,15 @@ class OAuthController extends Controller
|
||||
*/
|
||||
public function authorize(Request $request)
|
||||
{
|
||||
if (! Auth::check()) {
|
||||
return $this->authorizeErrorResponse(
|
||||
$request,
|
||||
'login_required',
|
||||
'Please sign in to continue.',
|
||||
Response::HTTP_UNAUTHORIZED
|
||||
);
|
||||
}
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'client_id' => 'required|string',
|
||||
'redirect_uri' => 'required|url',
|
||||
@@ -46,7 +57,13 @@ class OAuthController extends Controller
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return $this->errorResponse('Invalid request parameters', 400, $validator->errors());
|
||||
return $this->authorizeErrorResponse(
|
||||
$request,
|
||||
'invalid_request',
|
||||
'The authorization request is invalid.',
|
||||
Response::HTTP_BAD_REQUEST,
|
||||
['errors' => $validator->errors()->toArray()]
|
||||
);
|
||||
}
|
||||
|
||||
/** @var OAuthClient|null $client */
|
||||
@@ -56,23 +73,47 @@ class OAuthController extends Controller
|
||||
->first();
|
||||
|
||||
if (! $client) {
|
||||
return $this->errorResponse('Invalid client', 401);
|
||||
return $this->authorizeErrorResponse(
|
||||
$request,
|
||||
'invalid_client',
|
||||
'The specified client could not be found.',
|
||||
Response::HTTP_UNAUTHORIZED
|
||||
);
|
||||
}
|
||||
|
||||
$allowedRedirects = (array) $client->redirect_uris;
|
||||
if (! in_array($request->redirect_uri, $allowedRedirects, true)) {
|
||||
return $this->errorResponse('Invalid redirect URI', 400);
|
||||
return $this->authorizeErrorResponse(
|
||||
$request,
|
||||
'invalid_redirect',
|
||||
'The redirect URI is not registered for this client.',
|
||||
Response::HTTP_BAD_REQUEST
|
||||
);
|
||||
}
|
||||
|
||||
$requestedScopes = $this->parseScopes($request->string('scope'));
|
||||
$availableScopes = (array) $client->scopes;
|
||||
if (! $this->scopesAreAllowed($requestedScopes, $availableScopes)) {
|
||||
return $this->errorResponse('Invalid scopes requested', 400);
|
||||
return $this->authorizeErrorResponse(
|
||||
$request,
|
||||
'invalid_scope',
|
||||
'The client requested scopes that are not permitted.',
|
||||
Response::HTTP_BAD_REQUEST
|
||||
);
|
||||
}
|
||||
|
||||
$tenantId = $client->tenant_id ?? Tenant::query()->orderBy('id')->value('id');
|
||||
/** @var User $user */
|
||||
$user = Auth::user();
|
||||
|
||||
$tenantId = $this->resolveTenantId($client, $user);
|
||||
if (! $tenantId) {
|
||||
return $this->errorResponse('Unable to resolve tenant for client', 500);
|
||||
return $this->authorizeErrorResponse(
|
||||
$request,
|
||||
'tenant_mismatch',
|
||||
'You do not have access to the requested tenant.',
|
||||
Response::HTTP_FORBIDDEN,
|
||||
['client_id' => $client->client_id]
|
||||
);
|
||||
}
|
||||
|
||||
$code = Str::random(64);
|
||||
@@ -95,7 +136,7 @@ class OAuthController extends Controller
|
||||
OAuthCode::create([
|
||||
'id' => $codeId,
|
||||
'client_id' => $client->client_id,
|
||||
'user_id' => (string) $tenantId,
|
||||
'user_id' => (string) $user->getAuthIdentifier(),
|
||||
'code' => Hash::make($code),
|
||||
'code_challenge' => $request->code_challenge,
|
||||
'state' => $request->state,
|
||||
@@ -120,6 +161,75 @@ class OAuthController extends Controller
|
||||
return redirect()->away($redirectUrl);
|
||||
}
|
||||
|
||||
private function resolveTenantId(OAuthClient $client, User $user): ?int
|
||||
{
|
||||
if ($client->tenant_id !== null) {
|
||||
if ((int) $client->tenant_id === (int) ($user->tenant_id ?? 0) || $user->role === 'super_admin') {
|
||||
return (int) $client->tenant_id;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($user->tenant_id !== null) {
|
||||
return (int) $user->tenant_id;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function rememberIntendedUrl(Request $request): void
|
||||
{
|
||||
session()->put('url.intended', $request->fullUrl());
|
||||
}
|
||||
|
||||
private function authorizeErrorResponse(
|
||||
Request $request,
|
||||
string $code,
|
||||
string $message,
|
||||
int $status,
|
||||
array $meta = []
|
||||
) {
|
||||
$this->rememberIntendedUrl($request);
|
||||
|
||||
if ($this->shouldReturnJsonAuthorizeResponse($request)) {
|
||||
$payload = [
|
||||
'error' => $code,
|
||||
'error_description' => $message,
|
||||
];
|
||||
|
||||
if ($meta !== []) {
|
||||
$payload['meta'] = $meta;
|
||||
}
|
||||
|
||||
return response()->json($payload, $status);
|
||||
}
|
||||
|
||||
$query = [
|
||||
'error' => $code,
|
||||
'error_description' => $message,
|
||||
'return_to' => $this->encodeReturnTo($request->fullUrl()),
|
||||
];
|
||||
|
||||
if ($meta !== []) {
|
||||
$metaJson = json_encode($meta, JSON_UNESCAPED_SLASHES);
|
||||
if ($metaJson !== false) {
|
||||
$query['error_meta'] = $this->encodeReturnTo($metaJson);
|
||||
}
|
||||
}
|
||||
|
||||
$redirectUrl = route('tenant.admin.login').'?'.http_build_query($query);
|
||||
|
||||
return redirect()->to($redirectUrl);
|
||||
}
|
||||
|
||||
private function encodeReturnTo(?string $value): string
|
||||
{
|
||||
$value ??= '';
|
||||
|
||||
return rtrim(strtr(base64_encode($value), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
/**
|
||||
* Token endpoint - Code exchange & refresh
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user