Flux pour application native
Utilisez le flux Native app pour les intégrations qui agissent au nom d’un utilisateur connecté depuis sa propre machine, comme une application de bureau, un outil CLI ou un plugin CAO. Il utilise Authorization Code avec PKCE, une redirection loopback localhost et aucun client secret. Ce guide vous accompagne de la création de l’application OAuth jusqu’à votre premier appel API.
Consultez d’abord le guide Premiers pas si vous n’avez pas encore couvert les prérequis, l’accès réseau et le modèle de sécurité.
Ce que vous allez faire
Section intitulée « Ce que vous allez faire »- Créer une application OAuth : enregistrer une application native dans Prevu3D et obtenir un Client ID
- Configurer l’accès utilisateur : vous assurer que l’utilisateur qui se connecte peut atteindre les données nécessaires
- Autoriser avec PKCE : envoyer l’utilisateur vers la page de consentement dans le navigateur
- Échanger le code contre un jeton : échanger le code d’autorisation contre un jeton d’accès
- Trouver votre URL d’API : découvrir l’URL de base de votre organisation (elle varie selon la région)
- Effectuer votre premier appel : tester la connexion avec une requête simple
Étape 1 : Créer votre application OAuth
Section intitulée « Étape 1 : Créer votre application OAuth »- Connectez-vous à la Prevu3D Platform (ou à votre environnement de préproduction).
- Allez dans Settings → OAuth.
- Cliquez pour créer une nouvelle application.
- Activez Authorization Code flow.
- Activez Native Application. L’URI de redirection est fixée à
http://localhost. - Laissez le client secret désactivé. Les applications natives n’en utilisent pas.
- Copiez et stockez votre Client ID en lieu sûr. Vous en aurez besoin pour chaque autorisation.
Étape 2 : Configurer l’accès utilisateur
Section intitulée « Étape 2 : Configurer l’accès utilisateur »Le flux natif appelle l’API en tant qu’utilisateur connecté, et non en tant qu’utilisateur de service. Cela concerne les couches 2 et 3 du modèle de sécurité : quels nœuds l’utilisateur peut voir (accès au contenu) et ce qu’il peut en faire (accès par rôle / permission).
- Assurez-vous que l’utilisateur qui se connectera dispose d’un accès au contenu aux nœuds (organisations, divisions, sites, etc.) requis par votre cas d’usage.
- Assurez-vous que l’utilisateur dispose d’un rôle sur ces nœuds avec les permissions dont votre intégration a besoin (lecture, modification, gestion, etc.).
Sur l’écran de consentement, l’utilisateur sélectionne également l’organisation à autoriser. Les scopes approuvés à cet endroit configurent la couche 1.
Étape 3 : Autoriser avec PKCE
Section intitulée « Étape 3 : Autoriser avec PKCE »Les applications natives ne peuvent pas conserver de secret, le flux utilise donc PKCE pour protéger le code d’autorisation. Avant d’ouvrir la page de consentement, générez trois valeurs :
| Valeur | Méthode |
|---|---|
code_verifier | Chaîne aléatoire de 43 à 128 caractères |
code_challenge | BASE64URL(SHA256(code_verifier)) sans padding |
state | Chaîne aléatoire ; validez-la au retour de la redirection |
Démarrez un serveur loopback local sur un port libre, puis ouvrez le navigateur de l’utilisateur sur la page de consentement.
URL de consentement production : https://cloud.prevu3d.com/oauth
URL de consentement préproduction : https://cloud.preproduction.prevu3d-int.com/oauth
Paramètres de requête (tous obligatoires) :
| Paramètre | Valeur |
|---|---|
response_type | code |
code_challenge_method | S256 |
client_id | Votre Client ID |
redirect_uri | Votre URI loopback, par ex. http://localhost:8765 (inclure le port, sans barre oblique finale) |
scopes | Un paramètre par scope, par ex. scopes=read:basic&scopes=read:hierarchy |
code_challenge | Le challenge PKCE généré ci-dessus |
state | Votre valeur state aléatoire |
Après que l’utilisateur s’est connecté et a cliqué sur Allow, le navigateur redirige vers votre URI loopback :
http://localhost:8765/?code={authorization_code}&state={state}Si l’utilisateur refuse l’accès, vous recevez ?error=access_denied à la place. Les codes d’autorisation expirent après 60 secondes, échangez-les donc immédiatement.
Étape 4 : Échanger le code contre un jeton d’accès
Section intitulée « Étape 4 : Échanger le code contre un jeton d’accès »Point de terminaison : POST https://cloud-api.prevu3d.com/oauth/token
En-têtes : Content-Type: application/x-www-form-urlencoded
Corps :
| Champ | Valeur |
|---|---|
grant_type | authorization_code |
client_id | Votre Client ID |
code | Code reçu lors de la redirection |
redirect_uri | La même URI qu’à l’étape 3 (port inclus) |
code_verifier | Le verifier PKCE d’origine |
N’envoyez pas de client secret pour les applications natives.
Exemple de réponse :
{ "hasError": false, "expires_in": 86400, "access_token": "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9...", "refresh_token": "..."}Enregistrez les deux jetons. Utilisez l’access_token pour les appels API. Lorsqu’il expire, demandez-en un nouveau avec grant_type=refresh_token et votre refresh_token stocké (aucun client secret requis).
Étape 5 : Obtenir votre URL de base d’API
Section intitulée « Étape 5 : Obtenir votre URL de base d’API »Appelez le point de terminaison de découverte pour obtenir l’apiUrl de votre organisation. Ne codez pas une URL régionale en dur.
Point de terminaison : GET https://cloud-api.prevu3d.com/oauth/api-info
En-têtes : Authorization: Bearer <your_access_token>
Exemple de réponse :
{ "user": { "..." : "..." }, "organization": { "id": "217ebd23-ec54-4af0-a6d6-4a441a6d1966", "name": "Test Organization" }, "scopes": ["read:basic", "read:hierarchy"], "apiUrl": "https://api-ue1.prevu3d.com/realityconnect-api"}Utilisez la valeur apiUrl comme base pour tous vos appels API. Notez également l’organization.id, dont vous aurez besoin pour de nombreux points de terminaison.
Étape 6 : Effectuer votre premier appel API
Section intitulée « Étape 6 : Effectuer votre premier appel API »Vous avez maintenant tout ce qu’il faut : un jeton d’accès et votre URL de base. Effectuons une requête simple pour récupérer les divisions de votre organisation :
GET {apiUrl}/v1/nodes/{organization_id}/browseAuthorization: Bearer <your_access_token>Exemple avec des valeurs réelles :
GET https://api-ue1.prevu3d.com/realityconnect-api/v1/nodes/217ebd23-ec54-4af0-a6d6-4a441a6d1966/browse HTTP/1.1Authorization: Bearer eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9...Une réponse réussie contenant une liste de divisions confirme que votre intégration fonctionne correctement.
Essayer avec Python
Section intitulée « Essayer avec Python »Voici un script complet qui réalise tout ce qui précède. Remplacez client_id par votre Client ID, puis exécutez-le. Il démarre un serveur loopback temporaire, ouvre la page de consentement dans votre navigateur et affiche les divisions de votre organisation une fois que vous avez approuvé.
import base64import hashlibimport jsonimport secretsimport webbrowserfrom http.server import BaseHTTPRequestHandler, HTTPServerfrom urllib.parse import parse_qs, quote, urlencode, urlparse
import requests
client_id = "your-client-id"base_url = "https://cloud-api.prevu3d.com"scopes = ["read:basic", "read:hierarchy"]
# Step 1: Authorize with PKCE and get an access tokenverifier = secrets.token_urlsafe(48)[:64]challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).decode().rstrip("=")state = secrets.token_urlsafe(32)auth_result = {"code": None, "state": None}
class Handler(BaseHTTPRequestHandler): def log_message(self, *args): pass
def do_GET(self): query = parse_qs(urlparse(self.path).query) auth_result["code"] = query.get("code", [None])[0] auth_result["state"] = query.get("state", [None])[0] self.send_response(200) self.end_headers()
server = HTTPServer(("localhost", 0), Handler)redirect_uri = f"http://localhost:{server.server_address[1]}"consent_params = urlencode( { "response_type": "code", "code_challenge_method": "S256", "client_id": client_id, "redirect_uri": redirect_uri, "code_challenge": challenge, "state": state, })consent_url = f"{base_url.replace('cloud-api.', 'cloud.', 1)}/oauth?{consent_params}"consent_url += "&" + "&".join(f"scopes={quote(scope)}" for scope in scopes)
webbrowser.open(consent_url)server.handle_request()
if auth_result["state"] != state: raise RuntimeError("Invalid state")if not auth_result["code"]: raise RuntimeError("Authorization failed")
token_response = requests.post( f"{base_url}/oauth/token", data={ "grant_type": "authorization_code", "client_id": client_id, "code": auth_result["code"], "redirect_uri": redirect_uri, "code_verifier": verifier, },)token_response.raise_for_status()access_token = token_response.json()["access_token"]
# Step 2: Get your API URL and org IDapi_info = requests.get( f"{base_url}/oauth/api-info", headers={"Authorization": f"Bearer {access_token}"},).json()
api_url = api_info["apiUrl"]organization_id = api_info["organization"]["id"]
# Step 3: Browse divisionsdivisions = requests.get( f"{api_url}/v1/nodes/{organization_id}/browse", headers={"Authorization": f"Bearer {access_token}"},).json()
print("Divisions:", json.dumps(divisions, indent=2))Dépannage
Section intitulée « Dépannage »| Si vous voyez… | Essayez ceci… |
|---|---|
| Invalid OAuth grant request après avoir cliqué sur Allow | Vérifiez que vous utilisez le Client ID d’une application native (Authorization Code et Native app activés). Une application Client Credentials uniquement n’a pas d’URI de redirection et ne peut pas terminer ce flux. |
| Redirect URI domain must be verified lors de la création de l’application | N’entrez pas d’URI de redirection personnalisée. Activez plutôt le bouton Native app. Seul http://localhost (sans port, sans secret) peut être enregistré aujourd’hui. |
| Erreur sur la page de consentement concernant les paramètres de requête | Assurez-vous que response_type=code, code_challenge_method=S256 et tous les paramètres requis sont présents, y compris state et scopes. |
| 400 ou 403 lors de l’échange de jeton | Le code a peut-être expiré (limite de 60 secondes), le redirect_uri ne correspond peut-être pas à l’étape 3, ou le verifier et le challenge PKCE ne correspondent pas. |
| 403 Forbidden lors de l’appel API | Une requête doit passer les trois couches de sécurité. Vérifiez les scopes OAuth, l’accès au contenu de l’utilisateur connecté et son rôle sur le nœud cible. |
| Mauvaise organisation dans les réponses API | L’utilisateur sélectionne l’organisation sur l’écran de consentement. Réautorisez et choisissez la bonne organisation. |
Pour les problèmes de connexion, DNS et URL d’API, consultez Premiers pas — URL de l’API et accès réseau.
Et ensuite ?
Section intitulée « Et ensuite ? »- Pour un usage en production, ajoutez une logique pour rafraîchir votre jeton avant expiration avec
grant_type=refresh_tokenet votre refresh token stocké. - Explorez la référence API pour voir toutes les opérations disponibles.