nip98-url-query-param-mismatch

Par divinevideo · divine-mobile

Corrige les erreurs HTTP 401 d'authentification NIP-98 causées par une divergence d'URL entre le tag `u` et ce qu'attend le serveur. À utiliser quand : (1) l'auth NIP-98 retourne 401 avec une erreur "URL mismatch", (2) la création du token réussit mais le serveur rejette l'authentification, (3) les logs serveur montrent une différence entre l'URL attendue et l'URL reçue. CRITIQUE : les implémentations serveur varient — certaines suppriment les query params, d'autres non. Vérifiez le message d'erreur réel pour déterminer quel comportement s'applique.

npx skills add https://github.com/divinevideo/divine-mobile --skill nip98-url-query-param-mismatch

NIP-98 Décalage des paramètres de requête URL

Problème

L'authentification NIP-98 échoue avec 401 Unauthorized même si le token est créé avec succès et la signature est valide. La cause réelle est une non-correspondance d'URL entre le tag u dans l'événement signé et ce que le serveur attend.

Contexte / Conditions de déclenchement

  • Le serveur retourne 401 Unauthorized pour les endpoints protégés NIP-98
  • Les logs montrent que la création du token a réussi (événement signé et validé)
  • La réponse d'erreur contient "URL mismatch" avec les URLs attendue et réelle
  • Les URLs diffèrent uniquement par les paramètres de requête

Exemple de réponse d'erreur :

{"error":"Auth failed: URL mismatch: expected .../notifications, got .../notifications?limit=50"}

Cause racine

La spec NIP-98 dit :

Le tag u DOIT être exactement identique à l'URL de requête absolue (y compris les paramètres de requête).

Mais les implémentations serveur varient :

  • Certains serveurs suivent la spec strictement (exigent les paramètres de requête dans le tag u)
  • Certains serveurs normalisent les URLs en supprimant les paramètres de requête avant la validation
  • Vous DEVEZ correspondre à ce que votre serveur spécifique fait

Solution

Étape 1 : Ajouter du logging pour voir l'erreur réelle

} else if (response.statusCode == 401) {
  Log.error(
    'NIP-98 auth failed (401)\n'
    'URL: $url\n'
    'Response: ${response.body}',  // <-- Ceci révèle le problème réel
    ...
  );
}

Étape 2 : Vérifier le message d'erreur

  • Si l'erreur dit "expected .../path?params, got .../path" → Inclure les paramètres de requête
  • Si l'erreur dit "expected .../path, got .../path?params" → Supprimer les paramètres de requête

Étape 3 : Ajuster la normalisation d'URL en conséquence

Pour les serveurs qui SUPPRIMENT les paramètres de requête (comme Divine Relay) :

final uri = Uri.parse(url);
// Le serveur supprime les paramètres de requête avant la validation NIP-98
final normalizedUrl = '${uri.scheme}://${uri.host}${uri.path}';

Pour les serveurs qui EXIGENT les paramètres de requête (selon la spec NIP-98) :

final uri = Uri.parse(url);
final normalizedUrl = uri.hasQuery
    ? '${uri.scheme}://${uri.host}${uri.path}?${uri.query}'
    : '${uri.scheme}://${uri.host}${uri.path}';

Vérification

  1. Après le correctif, les URLs dans le tag u doivent correspondre à ce que le serveur attend
  2. L'erreur 401 doit être remplacée par une authentification réussie (200)
  3. Vérifier les logs pour confirmer la correspondance des URLs

Exemple

Comportement de Divine Relay (supprime les paramètres de requête) :

  • URL de requête : https://relay.dvines.org/api/users/abc/notifications?limit=50
  • Le serveur valide contre : https://relay.dvines.org/api/users/abc/notifications
  • Le tag u doit être : https://relay.dvines.org/api/users/abc/notifications

Notes

  • La spec NIP-98 est claire sur l'inclusion des paramètres de requête, mais tous les serveurs ne la suivent pas
  • Toujours vérifier la réponse d'erreur réelle pour déterminer le comportement du serveur
  • En cas de doute, essayer les deux approches et voir celle qui fonctionne
  • Envisager de signaler un bug auprès des serveurs qui ne suivent pas la spec

Références

  • Spécification NIP-98 HTTP Auth
  • Citation de la spec : "Le tag u DOIT être exactement identique à l'URL de requête absolue (y compris les paramètres de requête)"
  • Réalité : Les implémentations serveur varient, toujours vérifier le comportement réel

Skills similaires