feat(handler_ws): pluginLifecycle en copias locales acepta secreto_local del .acai
Segunda via de autenticacion de los ganchos de ciclo de vida en copias locales de Forge: ademas del par token+tokenHash del .acai, acepta el campo secretoLocal del cuerpo si coincide (hash_equals) con secreto_local del .acai. Las cadenas vacias o no escalares nunca coinciden y mode=production sigue rechazando. La via token+tokenHash queda como transitoria hasta que el .acai deje de llevar el token (fase 1d). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
dabdfa1354
commit
5709c5c856
@@ -406,10 +406,13 @@ function _renameFile() {
|
||||
* (install/uninstall/enable/disable) quedaban inservibles ahi con un
|
||||
* "Token no valido" que no tenia nada que ver con el token.
|
||||
*
|
||||
* No es un bypass: se compara el par token+tokenHash recibido con el que la
|
||||
* propia web guarda en su .acai, que es exactamente el que Forge envia. Sin
|
||||
* .acai (produccion), con mode=production, o sin coincidencia exacta, no
|
||||
* autoriza nada.
|
||||
* No es un bypass: se compara un secreto recibido en el cuerpo con el que la
|
||||
* propia web guarda en su .acai. Sin .acai (produccion), con mode=production,
|
||||
* o sin coincidencia exacta, no autoriza nada. Dos formas de coincidir:
|
||||
* - secretoLocal (cuerpo) == secreto_local (.acai): el secreto de la copia,
|
||||
* que no es una credencial de ninguna persona. Es la via buena.
|
||||
* - token+tokenHash (cuerpo) == token+tokenHash (.acai): la de siempre.
|
||||
* Las cadenas vacias nunca coinciden. Los secretos no se registran nunca.
|
||||
*/
|
||||
function _lifecycleTokenLocalValido($datosAuth) {
|
||||
$acaiPath = __DIR__ . "/../../../.acai";
|
||||
@@ -420,10 +423,24 @@ function _lifecycleTokenLocalValido($datosAuth) {
|
||||
if (!is_array($acai) || @$acai["mode"] === "production") {
|
||||
return false;
|
||||
}
|
||||
$token = (string) @$datosAuth["token"];
|
||||
$hash = (string) @$datosAuth["tokenHash"];
|
||||
$tokenLocal = (string) @$acai["token"];
|
||||
$hashLocal = (string) @$acai["tokenHash"];
|
||||
if (!is_array($datosAuth)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Via buena: el secreto propio de la copia local.
|
||||
$secretoLocal = @$acai["secreto_local"];
|
||||
$secreto = @$datosAuth["secretoLocal"];
|
||||
if (is_string($secretoLocal) && $secretoLocal !== ""
|
||||
&& is_scalar($secreto) && (string) $secreto !== ""
|
||||
&& hash_equals($secretoLocal, (string) $secreto)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// transitorio: quitar cuando el .acai ya no lleve token (fase 1d)
|
||||
$token = is_scalar(@$datosAuth["token"]) ? (string) $datosAuth["token"] : "";
|
||||
$hash = is_scalar(@$datosAuth["tokenHash"]) ? (string) $datosAuth["tokenHash"] : "";
|
||||
$tokenLocal = is_scalar(@$acai["token"]) ? (string) $acai["token"] : "";
|
||||
$hashLocal = is_scalar(@$acai["tokenHash"]) ? (string) $acai["tokenHash"] : "";
|
||||
if ($token === "" || $hash === "" || $tokenLocal === "" || $hashLocal === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user