# App Studio

## Guia Completo de Integração OAuth Zydon

Este guia detalha como implementar a integração OAuth com a plataforma Zydon, permitindo que seus clientes autorizem o acesso aos dados da conta Zydon deles através do seu plugin/aplicação.

#### Pré-requisitos

Antes de começar, garanta que seu plugin já está registrado na plataforma Zydon. Com o registro, você receberá três informações essenciais:

1. `client_id`: (Plugin ID).

   <figure><img src="/files/n99XEvEAMB31sPjhK2oM" alt=""><figcaption></figcaption></figure>

2. `access_key`: Sua chave secreta.

   <figure><img src="/files/FuQgT3Meo04W2tZ8iL0N" alt=""><figcaption></figcaption></figure>

3. URLs de Callback: Os endereços para onde o cliente será enviado após a autorização.<br>

### 🚀 **Fluxo OAuth Completo**

#### **Etapa 1: Redirecionamento para Autorização**

Redirecione seu cliente para a URL de autorização do Zydon:

```
https://admin.zydon.com.br/oauth/authorize?client_id={PLUGIN_ID}&redirect_uri={CALLBACK_URL}&state={STATE}
```

**Parâmetros Obrigatórios:**

* **`client_id`**: ID do seu plugin (UUID)
* **`redirect_uri`**: URL de callback autorizada do seu sistema
* **`state`**: Valor aleatório para proteção CSRF (recomendado)

**Exemplo:**

```
https://admin.zydon.com.br/oauth/authorize?client_id=123e4567-e89b-12d3-a456-426614174000&redirect_uri=https://meuapp.com/callback&state=xyz123
```

#### **Etapa 2: Autorização do Cliente**

O cliente será direcionado para a tela de autorização do Zydon onde:

1. **Visualizará** as permissões solicitadas
2. **Decidirá** se autoriza ou não o acesso
3. **Seu plugin será instalado automaticamente** (se ainda não estiver)

#### **Etapa 3: Callback com Código de Autorização**

Após a autorização, o cliente será redirecionado para sua URL de callback:

**Sucesso:**

```
https://meuapp.com/callback?code={AUTHORIZATION_CODE}&state={STATE}
```

**Erro:**

```
https://meuapp.com/callback?error={ERROR_CODE}&state={STATE}
```

**Códigos de Erro Possíveis:**

* **`invalid_client`**: Plugin não encontrado ou URL de callback não autorizada
* **`server_error`**: Erro interno durante a instalação/autorização

#### **Etapa 4: Troca do Código por Token de Acesso**

Com o código de autorização recebido, faça uma requisição para obter o token de acesso:

**Endpoint:**

```
POST https://api.zydon.com.br/appcenter/oauth/token
```

**Headers:**

```
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {BASE64_ENCODED_CREDENTIALS}
```

**Credenciais Basic Auth:**

```
Base64({PLUGIN_ID}:{ACCESS_KEY})
```

**Body (form-urlencoded):**

```
grant_type=authorization_code
code={AUTHORIZATION_CODE}
redirect_uri={CALLBACK_URL}
```

**Exemplo de Requisição:**

```bash
curl -X POST https://api.zydon.com.br/appcenter/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -H "Authorization: Basic MTIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDAwOmFiY2RlZmdoLWlqa2wtbW5vcC1xcnN0LXV2d3h5ejEyMzQ1Ng==" \
  -d "grant_type=authorization_code&code=987fcdeb-51a2-43d7-b890-123456789abc&redirect_uri=https://meuapp.com/callback"
```

**Resposta de Sucesso (200):**

```json
{
  "access_key_code": "987fcdeb-51a2-43d7-b890-123456789abc",
  "access_key_token": "fedcba98-7654-3210-fedc-ba9876543210"
}
```

### 🔑 **Usando as Credenciais de Acesso**

Após obter as credenciais, você pode usar o **`access_key_code`** e **`access_key_token`** para fazer chamadas autenticadas às APIs do Zydon em nome do cliente.

#### **Autenticação nas APIs:**

```
Authorization: Bearer {ACCESS_KEY_TOKEN}
X-Access-Key-Code: {ACCESS_KEY_CODE}
```

### ⚠️ **Tratamento de Erros**

#### **Erros na Autorização:**

* **404**: Plugin não encontrado
* **400**: Parâmetros inválidos
* **401**: Não autorizado

#### **Erros na Troca de Token:**

* **400**: `grant_type` inválido (deve ser `authorization_code`)
* **401**: Credenciais Basic Auth inválidas
* **404**: Código de autorização não encontrado ou expirado

### 🛡️ **Segurança**

#### **Boas Práticas:**

1. **Sempre use HTTPS** em suas URLs de callback
2. **Valide o parâmetro `state`** para prevenir ataques CSRF
3. **Mantenha o `access_key` seguro** - nunca exponha no frontend
4. **Configure apenas URLs de callback confiáveis** no seu plugin
5. **Implemente timeout** para códigos de autorização

#### **Validações Implementadas:**

* URLs de callback devem estar pré-autorizadas
* Códigos de autorização têm tempo de vida limitado
* Access key é validada em cada requisição

### 📊 **Fluxo Técnico Resumido**

<figure><img src="/files/LSpkHxz6tfBgisnlDtRP" alt=""><figcaption></figcaption></figure>

### 💡 **Exemplo Prático de Implementação**

#### **1. Iniciando o Fluxo (Backend da sua aplicação):**

```javascript
// Gerar state aleatório para CSRF protection
const state = crypto.randomUUID();
// Salvar state na sessão/cache para validação posterior

const authUrl = `https://admin.zydon.com.br/oauth/authorize?` +
  `client_id=${PLUGIN_ID}&` +
  `redirect_uri=${encodeURIComponent(CALLBACK_URL)}&` +
  `state=${state}`;

// Redirecionar cliente para authUrl
res.redirect(authUrl);
```

#### **2. Tratando o Callback:**

```javascript
app.get('/callback', async (req, res) => {
  const { code, state, error } = req.query;
  
  // Validar state para CSRF protection
  if (state !== getStoredState()) {
    return res.status(400).send('Invalid state');
  }
  
  if (error) {
    return res.status(400).send(`Authorization error: ${error}`);
  }
  
  try {
    // Trocar código por token
    const credentials = await exchangeCodeForToken(code);
    
    // Salvar credenciais do cliente
    await saveClientCredentials(clientId, credentials);
    
    res.send('Autorização realizada com sucesso!');
  } catch (err) {
    res.status(500).send('Erro ao obter token de acesso');
  }
});
```

#### **3. Trocando Código por Token:**

```javascript
async function exchangeCodeForToken(code) {
  const credentials = Buffer.from(`${PLUGIN_ID}:${ACCESS_KEY}`).toString('base64');
  
  const response = await fetch('https://api.zydon.com.br/appcenter/oauth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': `Basic ${credentials}`
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code: code,
      redirect_uri: CALLBACK_URL
    })
  });
  
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }
  
  return await response.json();
}
```

#### **4. Usando as Credenciais para Acessar APIs:**

```javascript
async function callZydonAPI(endpoint, accessKeyCode, accessKeyToken) {
  const response = await fetch(`https://api.zydon.com.br${endpoint}`, {
    headers: {
      'Authorization': `Bearer ${accessKeyToken}`,
      'X-Access-Key-Code': accessKeyCode,
      'Content-Type': 'application/json'
    }
  });
  
  if (!response.ok) {
    throw new Error(`API Error: ${response.status}`);
  }
  
  return await response.json();
}
```

### 🎯 **URLs de Referência**

* **Frontend (Autorização)**: `https://admin.zydon.com.br/oauth/authorize`
* **Backend API (Token)**: `https://api.zydon.com.br/appcenter/oauth/token`
* **Backend APIs (Dados)**: `https://api.zydon.com.br/*`

### 📋 **Checklist de Implementação**

* [ ] Plugin registrado na plataforma Zydon
* [ ] URLs de callback configuradas e autorizadas
* [ ] Implementação do redirecionamento para autorização
* [ ] Tratamento do callback com validação de state
* [ ] Implementação da troca código por token
* [ ] Armazenamento seguro das credenciais
* [ ] Implementação de chamadas autenticadas às APIs
* [ ] Tratamento de erros e renovação de tokens (se necessário)

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.zydon.com.br/app-studio.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
