// ===================== // Validación de session token de Shopify App Bridge (JWT) // ===================== if (!function_exists('npd_validate_shopify_session_token')) { /** * Valida el session token JWT de Shopify App Bridge. * @param string $token * @param string $api_key (opcional, por defecto NPD_SHOPIFY_PUBLIC_API_KEY) * @return array|WP_Error Datos del token si es válido, WP_Error si no */ function npd_validate_shopify_session_token($token, $api_key = null) { if (!$api_key) { $api_key = defined('NPD_SHOPIFY_PUBLIC_API_KEY') ? NPD_SHOPIFY_PUBLIC_API_KEY : ''; } if (!$token || !$api_key) { return new WP_Error('missing_token_or_key', 'Falta token o api_key'); } // Decodificar JWT (sin verificar firma aún) $parts = explode('.', $token); if (count($parts) !== 3) { return new WP_Error('invalid_jwt', 'Formato JWT inválido'); } list($header64, $payload64, $sig64) = $parts; // Función para añadir padding base64 si falta $b64pad = function($s) { $s = strtr($s, '-_', '+/'); $pad = strlen($s) % 4; if ($pad > 0) $s .= str_repeat('=', 4 - $pad); return $s; }; $header_json = base64_decode($b64pad($header64)); $payload_json = base64_decode($b64pad($payload64)); if ($header_json === false || $payload_json === false) { return new WP_Error('invalid_jwt', 'No se pudo decodificar base64 JWT'); } $header = json_decode($header_json, true); $payload = json_decode($payload_json, true); if (!$header || !$payload) { return new WP_Error('invalid_jwt', 'No se pudo decodificar JSON JWT'); } // Verificar firma (HS256) $sig = base64_decode($b64pad($sig64)); $data = $header64 . '.' . $payload64; $expected = hash_hmac('sha256', $data, $api_key, true); if ($sig === false || !hash_equals($expected, $sig)) { return new WP_Error('invalid_signature', 'Firma JWT inválida'); } // Verificar expiración if (isset($payload['exp']) && time() > intval($payload['exp'])) { return new WP_Error('expired_token', 'El session token ha expirado'); } return $payload; } } HUGO BOSS → NEXUS

Menú