Backgrounds avec authentification

Ce guide montre comment ajouter différents types de fonds de plan avec authentification en utilisant IdentityManager.

Types d'identité disponibles

L'IdentityManager supporte plusieurs types d'identité :

  • TOKEN : Token en clair
  • IDENTITY : Information d'identité en clair (objet ou string)
  • LOCALSTORAGE : Identité stockée dans le localStorage
  • URL : Identité demandée à un service tiers
  • FUNCTION : Identité récupérée via une fonction

Méthodes d'application (apply)

  • query : Ajoute l'identité en paramètre d'URL
  • header : Ajoute un header personnalisé
  • headers : Ajoute plusieurs headers (identité = objet)
  • bearer : Ajoute un header Authorization: Bearer <token>
  • basic : Ajoute un header Authorization: Basic <base64>
  • cookie : Ajoute un cookie

1. WMTS avec Bearer Token

Utilisation d'un token Bearer pour accéder à un service WMTS protégé.

// Source d'identité partagée avec Bearer
await kmapvInstance.addIdentitySource({
  id: 'wmts-service',
  type: 'TOKEN',
  token: 'votre-token-jwt',
  apply: {
    type: 'bearer'
  },
  refreshInterval: 3600000 // Rafraîchir toutes les heures
});

// Ajout du fond WMTS
await kmapvInstance.backgroundLayer.addBackgroundLayer(
  'fond-wmts-protege',
  'wmts',
  {
    title: 'WMTS Protégé (Bearer)',
    url: 'https://example.com/wmts/getcapabilities',
    identity: {
      id: 'wmts-service'
    },
    params: {
      layer: 'NomDuLayer',
      tileMatrixSet: 'EPSG:3857'
    }
  }
);

2. Layer XYZ avec Query Parameter

Token ajouté en paramètre d'URL pour un service de tuiles XYZ.

// Identité directement sur le layer
kmapvInstance.backgroundLayer.addBackgroundLayer(
  'xyz-avec-token',
  'layerXYZ',
  {
    title: 'XYZ avec token URL',
    url: 'https://tiles.example.com/{z}/{x}/{y}.png',
    identity: {
      type: 'TOKEN',
      token: 'abc123xyz',
      apply: {
        type: 'query',
        name: 'apikey' // Résultat : ?apikey=abc123xyz
      }
    }
  }
);

3. WMS Tuilé avec Basic Auth

Authentification Basic pour un WMS tuilé.

// Option 1 : Username/Password en clair (déconseillé en production)
kmapvInstance.backgroundLayer.addBackgroundLayer(
  'wms-tiled-basic',
  'wmstiled',
  {
    title: 'WMS Tuilé (Basic Auth)',
    url: 'https://wms.example.com/service',
    projection: 'EPSG:3857',
    identity: {
      type: 'IDENTITY',
      identity: {
        username: 'user',
        password: 'pass'
      },
      apply: {
        type: 'basic'
      }
    },
    params: {
      LAYERS: 'layer1,layer2'
    }
  }
);

// Option 2 : Via service d'authentification
kmapvInstance.backgroundLayer.addBackgroundLayer(
  'wms-tiled-basic-url',
  'wmstiled',
  {
    title: 'WMS Tuilé (Basic via URL)',
    url: 'https://wms.example.com/service',
    identity: {
      type: 'url',
      url: 'https://auth.example.com/api/getCredentials',
      method: 'GET',
      apply: {
        type: 'basic'
      },
      refreshInterval: 1800000 // 30 minutes
    },
    params: {
      LAYERS: 'cadastre'
    }
  }
);

4. WMS Non-tuilé avec Headers multiples

Plusieurs headers d'authentification pour un WMS non-tuilé.

// Source partagée avec headers multiples
await kmapvInstance.addIdentitySource({
  id: 'multi-headers-auth',
  type: 'IDENTITY',
  identity: {
    'Authorization': 'Bearer xyz789',
    'X-Api-Key': 'ma-cle-api',
    'X-Client-Id': 'mon-client-id'
  },
  apply: {
    type: 'headers'
  }
});

kmapvInstance.backgroundLayer.addBackgroundLayer(
  'wms-untiled-headers',
  'wmsuntiled',
  {
    title: 'WMS Non-tuilé (Multi-headers)',
    url: 'https://wms-secure.example.com/service',
    identity: {
      id: 'multi-headers-auth'
    },
    params: {
      LAYERS: 'reseau-hydraulique',
      STYLES: 'style-default'
    }
  }
);

5. Vector (WFS) avec Basic Auth

Source vectorielle WFS avec authentification.

// Option 1 : Basic auth avec username/password
kmapvInstance.dataLayer.addDataLayer({
  title: 'WFS Protégé (Basic)',
  layerId: 'wfs-basic',
  style: monStyle,
  wfs: {
    url: 'https://wfs.example.com/service',
    projection: 'EPSG:3946',
    geometryName: 'geometry',
    identity: {
      type: 'IDENTITY',
      identity: {
        username: 'user',
        password: 'pass'
      },
      apply: {
        type: 'basic'
      }
    },
    params: {
      typename: 'namespace:layer'
    }
  }
});

// Option 2 : Via fonction personnalisée
kmapvInstance.dataLayer.addDataLayer({
  title: 'WFS Protégé (Function)',
  layerId: 'wfs-function',
  style: monStyle,
  wfs: {
    url: 'https://wfs.example.com/service',
    identity: {
      type: 'FUNCTION',
      getIdentity: async () => {
        // Logique personnalisée pour obtenir les credentials
        const response = await fetch('/api/get-wfs-credentials');
        const data = await response.json();
        return {
          username: data.user,
          password: data.pass
        };
      },
      apply: {
        type: 'basic'
      },
      refreshInterval: 600000 // 10 minutes
    },
    params: {
      typename: 'mon:calque'
    }
  }
});

6. Vector Tile avec JWT Token

Tuiles vectorielles avec authentification JWT.

// Source partagée pour plusieurs vector tiles
await kmapvInstance.addIdentitySource({
  id: 'geoservice',
  type: 'url',
  method: 'POST',
  url: 'https://services.example.com/api/auth/login',
  auth: {
    username: 'monuser',
    password: 'monpass'
  },
  responseIdentityName: 'token', // Nom de la propriété dans la réponse JSON
  apply: {
    type: 'query',
    name: 'jwt' // Ajouté comme ?jwt=<token>
  },
  refreshInterval: 3600000 // 1 heure
});

// Vector Tile OSM Basic
await kmapvInstance.backgroundLayer.addBackgroundLayer(
  'vector-osm-basic',
  'vectorTile',
  {
    title: 'OSM Basic (Vector Tile)',
    styleUrl: 'https://services.example.com/styles/osm-basic/style.json',
    identity: {
      id: 'geoservice'
    }
  }
);

// Vector Tile Cadastre
await kmapvInstance.backgroundLayer.addBackgroundLayer(
  'vector-cadastre',
  'vectorTile',
  {
    title: 'Cadastre (Vector Tile)',
    styleUrl: 'https://services.example.com/styles/cadastre/style.json',
    identity: {
      id: 'geoservice'
    }
  }
);

7. LocalStorage avec Header personnalisé

Récupération du token depuis le localStorage.

// Stocker le token dans localStorage (à faire au préalable)
localStorage.setItem('MY_MAP_TOKEN', JSON.stringify({
  accessToken: 'mon-token-xyz',
  expiresAt: Date.now() + 3600000
}));

// Utilisation du token depuis localStorage
kmapvInstance.backgroundLayer.addBackgroundLayer(
  'fond-localstorage',
  'layerXYZ',
  {
    title: 'XYZ avec LocalStorage',
    url: 'https://secure-tiles.example.com/{z}/{x}/{y}.png',
    identity: {
      type: 'LOCALSTORAGE',
      path: 'MY_MAP_TOKEN',
      responseIdentityName: 'accessToken',
      apply: {
        type: 'header',
        name: 'X-Access-Token',
        scheme: 'Token' // Résultat : X-Access-Token: Token <value>
      }
    }
  }
);

8. ArcGIS avec Token en Query

Service ArcGIS REST avec token.

// Token statique
kmapvInstance.backgroundLayer.addBackgroundLayer(
  'arcgis-token',
  'arcgis',
  {
    title: 'ArcGIS (Token)',
    url: 'https://services.arcgis.com/xyz/arcgis/rest/services/MyMap/MapServer',
    identity: {
      type: 'TOKEN',
      token: 'mon-token-arcgis',
      apply: {
        type: 'query',
        name: 'token'
      }
    }
  }
);

// Token dynamique via URL
kmapvInstance.backgroundLayer.addBackgroundLayer(
  'arcgis-dynamic-token',
  'arcgis',
  {
    title: 'ArcGIS (Token dynamique)',
    url: 'https://services.arcgis.com/xyz/arcgis/rest/services/MyMap/MapServer',
    identity: {
      type: 'url',
      url: 'https://arcgis.example.com/tokens/generate',
      method: 'POST',
      data: {
        username: 'user',
        password: 'pass',
        client: 'referer',
        referer: window.location.origin,
        expiration: 60,
        f: 'json'
      },
      responseIdentityName: 'token',
      apply: {
        type: 'query',
        name: 'token'
      },
      refreshInterval: 3000000 // 50 minutes
    }
  }
);

9. Exemple complet avec gestion d'erreur

Exemple robuste avec gestion d'erreur et rafraîchissement.

// Fonction pour gérer l'authentification avec retry
async function setupSecureBackground() {
  try {
    // Créer une source d'identité avec gestion d'erreur
    await kmapvInstance.addIdentitySource({
      id: 'secure-service',
      type: 'url',
      url: 'https://auth.example.com/api/token',
      method: 'POST',
      data: {
        grant_type: 'client_credentials',
        client_id: 'my-client-id',
        client_secret: 'my-secret'
      },
      responseIdentityName: 'access_token',
      apply: {
        type: 'bearer'
      },
      refreshInterval: 2700000 // 45 minutes (token valide 1h)
    });

    // Ajouter le fond de plan
    await kmapvInstance.backgroundLayer.addBackgroundLayer(
      'secure-background',
      'wmts',
      {
        title: 'Fond sécurisé',
        url: 'https://secure-wmts.example.com/service',
        identity: {
          id: 'secure-service'
        },
        params: {
          layer: 'secure-layer'
        }
      }
    );

    console.log('Fond de plan sécurisé ajouté avec succès');
  } catch (error) {
    console.error('Erreur lors de l\'ajout du fond sécurisé:', error);
    // Gérer l'erreur (afficher un message à l'utilisateur, etc.)
  }
}

setupSecureBackground();

Utilisation de cookies pour l'authentification (rare mais possible).

kmapvInstance.backgroundLayer.addBackgroundLayer(
  'wms-cookie-auth',
  'wmstiled',
  {
    title: 'WMS avec Cookie',
    url: 'https://wms.example.com/service',
    identity: {
      type: 'TOKEN',
      token: 'session-id-xyz789',
      apply: {
        type: 'cookie',
        name: 'SESSIONID' // Cookie: SESSIONID=session-id-xyz789
      }
    },
    params: {
      LAYERS: 'data-layer'
    }
  }
);

Bonnes pratiques

Sécurité

  1. Ne jamais hardcoder les credentials en production
  2. Utiliser HTTPS pour toutes les requêtes d'authentification
  3. Implémenter le rafraîchissement automatique avec refreshInterval
  4. Gérer les erreurs d'authentification proprement
  5. Utiliser des tokens temporaires plutôt que des mots de passe

Performance

  1. Partager les sources d'identité entre plusieurs calques via addIdentitySource()
  2. Configurer refreshInterval légèrement avant l'expiration réelle du token
  3. Mettre en cache les tokens dans localStorage quand approprié

Code

// ✅ BON : Source partagée
await kmapvInstance.addIdentitySource({
  id: 'shared-auth',
  type: 'url',
  url: 'https://auth.example.com/token',
  // ...
});

// Réutiliser pour plusieurs layers
layer1.identity = { id: 'shared-auth' };
layer2.identity = { id: 'shared-auth' };
layer3.identity = { id: 'shared-auth' };

// ❌ MAUVAIS : Duplication
layer1.identity = { type: 'url', url: '...', /* config complète */ };
layer2.identity = { type: 'url', url: '...', /* config complète */ };
layer3.identity = { type: 'url', url: '...', /* config complète */ };

Débogage

Pour déboguer les problèmes d'authentification :

// Activer les logs de l'identity manager
kmapvInstance.on('identity:error', (event) => {
  console.error('Erreur d\'identité:', event);
});

// Vérifier l'état d'une source
const identityManager = kmapvInstance.getIdentityManager('my-source-id');
console.log('Token actuel:', identityManager.identity);

// L'identité est automatiquement rafraîchie lors des appels getRequest()
// si refreshInterval est configuré et que le délai est dépassé

Rafraîchissement automatique

L'IdentityManager récupère l'identité à la demande lors du premier appel à getRequest(), puis la rafraîchit automatiquement si refreshInterval est configuré et que le délai d'expiration est dépassé. Plus besoin d'appeler init() ou restart() manuellement !

Références

Dernière mise à jour:
Contributors: David Hequet