> For the complete documentation index, see [llms.txt](https://docs.opencityitalia.it/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opencityitalia.it/sviluppatori-e-partner-tecnologici/integrazioni/single-sign-on/sso-con-app-io.md).

# SSO con App IO

`io-sso` è un componente server-side che funge da identity broker tra App IO (PagoPA) e la Stanza del Cittadino (SDC). Permette a un cittadino di aprire un documento direttamente da un messaggio App IO senza dover fare login manuale sul portale.

Il componente usa NextAuth v5 con sessioni JWT e il provider FIMS (OIDC di PagoPA). Tutta la logica gira server-side: nessun componente client, nessuna variabile d'ambiente sensibile nel bundle browser. I cookie di sessione sono `HttpOnly`, `Secure`, `SameSite=lax`.

## Multi-tenant

Ogni comune ha un proprio slug nell'URL. La configurazione del backend documentale (URL, credenziali operatore) è in `SDC_TENANTS` server-side — mai esposta al client.

```
https://appio-sso.opencityitalia.it/{tenant}/{sistema}/documents
```

## Il problema: due client, due cookie jar

App IO usa due client separati: il client nativo (Ktor/Alamofire), che gestisce l'autenticazione FIMS in background, e Chrome Custom Tab, che apre il documento. Il problema è che le sessioni del client nativo non sono accessibili da Chrome: i due client hanno cookie jar separati.

La soluzione è un claim store in-memory (OTT — *One Time Token*): il JWT di sessione viene conservato server-side, indicizzato da un UUID con TTL di 60 secondi. Chrome lo consuma in un'unica operazione, dopodiché il claim viene eliminato.

## Flusso di autenticazione

Vediamo il flusso completo dal click sulla CTA alla visualizzazione del documento:

```mermaid
sequenceDiagram
  autonumber
  actor c as Cittadino
  participant io as App IO (Ktor)
  participant iosso as io-sso
  participant fims as FIMS (PagoPA)
  participant chrome as Chrome Custom Tab
  participant sdc as SDC

  c -->> io: preme CTA nel messaggio
  io -->> iosso: GET /{tenant}/documents/{id}
  Note over iosso: middleware: UA = Ktor → avvia flusso auth
  iosso -->> fims: avvia flusso OIDC
  fims -->> io: autentica con _io_fims_token
  io -->> iosso: callback con codice autorizzazione
  Note over iosso: crea JWT di sessione
  Note over iosso: storeClaimJWT(UUID, JWT) in-memory
  iosso -->> io: 302 → /api/auth/ott?claim=UUID&then=/...
  Note over io: non segue il redirect (cross-domain)
  io -->> chrome: passa URL con claim UUID
  chrome -->> iosso: GET /api/auth/ott?claim=UUID
  Note over iosso: consumeClaimJWT(UUID) → JWT ✓ (one-time)
  iosso -->> chrome: Set-Cookie sessione + redirect
  chrome -->> iosso: GET /{tenant}/documents/{id}
  iosso -->> sdc: proxy con token operatore
  sdc -->> chrome: documento
```

## Accesso ai documenti

I documenti SDC sono protetti da credenziali operatore. Quando il cittadino arriva sulla pagina del documento con una sessione valida, il server recupera il codice fiscale dal JWT, ottiene l'ID utente SDC tramite `/api/users?cf=<codice_fiscale>` e verifica che l'utente sia il proprietario del documento (`owner`) oppure sia presente in `readers_allowed`. Se il controllo è superato, il server funge da proxy verso SDC usando un token operatore in cache e restituisce il documento.

## Formato URL della CTA

L'URL da inserire nella CTA del messaggio App IO segue questo schema:

```
iosso://https://appio-sso.opencityitalia.it/{tenant}/{sistema}/documents
```

Ad esempio, per il comune di Trento con il sistema IMIS:

```
iosso://https://appio-sso.opencityitalia.it/trento/imis/documents
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.opencityitalia.it/sviluppatori-e-partner-tecnologici/integrazioni/single-sign-on/sso-con-app-io.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
