Sécurité et qualité : headers HTTP, permissions .env, lint PHPStan + PHP-CS-Fixer, réorganisation dossiers, scripts de déploiement

This commit is contained in:
Cedric Abonnel
2026-05-08 13:18:00 +02:00
parent 700329f156
commit 70304d3b31
44 changed files with 776 additions and 670 deletions
+22 -8
View File
@@ -1,19 +1,27 @@
<?php
declare(strict_types=1);
use App\Infrastructure\Database;
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
require_once dirname(__DIR__, 2) . '/config/config.php';
if (!function_exists('env')) {
function env(string $key, ?string $default = null): ?string {
if (array_key_exists($key, $_ENV) && $_ENV[$key] !== '') return (string)$_ENV[$key];
function env(string $key, ?string $default = null): ?string
{
if (array_key_exists($key, $_ENV) && $_ENV[$key] !== '') {
return (string)$_ENV[$key];
}
$v = getenv($key);
if ($v !== false && $v !== '') return (string)$v;
if ($v !== false && $v !== '') {
return (string)$v;
}
return $default;
}
}
@@ -68,7 +76,9 @@ $post = [
'client_id' => $OIDC_CLIENT_ID,
'code_verifier' => $codeVerifier,
];
if ($OIDC_CLIENT_SECRET !== '') $post['client_secret'] = $OIDC_CLIENT_SECRET;
if ($OIDC_CLIENT_SECRET !== '') {
$post['client_secret'] = $OIDC_CLIENT_SECRET;
}
$ch = curl_init($tokenEndpoint);
curl_setopt_array($ch, [
@@ -127,7 +137,9 @@ if (!$email && $idToken && substr_count($idToken, '.') === 2) {
[, $p, ] = explode('.', $idToken, 3);
$payloadJson = base64_decode(strtr($p, '-_', '+/'), true);
$payload = $payloadJson ? json_decode($payloadJson, true) : null;
if (is_array($payload) && !empty($payload['email'])) $email = $payload['email'];
if (is_array($payload) && !empty($payload['email'])) {
$email = $payload['email'];
}
}
if (!$email) {
@@ -159,7 +171,9 @@ if ($flow === 'login' && $existingId) {
];
$target = $_SESSION['oidc_return_to'] ?? '/';
unset($_SESSION['oidc_return_to'], $_SESSION['oidc_flow']);
if (!is_string($target) || $target === '' || $target[0] !== '/') $target = '/';
if (!is_string($target) || $target === '' || $target[0] !== '/') {
$target = '/';
}
header('Location: ' . $target, true, 303);
exit;
}
@@ -176,4 +190,4 @@ $_SESSION['pending_oidc'] = [
unset($_SESSION['oidc_flow']);
header('Location: ' . url('register/from-oidc'), true, 303);
exit;
exit;
+31 -12
View File
@@ -12,31 +12,48 @@ require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
require_once dirname(__DIR__, 2) . '/config/config.php';
function maskToken(?string $t): string {
if (!$t) return '';
function maskToken(?string $t): string
{
if (!$t) {
return '';
}
$len = strlen($t);
if ($len <= 12) return str_repeat('•', $len);
if ($len <= 12) {
return str_repeat('•', $len);
}
return substr($t, 0, 6) . str_repeat('•', max(0, $len - 12)) . substr($t, -6);
}
function b64url_decode_str(string $s): string|false {
function b64url_decode_str(string $s): string|false
{
$s = strtr($s, '-_', '+/');
$pad = strlen($s) % 4;
if ($pad) $s .= str_repeat('=', 4 - $pad);
if ($pad) {
$s .= str_repeat('=', 4 - $pad);
}
return base64_decode($s, true);
}
function decode_jwt(string $jwt): array {
if (substr_count($jwt, '.') !== 2) return [];
function decode_jwt(string $jwt): array
{
if (substr_count($jwt, '.') !== 2) {
return [];
}
[, $payload, ] = explode('.', $jwt, 3);
$json = b64url_decode_str($payload);
if ($json === false) return [];
if ($json === false) {
return [];
}
$arr = json_decode($json, true);
return is_array($arr) ? $arr : [];
}
$env = static function(string $k, ?string $d = null): ?string {
if (array_key_exists($k, $_ENV) && $_ENV[$k] !== '') return (string)$_ENV[$k];
$env = static function (string $k, ?string $d = null): ?string {
if (array_key_exists($k, $_ENV) && $_ENV[$k] !== '') {
return (string)$_ENV[$k];
}
$v = getenv($k);
if ($v !== false && $v !== '') return (string)$v;
if ($v !== false && $v !== '') {
return (string)$v;
}
return $d;
};
@@ -72,7 +89,9 @@ if ($debugEnabled && $claims === [] && $accTok && $issuer) {
curl_close($ch);
if ($resp !== false && $code === 200) {
$tmp = json_decode((string)$resp, true);
if (is_array($tmp)) $claims = $tmp;
if (is_array($tmp)) {
$claims = $tmp;
}
}
}
+17 -7
View File
@@ -1,23 +1,33 @@
<?php
declare(strict_types=1);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
require_once dirname(__DIR__, 2) . '/app/bootstrap.php';
require_once dirname(__DIR__, 2) . '/config/config.php';
if (!function_exists('env')) {
function env(string $key, ?string $default = null): ?string {
if (array_key_exists($key, $_ENV) && $_ENV[$key] !== '') return (string)$_ENV[$key];
function env(string $key, ?string $default = null): ?string
{
if (array_key_exists($key, $_ENV) && $_ENV[$key] !== '') {
return (string)$_ENV[$key];
}
$v = getenv($key);
if ($v !== false && $v !== '') return (string)$v;
if ($v !== false && $v !== '') {
return (string)$v;
}
return $default;
}
}
$flow = $_GET['flow'] ?? 'login'; // 'login' ou 'register'
if (!in_array($flow, ['login','register'], true)) $flow = 'login';
if (!in_array($flow, ['login','register'], true)) {
$flow = 'login';
}
// return_to (URL relative uniquement)
$defaultReturn = '/';
@@ -29,8 +39,8 @@ $_SESSION['oidc_flow'] = $flow;
$_SESSION['oidc_return_to'] = $returnTo;
// --- OIDC conf ---
$issuer = rtrim((string)env('OIDC_ISSUER',''), '/');
$clientId = (string)env('OIDC_CLIENT_ID','');
$issuer = rtrim((string)env('OIDC_ISSUER', ''), '/');
$clientId = (string)env('OIDC_CLIENT_ID', '');
$redirectUri = (string)(env('OIDC_REDIRECT_URI') ?: url('oidc/callback'));
if (!$issuer || !$clientId || !$redirectUri) {
http_response_code(500);