oauth2: flux automat token ANAF (FR-1..FR-11) + arhivare fisiere vechi
- index.php: schimb code->token cu tratare completa erori, sesiune PHP pentru legare state (CSRF), stocare atomica tokenuri in fisier - pick.php: endpoint polling pentru ROACONT (preluare automata token) - oauth2_tokens mutat in oauth2/tokens/ + .htaccess Require all denied (locatia initiala "extra-docroot" era de fapt in interiorul public_html, deci web-accesibila fara aceasta protectie) - index1.php/index2.php/info.php (versiuni vechi) arhivate in _arhiva_oauth2/ cu .htaccess care blocheaza accesul HTTP Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
62
oauth2/pick.php
Normal file
62
oauth2/pick.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
// pick.php — Endpoint polling preluare automata token OAuth2 ANAF eFactura
|
||||
// Apelat de ROACONT cu POST state=<64 hex>; raspunde JSON:
|
||||
// {"status":"pending"} cat timp tokenul nu a sosit (intotdeauna HTTP 200, nu 404),
|
||||
// continutul fisierului de token (succes sau eroare ANAF) o SINGURA data, apoi il sterge.
|
||||
// Fara session_start() — evita serializarea pe lock-ul de sesiune PHP.
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// Director tokenuri (acelasi ca in index.php) — protejat cu .htaccess
|
||||
$tokens_dir = __DIR__ . '/tokens';
|
||||
if (!is_dir($tokens_dir)) {
|
||||
@mkdir($tokens_dir, 0700, true);
|
||||
}
|
||||
$tokens_htaccess = $tokens_dir . '/.htaccess';
|
||||
if (!file_exists($tokens_htaccess)) {
|
||||
@file_put_contents($tokens_htaccess, "Require all denied\n");
|
||||
}
|
||||
|
||||
// Validare stricta format state: 64 caractere [A-Za-z0-9] (protectie path traversal)
|
||||
$state = isset($_POST['state']) ? (string)$_POST['state'] : '';
|
||||
if (strlen($state) !== 64 || !preg_match('/^[A-Za-z0-9]+$/', $state)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'invalid_state']);
|
||||
exit();
|
||||
}
|
||||
|
||||
// TTL: sterge fisierele de tokenuri (si .tmp orfane) mai vechi de 10 minute
|
||||
// (aliniat cu timeout-ul de polling din ROACONT)
|
||||
$now = time();
|
||||
foreach (array_merge((array)glob($tokens_dir . '/*.json'), (array)glob($tokens_dir . '/*.tmp')) as $f) {
|
||||
if (($now - filemtime($f)) > 600) {
|
||||
@unlink($f);
|
||||
}
|
||||
}
|
||||
|
||||
// Numele fisierului = SHA-256(state): secretul nu apare in listinguri de directoare
|
||||
$token_file = $tokens_dir . '/' . hash('sha256', $state) . '.json';
|
||||
|
||||
if (!file_exists($token_file)) {
|
||||
echo json_encode(['status' => 'pending']);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Claim atomic prin rename: din doua cereri concurente una singura primeste tokenul,
|
||||
// cealalta "pending"; previne si citirea unui JSON partial (index.php scrie .tmp + rename)
|
||||
$claim_file = $tokens_dir . '/' . hash('sha256', $state) . '_claim_' . getmypid() . '.json';
|
||||
if (!@rename($token_file, $claim_file)) {
|
||||
echo json_encode(['status' => 'pending']);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Citire INAINTE de stergere; la esec nu stergem (TTL curata fisierul claim ramas)
|
||||
$content = file_get_contents($claim_file);
|
||||
if ($content === false || $content === '') {
|
||||
echo json_encode(['error' => 'read_error']);
|
||||
exit();
|
||||
}
|
||||
@unlink($claim_file);
|
||||
|
||||
// Continutul JSON exact cum a fost salvat de index.php (tokenuri sau eroare ANAF)
|
||||
echo $content;
|
||||
Reference in New Issue
Block a user