fix(ios): injecte le cookie d'auth dans le store de la WKWebView

AppDelegate écrivait dans HTTPCookieStorage.shared, qui est le store
d'URLSession — pas celui que lit la WKWebView (WKWebsiteDataStore). Ça
fonctionnait jusqu'en mai parce que Capacitor recopiait alors les cookies au
démarrage ; ce n'est plus le cas, et l'app retombait sur l'écran de login
malgré un token valide (constaté sur device le 2026-08-03).

MainViewController.viewDidLoad injecte désormais dans le store de la WebView,
puis recharge une fois pour rejouer la première requête avec le cookie. Pas de
boucle : au passage suivant le cookie existe et on sort avant.

L'injection AppDelegate est conservée : elle sert aux appels natifs URLSession.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Sylvain Bettinelli
2026-08-03 15:21:28 +00:00
parent 95d2961a56
commit df843368ce

View File

@@ -6,6 +6,7 @@
import UIKit
import Capacitor
import WebKit
class MainViewController: CAPBridgeViewController {
override func capacitorDidLoad() {
@@ -37,8 +38,50 @@ class MainViewController: CAPBridgeViewController {
bridge?.registerPluginInstance(CoachRoutineBridgePlugin())
}
/// Injecte le cookie d'auth dans le magasin de la WKWebView.
///
/// `AppDelegate.injectCoachAuthCookie()` écrit dans
/// `HTTPCookieStorage.shared` c'est le store d'URLSession, PAS celui que
/// lit la WKWebView. Ça a marché jusqu'en mai parce que Capacitor recopiait
/// alors les cookies au démarrage ; ce n'est plus le cas, d'où l'écran de
/// login qui réapparaissait (constaté sur device le 2026-08-03).
///
/// Les deux injections sont conservées : `HTTPCookieStorage.shared` reste
/// utile aux appels natifs via URLSession.
private func injectAuthCookieIntoWebView() {
let token = CoachAuth.kCoachWebToken
guard !token.isEmpty, token != "REPLACE_ME", let webView = self.webView else { return }
let store = webView.configuration.websiteDataStore.httpCookieStore
store.getAllCookies { cookies in
// Ne PAS écraser une session per-user existante (login Apple/Google).
if cookies.contains(where: {
$0.name == "coach_web_token" && $0.domain.contains("coach.hypnotruck.ch")
}) { return }
let oneYear: TimeInterval = 60 * 60 * 24 * 365
guard let cookie = HTTPCookie(properties: [
.name: "coach_web_token",
.value: token,
.domain: "coach.hypnotruck.ch",
.path: "/",
.secure: true,
.expires: Date(timeIntervalSinceNow: oneYear),
]) else { return }
store.setCookie(cookie) {
// La première requête est déjà partie sans cookie (on a atterri
// sur /login) : il faut recharger pour la rejouer avec.
// Pas de boucle possible au prochain passage le cookie existe
// et on sort au `return` ci-dessus.
DispatchQueue.main.async { webView.reload() }
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
injectAuthCookieIntoWebView()
// Force le background noir sur tous les niveaux pour éliminer la
// bande blanche du bounce iOS WKWebView (cause : scrollView.backgroundColor
// par défaut blanc, exposé lors de l'overscroll). Aucun CSS web ne peut