Skip to content

OAuth e Service Canvas

Queria si integra con API esterne autenticate tramite Service Canvas -- canvas DSL speciali con purpose = SERVICE che descrivono come autorizzare un provider OAuth2 e quali operazioni espongono. Le credenziali utente vengono memorizzate cifrate in un vault e referenziate dai canvas consumatori (CHAT, INGESTION, WIDGET) tramite il tipo connection_ref.

BYO (Bring Your Own)

V1/V2 supportano solo l'approccio BYO: il tenant porta il proprio client_id e client_secret OAuth registrati presso il provider. Queria non fornisce e non certifica app OAuth proprie verso provider terzi.

Quando serve

Caso d'usoEsempio
Chat che invia messaggi su un canaleSlack, Microsoft Teams
Pipeline che crea eventi calendarioGoogle Calendar, Microsoft 365
Ingestione automatica da SaaSNotion, Confluence, GitHub Issues
Constructor che chiama API a pagamentoStripe, Salesforce, HubSpot
Cloud storage avanzatoGoogle Drive con permessi delegati, OneDrive

Per cloud storage base con login utente personale, esistono gia i connettori standard documentati in Impostazioni > Storage Cloud.

Architettura

┌────────────────────────────────────────┐
│  Service Canvas "Slack OAuth"          │
│  purpose = SERVICE                     │
│  ┌──────────────┐  ┌─────────────────┐ │
│  │ oauth2_config│  │ operation_def[] │ │
│  │ client_id    │  │ post_message    │ │
│  │ client_secret│  │ list_channels   │ │
│  │ auth_url     │  │ get_user_email  │ │
│  │ token_url    │  └─────────────────┘ │
│  │ scopes[]     │                      │
│  └──────────────┘                      │
└────────────────────────────────────────┘
            ^ referenziato da

┌─────────────────────────────┐
│  Canvas CHAT consumer       │
│  ... -> external_tool(      │
│    serviceCanvasId='slack', │
│    operationId='post_msg')  │
└─────────────────────────────┘
            │ runtime
            v
┌────────────────────────────────────┐
│  ExternalServiceConnection (DB)    │
│  per (serviceCanvasId,             │
│       companyId, userId)           │
│  -> accessToken (cifrato AES-256)  │
│  -> refreshToken (cifrato)         │
│  -> scopes, expiresAt              │
└────────────────────────────────────┘

Tre concetti chiave:

  1. Service canvas -- definizione del provider (chi e, come si autorizza, quali endpoint espone).
  2. External_tool node -- usato nei canvas CHAT/INGESTION per chiamare un'operazione del service canvas.
  3. Connection -- riga in DB con i token cifrati per la coppia (utente, service).

Creare un service canvas

L'admin segue questi passi:

1. Registra l'app OAuth presso il provider

Esempio Slack:

  1. Vai su https://api.slack.com/apps e crea una nuova app.
  2. Configura Redirect URL = https://admin.queria.pro/api/oauth/callback/slack (sostituisci con il dominio Queria del tuo tenant).
  3. Definisci gli scopes richiesti (es. chat:write, channels:read).
  4. Copia client_id e client_secret.

2. Crea il service canvas

  1. Pannello admin > DSL e Pipeline > OAuth e Service Canvas > Nuovo.
  2. Scegli un template provider (Slack, Google Workspace, Microsoft 365, GitHub, Notion, Custom).
  3. Incolla client_id e client_secret nei campi del nodo oauth2_config. Il client_secret e crittografato server-side (AES-256-GCM).
  4. Verifica auth_url, token_url, scopes (precompilati dal template, modificabili).
  5. Aggiungi i nodi operation_def con metodo HTTP, path, parametri input/output. Puoi importarli da OpenAPI 3.x (per provider che lo espongono).
  6. Salva. Il canvas viene validato e marcato ACTIVE.

3. Gli utenti si autorizzano

Sul service canvas appare un pulsante Connect. Quando un utente lo clicca:

  1. Redirect al provider per autorizzazione (consenso utente, scopes).
  2. Provider redirect indietro con code.
  3. Backend scambia code per access_token + refresh_token.
  4. I token vengono cifrati e salvati in ExternalServiceConnection per (serviceCanvasId, companyId, userId).
  5. L'utente vede la connessione come Connected e puo revocarla in qualsiasi momento.

Usare la connessione in un canvas

Nel canvas CHAT/INGESTION aggiungi un nodo external_tool:

json
{
  "type": "external_tool",
  "params": {
    "serviceCanvasId": "slack-oauth-canvas-id",
    "operationId": "post_message",
    "inputs": {
      "channel": "{{sys.target_channel}}",
      "text": "{{llm_writer_1.output}}"
    },
    "outputName": "slack_response"
  }
}

A runtime:

  • Il motore carica il service canvas.
  • Trova l'operation post_message.
  • Risolve la connection per (serviceCanvasId, companyId, ctx.userId).
  • Se il token e scaduto, lo refresh automaticamente.
  • Esegue la chiamata HTTP con Authorization: Bearer <access_token>.
  • Scrive la risposta in sys.slack_response.

Gestione delle connessioni

Pannello admin > OAuth e Service Canvas > [service] > Connections:

  • Tabella di tutte le connessioni per quel service canvas (utenti, scopes, stato, ultimo uso).
  • Stato possibile: ACTIVE, EXPIRED (refresh fallito), REVOKED, ERROR.
  • Revoca lato Queria (rimuove i token cifrati) e -- se il provider lo supporta -- chiama l'endpoint di revoca remoto.
  • Audit log: chi ha autorizzato, quando, con quali scopes, quale canvas ha consumato la connection.

Sicurezza

  • Token a riposo: cifrati con AES-256-GCM. La chiave master LLM_VAULT_KEK deriva da JWT_SECRET (assicurarsi che in produzione non sia il default dev-secret-change-me).
  • Token in transito: solo HTTPS verso il provider; le call interne attraversano la rete Docker isolata.
  • Scopes minimi: il template ti suggerisce gli scopes minimi per operazione. Non richiedere admin:* se non serve.
  • Per-utente: ogni connection appartiene a un singolo utente. Quando un canvas viene eseguito, usa il token dell'utente che ha triggerato l'esecuzione (ctx.userId).
  • Audit: ogni chiamata external_tool con OAuth registra (userId, serviceCanvasId, operationId, statusCode, latencyMs) in IntegrationCallLog.

Limiti e roadmap

V1/V2 attuali:

  • Solo authorization_code flow.
  • BYO client only (no Queria-owned verified apps).
  • No client_credentials (M2M) -- in roadmap V3.
  • No device_code flow.
  • No domain-wide delegation Google Workspace.
  • No webhook inbound dal provider (in roadmap separata).
  • Import operazioni da OpenAPI 3.x in V1.2.

Best practice

  1. Un service canvas per provider, anche se usi piu operations: semplifica la gestione token.
  2. Documenta gli scopes nel nome o description del canvas: "Slack (chat:write only)" e meglio di "Slack OAuth".
  3. Limita gli operation_def attivi: aggiungi solo le operazioni effettivamente usate.
  4. Test su tenant pilota: prima di abilitare per tutti, prova su un'azienda interna.
  5. Monitora EXPIRED: un calo di refresh riusciti spesso indica che il provider ha rivocato l'app o cambiato le policy.

Queria v3.5.0 -- External Tools OAuth V2 + Service Canvas

Queria - Document Intelligence con Cog-RAG