Pular para o conteúdo

Fluxo de Aplicativo Nativo

Use o fluxo de aplicativo nativo para integrações que agem em nome de um usuário conectado a partir da própria máquina dele, como um aplicativo de desktop, uma CLI ou um plugin de CAD. Ele usa Authorization Code com PKCE, um redirecionamento loopback localhost e nenhum segredo de cliente. Este guia mostra a configuração da criação do aplicativo OAuth até a primeira chamada à API.

Consulte primeiro o guia Primeiros passos se você ainda não conhece os pré-requisitos, o acesso de rede e o modelo de segurança.


  1. Criar um aplicativo OAuth: Registre um aplicativo nativo no Prevu3D e obtenha um Client ID
  2. Configurar o acesso do usuário: Garanta que o usuário que fará login consiga alcançar os dados de que precisa
  3. Autorizar com PKCE: Envie o usuário à página de consentimento no navegador
  4. Trocar o código por um token: Troque o código de autorização por um token de acesso
  5. Encontrar sua URL da API: Descubra a URL base da sua organização (ela varia por região)
  6. Fazer sua primeira chamada: Teste a conexão com uma requisição simples
  1. Faça login na Plataforma Prevu3D.
  2. Vá em SettingsOAuth.
  3. Clique para criar um novo aplicativo.
  4. Ative o Authorization Code flow.
  5. Ative Native Application. A URI de redirecionamento é fixada em http://localhost.
  6. Deixe o segredo de cliente desativado. Aplicativos nativos não usam segredo.
  7. Copie e armazene com segurança seu Client ID. Você precisará dele em cada autorização.

O fluxo nativo chama a API como o usuário conectado, não como um usuário de serviço. Isso cobre as camadas 2 e 3 do modelo de segurança: quais nós o usuário pode ver (acesso ao conteúdo) e o que ele pode fazer com eles (acesso por função/permissão).

  1. Garanta que o usuário que fará login tenha acesso ao conteúdo dos nós (organizações, divisões, sites etc.) que seu caso de uso exige.
  2. Garanta que o usuário tenha uma função nesses nós com as permissões de que sua integração precisa (ler, editar, gerenciar etc.).

Na tela de consentimento, o usuário também seleciona qual organização autorizar. Os escopos que o usuário aprova ali configuram a camada 1.

Aplicativos nativos não conseguem guardar um segredo, então o fluxo usa PKCE para proteger o código de autorização. Antes de abrir a página de consentimento, gere três valores:

ValorComo
code_verifierString aleatória, de 43 a 128 caracteres
code_challengeBASE64URL(SHA256(code_verifier)) sem preenchimento
stateString aleatória; valide-a quando o redirecionamento retornar

Inicie um servidor loopback local em uma porta livre e, em seguida, abra o navegador do usuário na página de consentimento.

URL de consentimento: https://cloud.prevu3d.com/oauth

Parâmetros de consulta (todos obrigatórios):

ParâmetroValor
response_typecode
code_challenge_methodS256
client_idSeu Client ID
redirect_uriSua URI de loopback, por exemplo http://localhost:8765 (inclua a porta, sem barra final)
scopesUm por escopo, por exemplo scopes=read:basic&scopes=read:hierarchy
code_challengeO desafio PKCE gerado acima
stateSeu valor de state aleatório

Depois que o usuário fizer login e clicar em Allow, o navegador redireciona para sua URI de loopback:

http://localhost:8765/?code={authorization_code}&state={state}

Se o usuário negar o acesso, você receberá ?error=access_denied em vez disso. Os códigos de autorização expiram após 60 segundos, portanto troque-os imediatamente.

Endpoint: POST https://cloud-api.prevu3d.com/oauth/token

Cabeçalhos: Content-Type: application/x-www-form-urlencoded

Corpo:

CampoValor
grant_typeauthorization_code
client_idSeu Client ID
codeCódigo do redirecionamento
redirect_uriA mesma URI usada na Etapa 3 (incluindo a porta)
code_verifierO verificador PKCE original

Não envie um segredo de cliente para aplicativos nativos.

Exemplo de resposta:

{
"hasError": false,
"expires_in": 86400,
"access_token": "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "..."
}

Salve os dois tokens. Use o access_token para chamadas à API. Quando ele expirar, solicite um novo com grant_type=refresh_token e seu refresh_token armazenado (nenhum segredo de cliente necessário).

Chame o endpoint de descoberta para obter a apiUrl da sua organização. Não codifique uma URL regional de forma fixa.

Endpoint: GET https://cloud-api.prevu3d.com/oauth/api-info

Cabeçalhos: Authorization: Bearer <your_access_token>

Exemplo de resposta:

{
"user": { "..." : "..." },
"organization": {
"id": "217ebd23-ec54-4af0-a6d6-4a441a6d1966",
"name": "Test Organization"
},
"scopes": ["read:basic", "read:hierarchy"],
"apiUrl": "https://api-ue1.prevu3d.com/realityconnect-api"
}

Use o valor de apiUrl como base para todas as suas chamadas à API. Anote também o organization.id, de que você precisará em muitos endpoints.

Agora você tem tudo de que precisa: um token de acesso e sua URL base. Vamos fazer uma requisição simples para recuperar as divisões da sua organização:

GET {apiUrl}/v1/nodes/{organization_id}/browse
Authorization: Bearer <your_access_token>

Exemplo com valores reais:

GET https://api-ue1.prevu3d.com/realityconnect-api/v1/nodes/217ebd23-ec54-4af0-a6d6-4a441a6d1966/browse HTTP/1.1
Authorization: Bearer eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9...

Uma resposta bem-sucedida contendo uma lista de divisões confirma que sua integração está funcionando corretamente.

Aqui está um script completo que faz tudo o que foi descrito acima. Substitua client_id pelo seu Client ID e execute-o. Ele inicia um servidor loopback temporário, abre a página de consentimento no navegador e imprime as divisões da sua organização assim que você aprovar.

import base64
import hashlib
import json
import secrets
import webbrowser
from http.server import BaseHTTPRequestHandler, HTTPServer
from 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 token
verifier = 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 ID
api_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 divisions
divisions = requests.get(
f"{api_url}/v1/nodes/{organization_id}/browse",
headers={"Authorization": f"Bearer {access_token}"},
).json()
print("Divisions:", json.dumps(divisions, indent=2))
Se você vir…Tente isto…
Invalid OAuth grant request após clicar em AllowConfirme que você está usando o Client ID de um aplicativo nativo (Authorization Code e Native app ativados). Um aplicativo somente Client Credentials não tem URI de redirecionamento e não consegue concluir esse fluxo.
Erro na página de consentimento sobre parâmetros de consultaGaranta que response_type=code, code_challenge_method=S256 e todos os parâmetros obrigatórios estejam presentes, incluindo state e scopes.
400 ou 403 na troca do tokenO código pode ter expirado (limite de 60 segundos), a redirect_uri pode não corresponder à da Etapa 3, ou o verificador e o desafio PKCE podem não corresponder.
403 Forbidden ao chamar a APIUma requisição precisa passar pelas três camadas de segurança. Verifique os escopos OAuth, o acesso ao conteúdo do usuário conectado e a função do usuário no nó de destino.
Organização errada nas respostas da APIO usuário seleciona a organização na tela de consentimento. Autorize novamente e escolha a correta.

Para problemas de conexão, DNS e URL da API, consulte Primeiros passos.

  • Adicione lógica para renovar seu token antes de ele expirar usando grant_type=refresh_token com seu refresh token armazenado.
  • Explore a referência da API para conhecer todas as operações disponíveis.