Démarrage rapide : Créer une application web avec Microsoft Planetary Computer Pro

Dans ce guide de démarrage rapide, vous créez une application web qui affiche des images satellites et des données géospatiales à partir de votre GeoCatalog sur une carte interactive. Vous authentifiez les utilisateurs avec l’ID Microsoft Entra, interrogez les collections STAC et affichez des vignettes de carte, toutes à partir du navigateur JavaScript.

Ce que vous apprenez :

  • Authentifier les utilisateurs et acquérir des jetons d’accès à l’aide de MSAL.js
  • Interroger l’API STAC pour découvrir des collections et des éléments
  • Afficher des vignettes raster sur une carte MapLibre GL avec des en-têtes d’autorisation
  • Créer des couches de mosaïque transparentes dans l’ensemble des collections
  • Télécharger des ressources brutes à l’aide de jetons SAP

Les modèles de code fonctionnent avec n’importe quelle infrastructure JavaScript moderne (React, Vue, Angular) ou JavaScript vanille. Les API GeoCatalog disposent d’une prise en charge CORS complète. Vous pouvez donc les appeler directement depuis localhost pendant le développement, sans proxy requis.

Vous pouvez télécharger et tester ce code à partir du dépôt GitHub public Microsoft Planetary Computer Pro.

Prerequisites

Vue d’ensemble de l’architecture

Une application web GeoCatalog classique suit cette architecture :

Diagramme montrant l’architecture d’une application web GeoCatalog avec un client de navigateur se connectant à Microsoft Entra ID pour l’authentification et aux API GeoCatalog pour l’accès aux données.

Inscrire votre application dans l’ID Microsoft Entra

Avant que votre application web puisse authentifier les utilisateurs, inscrivez-la dans Microsoft Entra ID. Ce guide de démarrage rapide utilise un enregistrement d'application à page unique (SPA), ce qui est idéal pour les applications JavaScript côté client et le développement local. Les modèles d’intégration d’API présentés dans les étapes ultérieures fonctionnent avec n’importe quel type d’application.

Note

Pour les applications de production avec un serveur principal, envisagez de choisir un autre type d’inscription (Web, Natif, etc.). Consultez Configurer l’authentification d’application pour obtenir des conseils sur le choix de l’approche appropriée pour votre scénario.

S’inscrire en tant qu’application à page unique

  1. Accédez à Microsoft Entra ID dans le portail Azure.
  2. Sélectionnez Inscriptions d’applications dans le volet latéral.
  3. Sélectionnez Nouvelle inscription.
  4. Entrez un nom pour votre application (par exemple, « GeoCatalog Web App »).
  5. Sous Types de comptes pris en charge, sélectionnez Comptes dans cet annuaire organisationnel uniquement.
  6. Sous URI de redirection, sélectionnez Application monopage (SPA) et entrez votre URL de développement (par exemple). http://localhost:5173
  7. Sélectionnez Inscrire.

Après l’inscription, notez les valeurs suivantes dans la page Vue d’ensemble :

  • ID d’application (client)
  • ID de l’annuaire (locataire)

Pour plus d’informations, consultez l'enregistrement de l'application Quickstart.

Accorder des autorisations d’API

Votre application doit être autorisée à appeler l’API GeoCatalog pour le compte des utilisateurs connectés :

  1. Dans l’inscription de votre application, sélectionnez Autorisations d’API>Ajouter une autorisation.
  2. Sélectionnez les API que mon organisation utilise et recherchez Azure Orbital Spatio.
  3. Sélectionnez Autorisations déléguées et vérifiez user_impersonation.
  4. Sélectionnez Ajouter des autorisations.
  5. Si vous êtes administrateur, sélectionnez Accorder le consentement de l’administrateur pour le compte de tous les utilisateurs de votre locataire.

Configuration de votre application

Votre application a besoin des valeurs de configuration suivantes. La façon dont vous fournissez ces valeurs dépend de vos outils de génération (variables d’environnement, fichiers de configuration, et ainsi de suite) :

Paramétrage Valeur Descriptif
URL du catalogue https://{name}.{region}.geocatalog.spatio.azure.com Votre point de terminaison GeoCatalog
ID du locataire Depuis l'inscription de l'application Votre locataire Microsoft Entra
ID de client Depuis l'inscription de l'application ID client de votre application
Étendue de l’API https://geocatalog.spatio.azure.com/.default Utilisez toujours cette valeur exacte

Installer des dépendances

Installez la bibliothèque d’authentification Microsoft (MSAL) pour les applications de navigateur et une bibliothèque de cartes :

npm install @azure/msal-browser maplibre-gl
  • @azure/msal-browser - Gère l’authentification OAuth 2.0 avec l’ID Microsoft Entra
  • maplibre-gl - Bibliothèque de cartes open source pour la visualisation des vignettes

Conseil / Astuce

Structure du projet : Les exemples de code de ce démarrage rapide sont des fonctions autonomes que vous pouvez organiser comme vous le souhaitez. Modèle courant :

  • auth.js: fonctions de configuration MSAL et de jeton
  • api.js: API STAC, API Tiler et fonctions de jeton SAS
  • map.js: Initialisation mapLibre et gestion des couches de mosaïques
  • App.js ou main.js : Connectez tout avec votre interface utilisateur

Chaque fonction reçoit ses dépendances (jetons d’accès, URL) en tant que paramètres, ce qui facilite leur intégration dans n’importe quelle structure de framework ou de projet.

Implémenter l’authentification MSAL

Capture d’écran montrant le flux d’authentification dans un exemple d’application web.

Configurez MSAL pour l’authentification du navigateur. L’exemple suivant montre la configuration clé et le modèle d’acquisition de jeton :

import { PublicClientApplication, InteractionRequiredAuthError } from '@azure/msal-browser';

// Configuration - replace with your values or load from environment/config
const msalConfig = {
  auth: {
    clientId: 'YOUR_CLIENT_ID',
    authority: 'https://login.microsoftonline.com/YOUR_TENANT_ID',
    redirectUri: window.location.origin,
  },
  cache: {
    cacheLocation: 'sessionStorage',
    storeAuthStateInCookie: false,
  },
};

// Create MSAL instance
const msalInstance = new PublicClientApplication(msalConfig);

// GeoCatalog API scope - always use this exact value
const scopes = ['https://geocatalog.spatio.azure.com/.default'];

/**
 * Acquire an access token for GeoCatalog API calls.
 * Tries silent acquisition first, falls back to popup if needed.
 */
async function getAccessToken() {
  const account = msalInstance.getActiveAccount() || msalInstance.getAllAccounts()[0];
  
  if (!account) {
    throw new Error('No authenticated account. Call login() first.');
  }

  try {
    // Try silent token acquisition (uses cached token)
    const result = await msalInstance.acquireTokenSilent({ account, scopes });
    return result.accessToken;
  } catch (error) {
    // If silent fails (token expired), fall back to popup
    if (error instanceof InteractionRequiredAuthError) {
      const result = await msalInstance.acquireTokenPopup({ scopes });
      return result.accessToken;
    }
    throw error;
  }
}

/**
 * Sign in the user via popup.
 */
async function login() {
  const result = await msalInstance.loginPopup({ scopes });
  msalInstance.setActiveAccount(result.account);
  return result.account;
}

/**
 * Sign out the user.
 */
function logout() {
  msalInstance.logoutPopup();
}

API STAC : Interroger des collections et des éléments

L’API STAC GeoCatalog fournit des points de terminaison pour découvrir et interroger des données géospatiales. Toutes les requêtes nécessitent un en-tête Authorization avec un jeton Bearer obtenu à partir de l'implémentation de l'authentification MSAL.

Lister les collections

Capture d’écran montrant la liste des collections STAC dans un exemple d’application web.

const API_VERSION = '2026-04-15';

async function listCollections(accessToken, catalogUrl) {
  const url = `${catalogUrl}/stac/collections?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
    },
  });
  
  if (!response.ok) {
    throw new Error(`Failed to list collections: ${response.statusText}`);
  }
  
  const data = await response.json();
  return data.collections; // Array of STAC Collection objects
}

Répertorier les éléments d’une collection

Capture d’écran montrant la liste des éléments STAC dans un exemple d’application web.

const API_VERSION = '2026-04-15';

async function listItems(accessToken, catalogUrl, collectionId, limit = 10) {
  const url = `${catalogUrl}/stac/collections/${collectionId}/items?limit=${limit}&api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
    },
  });
  
  if (!response.ok) {
    throw new Error(`Failed to list items: ${response.statusText}`);
  }
  
  const data = await response.json();
  return data.features; // Array of STAC Item objects
}

Rechercher dans plusieurs collections

Capture d’écran montrant comment utiliser la recherche STAC pour retourner des éléments intéressants.

const API_VERSION = '2026-04-15';

async function searchItems(accessToken, catalogUrl, searchParams) {
  const url = `${catalogUrl}/stac/search?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(searchParams),
  });
  
  if (!response.ok) {
    throw new Error(`Search failed: ${response.statusText}`);
  }
  
  return await response.json();
}

// Example usage:
const results = await searchItems(token, catalogUrl, {
  collections: ['my-collection'],
  bbox: [-122.5, 37.5, -122.0, 38.0],  // [west, south, east, north]
  datetime: '2024-01-01/2024-12-31',
  limit: 20,
});

URL de tuiles : Générer des URL pour la visualisation de cartes

L’API GeoCatalog Tiler sert les données raster comme vignettes cartographiques. Construire des URL de tuiles avec le modèle suivant :

Vignettes d’élément unique

Capture d’écran montrant comment afficher des vignettes pour un seul élément.

{catalogUrl}/data/mosaic/collections/{collectionId}/items/{itemId}/tiles/{z}/{x}/{y}@1x.png
  ?api-version=2026-04-15
  &tileMatrixSetId=WebMercatorQuad
  &assets=visual

Fonction Générateur d’URL de vignette

const API_VERSION = '2026-04-15';

/**
 * Build a tile URL template for a STAC item.
 * Returns a URL with {z}/{x}/{y} placeholders for use with map libraries.
 */
function buildTileUrl(catalogUrl, collectionId, itemId, options = {}) {
  const { assets = 'visual', colormap, rescale } = options;
  
  const base = `${catalogUrl}/data/mosaic/collections/${collectionId}/items/${itemId}/tiles/{z}/{x}/{y}@1x.png`;
  
  const params = new URLSearchParams();
  params.set('api-version', API_VERSION);
  params.set('tileMatrixSetId', 'WebMercatorQuad');
  params.set('assets', assets);
  
  if (colormap) params.set('colormap_name', colormap);
  if (rescale) params.set('rescale', rescale);
  
  return `${base}?${params.toString()}`;
}

// Example usage:
const tileUrl = buildTileUrl(
  'https://mygeocatalog.northcentralus.geocatalog.spatio.azure.com',
  'aerial-imagery',
  'image-001',
  { assets: 'visual' }
);

Paramètres de vignette clé

Paramètre Obligatoire Descriptif
api-version Oui Version de l’API (2026-04-15)
tileMatrixSetId Oui Utiliser WebMercatorQuad pour les cartes web
assets Oui Noms des ressources à afficher (exemple : visual, image)
colormap_name Non Palette de couleurs nommée (Exemple : viridis, terrain)
rescale Non Plage de valeurs pour la mise à l’échelle (exemple : 0,255)
asset_bidx Non Index de bande (exemple : image\|1,2,3 pour RVB)

Note

Pour les collections avec des images à quatre bandes (comme NAIP avec RVB + NIR), utilisez asset_bidx=image|1,2,3 pour sélectionner uniquement les bandes RVB. Le tiler ne peut pas encoder quatre bandes en tant que PNG.


Intégration de la carte : afficher des vignettes avec MapLibre GL

Les bibliothèques cartographiques telles que MapLibre GL, Leaflet et OpenLayers peuvent afficher des vignettes raster. Le défi clé consiste à ajouter des en-têtes d’autorisation aux demandes de vignettes, car ces bibliothèques extraient directement des vignettes.

Exemple d'utilisation de MapLibre GL

MapLibre GL offre une option transformRequest permettant d’injecter des en-têtes :

import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';

// Store the current access token
let currentAccessToken = null;

function initializeMap(containerId, accessToken) {
  currentAccessToken = accessToken;
  
  const map = new maplibregl.Map({
    container: containerId,
    style: {
      version: 8,
      sources: {
        osm: {
          type: 'raster',
          tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
          tileSize: 256,
          attribution: '© OpenStreetMap contributors',
        },
      },
      layers: [{ id: 'osm', type: 'raster', source: 'osm' }],
    },
    center: [0, 0],
    zoom: 2,
    // Add authorization header to tile requests
    transformRequest: (url, resourceType) => {
      // Only add auth for GeoCatalog tile requests
      if (url.includes('geocatalog.spatio.azure.com') && currentAccessToken) {
        return {
          url,
          headers: { 'Authorization': `Bearer ${currentAccessToken}` },
        };
      }
      return { url };
    },
  });
  
  return map;
}

function addTileLayer(map, tileUrl, bounds) {
  // Remove existing layer and source if present
  if (map.getLayer('data-layer')) {
    map.removeLayer('data-layer');
  }
  if (map.getSource('data-tiles')) {
    map.removeSource('data-tiles');
  }
  
  // Add tile source
  map.addSource('data-tiles', {
    type: 'raster',
    tiles: [tileUrl],
    tileSize: 256,
    minzoom: 10,  // Many aerial collections require zoom 10+
    maxzoom: 18,
  });
  
  // Add tile layer
  map.addLayer({
    id: 'data-layer',
    type: 'raster',
    source: 'data-tiles',
  });
  
  // Zoom to bounds [west, south, east, north]
  if (bounds) {
    map.fitBounds([[bounds[0], bounds[1]], [bounds[2], bounds[3]]], { padding: 50 });
  }
}

Important

La transformRequest fonction est appelée pour chaque demande de vignette. Stockez le jeton d’accès dans une variable qui transformRequest peut y accéder et mettez-le à jour lors de l’actualisation du jeton.


Mosaïques : Affichage d’images à l’échelle de la collection

Capture d’écran montrant comment afficher des mosaïques pour une collection.

Pour afficher tous les éléments d’une collection en tant que couche transparente, inscrivez une recherche en mosaïque et utilisez l’ID de recherche retourné :

const API_VERSION = '2026-04-15';

/**
 * Register a mosaic search for a collection.
 * Returns a search ID that can be used to fetch mosaic tiles.
 */
async function registerMosaic(catalogUrl, collectionId, accessToken) {
  const url = `${catalogUrl}/data/mosaic/register?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      collections: [collectionId],
    }),
  });
  
  if (!response.ok) {
    throw new Error(`Failed to register mosaic: ${response.statusText}`);
  }
  
  const data = await response.json();
  // Note: API returns 'searchid' (lowercase), not 'searchId'
  return data.searchid;
}

/**
 * Build a mosaic tile URL template.
 */
function buildMosaicTileUrl(catalogUrl, searchId, collectionId, options = {}) {
  const { assets = 'visual' } = options;
  
  const base = `${catalogUrl}/data/mosaic/searches/${searchId}/tiles/{z}/{x}/{y}@1x.png`;
  
  const params = new URLSearchParams();
  params.set('api-version', API_VERSION);
  params.set('tileMatrixSetId', 'WebMercatorQuad');
  params.set('collection', collectionId);
  params.set('assets', assets);
  
  return `${base}?${params.toString()}`;
}

Jetons SAP : télécharger des ressources brutes

L’API SAS fournit des jetons à durée limitée pour télécharger des fichiers d'actifs bruts (GeoTIFFs, COGs et autres fichiers) directement à partir du Stockage Blob Azure. Utilisez cette option lorsque vous avez besoin des fichiers sources d’origine plutôt que des vignettes rendues.

Important

Les jetons SAP activent uniquement les téléchargements dans les applications de navigateur. En raison des stratégies CORS de l'Stockage Blob Azure, les navigateurs ne peuvent pas lire les données des objets blob via JavaScript fetch(). Consultez la section Limitations du navigateur .

Capture d’écran montrant comment télécharger des ressources à l’aide d’un jeton SAP.

Obtenir un jeton SAP

const API_VERSION = '2026-04-15';

/**
 * Get a SAS token for accessing assets in a collection.
 * Returns a token string that can be appended to asset URLs.
 */
async function getCollectionSasToken(accessToken, catalogUrl, collectionId) {
  const url = `${catalogUrl}/sas/token/${collectionId}?api-version=${API_VERSION}`;
  
  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
    },
  });
  
  if (!response.ok) {
    throw new Error(`Failed to get SAS token: ${response.statusText}`);
  }
  
  const data = await response.json();
  return data.token; // SAS token string
}

Générer une URL de téléchargement signée

/**
 * Build a signed URL for downloading an asset.
 * Appends the SAS token to the asset's href.
 */
function buildSignedAssetUrl(assetHref, sasToken) {
  const separator = assetHref.includes('?') ? '&' : '?';
  return `${assetHref}${separator}${sasToken}`;
}

// Example usage:
const sasToken = await getCollectionSasToken(accessToken, catalogUrl, 'my-collection');
const assetHref = item.assets['visual'].href;
const signedUrl = buildSignedAssetUrl(assetHref, sasToken);

Déclencher un téléchargement de fichier

/**
 * Trigger a browser download for an asset file.
 * Works by creating a temporary anchor element.
 */
function downloadAsset(signedUrl, filename) {
  const link = document.createElement('a');
  link.href = signedUrl;
  link.download = filename || 'download';
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);
}

// Example: Download an asset
downloadAsset(signedUrl, 'aerial-image.tif');

Limitations du navigateur

Les jetons SAP fonctionnent différemment dans les navigateurs et dans le code côté serveur :

Cas d’usage Browser Server-side
Télécharger des fichiers (l’utilisateur sélectionne le lien) ✅ Fonctionne ✅ Fonctionne
Lire les données de blob via fetch() ❌ CORS bloqué ✅ Fonctionne
Traiter les pixels bruts en JavaScript ❌ Impossible ✅ Fonctionne

Les téléchargements du navigateur fonctionnent, car la navigation (en cliquant sur des liens) contourne CORS. Toutefois, les fetch() demandes adressées au stockage Blob Azure sont bloquées, car le compte de stockage n’inclut pas l’origine de votre application dans sa stratégie CORS.

Si votre application doit lire et traiter des données de ressources brutes dans le navigateur, implémentez un proxy côté serveur :

Note

Le code suivant est un exemple simplifié pour illustrer le modèle proxy. Pour les applications de production, votre point de terminaison proxy doit authentifier les demandes (par exemple, en transférant le jeton du porteur de l’utilisateur ou à l’aide de l’authentification de session) et vérifier que l’utilisateur est autorisé à accéder aux ressources demandées.

// ❌ Browser: This fails due to CORS
const response = await fetch(signedUrl);
const data = await response.arrayBuffer(); // Error!

// ✅ Browser: Call your backend instead
const response = await fetch('/api/proxy-asset', {
  method: 'POST',
  body: JSON.stringify({ collectionId, itemId, assetName })
});
const data = await response.json(); // Works!

Votre back-end peut récupérer l’objet blob à l’aide du jeton SAP et retourner les résultats traités.


Considérations relatives au développement

Prise en charge de CORS

Les API GeoCatalog incluent la prise en charge complète de CORS avec Access-Control-Allow-Origin: *. Les applications basées sur un navigateur peuvent effectuer des requêtes directes vers GeoCatalog à partir de n’importe quelle origine, y compris http://localhost pendant le développement. Aucun proxy ou solution de contournement n’est nécessaire.

L’API autorise l’en-tête Authorization dans les requêtes CORS. Les appels authentifiés fetch() fonctionnent donc directement à partir du javaScript du navigateur.

Choix de la méthode d’accès aux données appropriée

Méthode Navigateur fetch() Téléchargements du navigateur Server-side Idéal pour
Tiler API ✅ Entièrement pris en charge ✅ Oui ✅ Oui Visualisation de carte
Jetons SAP ❌ CORS bloqué ✅ Oui ✅ Oui Téléchargements de fichiers bruts
  • API Tiler : permet d’afficher des images sur des cartes. Retourne des vignettes PNG ou WebP rendues avec prise en charge complète de CORS. Consultez URL de vignette et Intégration de la carte.

  • Jetons SAS : permet de télécharger des fichiers sources d’origine (GeoTIFFs, COGs). Les téléchargements du navigateur fonctionnent, mais fetch() est bloqué par les stratégies CORS d'Stockage Blob Azure. Pour plus d’informations et de solutions de contournement, consultez les jetons SAP .

Actualisation des jetons

Les jetons d’accès expirent généralement après une heure. Votre application doit :

  1. Gérez les erreurs 401 en acquérant un nouveau jeton.
  2. Utilisez l’acquisition de jetons silencieuse de MSAL, qui actualise automatiquement les jetons expirés.
  3. Mettez à jour la référence de jeton utilisée par la carte transformRequest.

Gestion des erreurs

Gérez les scénarios d’erreur courants :

État HTTP La cause Solution
401 Jeton expiré ou non valide Actualiser le jeton d’accès
404 Élément ou collection introuvable Vérifier que les ID existent
424 Tuile en dehors de l'étendue des données Attendu - traiter avec élégance

Résolution des problèmes

Erreur La cause Solution
« AADSTS50011 : Incompatibilité de l’URL de réponse » L'URI de redirection dans le code ne correspond pas à l'enregistrement de Microsoft Entra ID Ajoutez votre URL de développement (par exemple http://localhost:3000) en tant qu’URI de redirection SPA dans l’enregistrement de votre application
Erreur « Étendue non valide » Utilisation de l’URL GeoCatalog au lieu de l’étendue de l’API Utiliser https://geocatalog.spatio.azure.com/.default comme étendue
401 Non autorisé sur les demandes de vignette Bibliothèque de cartes sans en-têtes d'authentification Utiliser transformRequest (MapLibre) pour ajouter le jeton du porteur ; vérifiez que le jeton est actif
Les vignettes ne s’alignent pas sur le mappage de base Jeu de matrices de tuiles incorrect Utiliser tileMatrixSetId=WebMercatorQuad pour la projection Web Mercator (EPSG :3857)
« Impossible de décoder l’image » Nom de ressource incorrect, image multibande ou étendue de données externe Recherchez des noms valides avec item_assets, utilisez asset_bidx=image\|1,2,3 pour le RVB, et attendez-vous à des erreurs 404/424 en dehors de la couverture.

Étapes suivantes