Aller au contenu principal

Authentification et session

La CLI tk-ota-push implémente un flux d'authentification Web-to-CLI sécurisé par PKCE (Proof Key for Code Exchange, S256) dans AuthManager (lib/src/cli/auth/auth_manager.dart) et persiste les identifiants localement via SessionManager (lib/src/cli/auth/session_manager.dart). Pour les environnements CI/CD sans navigateur, la variable d'environnement OTA_API_KEY permet d'outrepasser le flux interactif.

1. Connexion interactive (tk-ota-push login)​

# Connexion standard (lit web_console_url dans shorebird.yaml ou http://localhost:3000)
tk-ota-push login

# Connexion en spécifiant explicitement l'URL de la Console Web
tk-ota-push login --web-url https://console.ota.exemple.org

Cascade de résolution de l'URL Web​

Lors de l'appel à tk-ota-push login, l'URL du portail Web est résolue dans cet ordre :

  1. Flag --web-url
  2. Champ web_console_url dans shorebird.yaml
  3. Variable d'environnement OTA_WEB_CONSOLE_URL
  4. Défaut : http://localhost:3000

Séquence détaillée du flux PKCE (AuthManager.login)​

Déroulement de l'authentification CLI
  1. Initialisation : La CLI démarre un écouteur local sécurisé (http://127.0.0.1:<port>).
  2. Connexion Web : La CLI ouvre votre navigateur sur la page /cli/login de la Console TkushPatch.
  3. Échange de jeton : Après validation de vos identifiants, un jeton sécurisé est transmis à l'écouteur local.
  4. Persistance sécurisée : Les identifiants de session sont enregistrés localement dans ~/.tk_ota_push/credentials.json.

Paramètres exacts de la requête d'autorisation initiale ouverte dans le navigateur :

  • callback_url : http://127.0.0.1:<port>/callback
  • state : chaîne aléatoire sécurisée de 32 caractères (Random.secure())
  • code_challenge : condensat SHA-256 encodé en Base64URL sans padding =
  • code_challenge_method : S256
  • device_name : Platform.localHostname
  • cli_version : 0.2.0

Le délai d'attente maximal (timeout) avant expiration de la tentative de connexion est de 3 minutes.

2. Échange et rafraîchissement des jetons​

Échange initial (/api/cli/token/exchange)​

Une fois le code reçu sur /callback, la CLI effectue une requête POST vers <webConsoleUrl>/api/cli/token/exchange :

{
"code": "<code_ephemere>",
"code_verifier": "<verifier_64_caracteres>"
}

Rafraîchissement automatique (ensureFreshToken)​

Avant chaque commande release, patch, promote ou symbols, si aucun OTA_API_KEY n'est défini dans l'environnement, la CLI charge la session locale et vérifie credentials.isExpired :

  • Un jeton est considéré comme expiré 30 secondes avant son horodatage expires_at (DateTime.now().isAfter(expiresAt.subtract(const Duration(seconds: 30)))).
  • S'il est expiré et qu'un refreshToken est disponible, AuthManager.ensureFreshToken appelle tokenRefreshUrl (ou <webConsoleUrl>/api/cli/token/refresh) en POST :
{
"refresh_token": "<refresh_token>",
"tenant_id": "<tenant_id>"
}

Si le serveur répond 200 OK, la nouvelle session est immédiatement persistée dans ~/.tk_ota_push/credentials.json.

3. Stockage de la session locale (SessionManager)​

Le fichier de session est enregistré dans :

  • macOS / Linux : $HOME/.tk_ota_push/credentials.json (avec permissions restreintes via chmod 600)
  • Windows : %USERPROFILE%\.tk_ota_push\credentials.json

Structure JSON persistée par CliCredentials.toJson() :

{
"access_token": "<jwt_access_token>",
"refresh_token": "<jwt_refresh_token>",
"expires_at": "2026-11-09T14:30:00.000Z",
"tenant_id": "sara-money",
"username": "alice.dev@saramoney.cm",
"sub": "user-uuid-999",
"roles": ["RELEASE_DEVELOPER", "SECURITY_OFFICER"],
"token_refresh_url": "http://localhost:3000/api/cli/token/refresh",
"web_console_url": "http://localhost:3000"
}

4. Vérification de la session (tk-ota-push whoami)​

La commande whoami lit ~/.tk_ota_push/credentials.json et affiche les informations d'identité sans effectuer d'appel réseau :

tk-ota-push whoami

Sortie :

Connecté en tant que : alice.dev@saramoney.cm
Tenant ID : sara-money
Subject (UUID) : user-uuid-999
Rôles : RELEASE_DEVELOPER, SECURITY_OFFICER
Expiration jeton : 2026-11-09 15:30:00.000

5. Authentification CI/CD sans navigateur (OTA_API_KEY)​

Sur un serveur d'intégration continue (GitHub Actions, GitLab CI, Jenkins, Bitbucket Pipelines), n'exécutez pas tk-ota-push login. Injectez directement le jeton d'accès dans la variable d'environnement OTA_API_KEY :

export OTA_API_KEY="<VOTRE_JETON_CI_OU_BEARER>"
export OTA_SERVER_URL="https://ota.exemple.org"
export OTA_TENANT_ID="sara-money"

tk-ota-push release --platform android --artifact aab

Dans OtaApiClient, si apiKey est non vide, l'en-tête HTTP suivant est ajouté à chaque requête vers /api/admin/v1/* :

Authorization: Bearer <OTA_API_KEY>

6. Déconnexion (tk-ota-push logout)​

Pour révoquer localement la session et supprimer le fichier ~/.tk_ota_push/credentials.json :

tk-ota-push logout

Sorties possibles :

  • Session supprimée avec succès. (si une session existait)
  • Déjà déconnecté. (si aucun fichier credentials.json n'était présent)