---
title: "Cloud certificate"
description: "How to enable cloud certificates on an on-premises Signer: registering the app with the provider (PSC or CSC), redirect URI, ClientId and ClientSecret, discovery and common errors."
canonical: "https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/certificado-em-nuvem"
locale: "en"
product: "Signer"
last_updated: "2026-10-22"
---

# Cloud certificate

Signer can sign with certificates kept by a cloud provider, with no token or smart card on the user's computer.
This page shows how to turn this integration on in an on-premises instance.

Signer talks to two kinds of provider:

| Kind | What it is | Settings section |
|---|---|---|
| PSC | ICP-Brasil trust service provider (*Prestador de Serviço de Confiança*, PSC), such as BirdID, SafeID, VIDaaS and NeoID | `TrustServices` |
| CSC | Provider that follows the *Cloud Signature Consortium* (CSC) standard | `Csc` |

> **Note**
>
> If the `Cloudhub` section is configured, Cloudhub supplies the provider list. In that case Signer does not use the
> providers in the `TrustServices` section. See the [Cloudhub settings](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/settings#cloudhub-settings-v300).

## PSC providers

### 1. Register the app with the provider

Each provider requires an app registration. The registration gives you a `ClientId` and a `ClientSecret`.

1. Fill in the registration with:
   * Name: your instance name, for example *Patorum Signer*.
   * Description: one sentence about the portal, for example *Patorum signature portal*.
   * Support e-mail: the address that will receive notices from the provider.
   * Redirect URI: `<SiteUrl>/tsp-callback`, for example `https://signer.patorum.com/tsp-callback`.
1. Register the app in the right place for each provider:

   | Provider | Where to register |
   |---|---|
   | BirdID, SafeID and VIDaaS | [Lacuna PSC app registration](https://demos.lacunasoftware.com/pt/tsp-app-registration) |
   | SerproID | [Serpro registration form](https://serproid.serpro.gov.br/manual-integracao/manutencao/formulario-cadastro-aplicacao/) |
   | Other providers | Contact the provider's support |

1. Write down the `ClientId` and `ClientSecret` of each provider.

> **Warning**
>
> The redirect URI registered with the provider must match, character by character, the URI Signer sends. Signer
> builds it from `General:SiteUrl` followed by `tsp-callback`. If `SiteUrl` has a path (for example
> `https://patorum.com/signer/`), end the value with `/`. Without the trailing slash, Signer drops the last path
> segment.

> **Tip**
>
> Each environment (staging and production) has its own domain and therefore its own redirect URI. Register the URI
> of each environment with the provider. If the provider rejects a URI that already exists in another app, edit the
> existing app instead of creating a new one.

### 2. Configure Signer

In the `TrustServices` section, enable the integration and enter the credentials of each provider. The name of the
subsection under `Services` is the provider name (`BirdID`, `SafeID`, `VIDaaS`, `NeoID` and so on). Enter only the
providers you will use.

```json
"TrustServices": {
  "Enabled": true,
  "Services": {
    "BirdID": {
      "ClientId": "...",
      "ClientSecret": "..."
    },
    "VIDaaS": {
      "ClientId": "...",
      "ClientSecret": "..."
    }
  }
}
```

In environment variables (Docker or Azure App Service), use `__` instead of `:`. For example:
`TrustServices__Services__BirdID__ClientId`.

Signer already knows the production endpoint of the most common providers. For a provider without a default
endpoint, or to use a provider's staging environment, also set `Endpoint`, `Provider` and `BadgeUrl` to the values
the provider gives you. Example:

```json
"SerproID": {
  "ClientId": "...",
  "ClientSecret": "...",
  "Endpoint": "https://neoid.estaleiro.serpro.gov.br/smartcert-api/",
  "Provider": "SERPRO",
  "BadgeUrl": "https://cdn.lacunasoftware.com/img/psc/serproid.png"
}
```

The full key list is in [*TrustServices* settings](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/settings#trustservices-settings-cloud-certificates-v1110).

### 3. Restart and test

1. Restart the application.
1. Create a document for a signer who has a certificate with one of the configured providers.
1. Open the document as that signer and choose to sign with a certificate. The provider shows in the cloud certificate list.

### How discovery works

Discovery is the query Signer makes to learn which providers hold a certificate for the signer.

* With `DiscoveryEnabled` set to `true` (default), Signer queries only the providers configured under `Services`,
  with the signer's CPF (or CNPJ). The screen shows only the providers that answer that they hold a certificate for
  that identifier.
* If no provider holds a certificate for the signer, the screen shows no cloud provider.
* If the signer has no identifier, Signer skips discovery and shows no cloud provider.
* With `DiscoveryEnabled` set to `false`, the screen shows every configured provider to every user, with or without an identifier.

If a provider fails during discovery (invalid credential, timeout or missing endpoint), Signer skips that provider
and writes a message like this to the log:

```text
Error calling trust service '<provider>' to discover certificates for ... (ignoring service)
```

The user sees no error. The provider just disappears from the list. The maximum wait for each provider is
`TrustServices:DiscoveryTimeoutSeconds` (default: 10 seconds).

> **Warning**
>
> Before you set `DiscoveryEnabled` to `false`, remove the providers without a valid endpoint. In that mode, Signer
> prepares the authorization of every provider at once. One provider without an endpoint makes the whole list fail.

## CSC providers

1. Register the app with the CSC provider using the redirect URI `<SiteUrl>/api/csc/callback`.
1. Write down the `ClientId`, the `ClientSecret` and the base URL of the provider's CSC API.
1. In the `Csc` section, set `Enabled` to `true` and add a subsection under `Services` for each provider:

   ```json
   "Csc": {
     "Enabled": true,
     "Services": {
       "MyProvider": {
         "FriendlyName": "My provider",
         "Endpoint": "https://csc.provider.com/",
         "ClientId": "...",
         "ClientSecret": "...",
         "BadgeUrl": "https://provider.com/badge.png"
       }
     }
   }
   ```

1. Restart the application.

CSC providers do not go through discovery: the signature screen shows every configured provider.
The other keys (for example, server certificate pinning) are in [*Csc* settings](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/settings#csc).

## Common errors

| Symptom | Likely cause | What to do |
|---|---|---|
| The provider rejects the login with a `redirect_uri` error | The URI registered with the provider differs from the URI Signer sends | Compare the registered URI with `<SiteUrl>/tsp-callback` (PSC) or `<SiteUrl>/api/csc/callback` (CSC). Check scheme, domain, path and trailing slash |
| No cloud provider shows | `TrustServices:Enabled` is `false`, the signer has no certificate with the configured providers, or every provider failed discovery | Check the settings. Search the log for `(ignoring service)` |
| A provider shows for one user and not for another | Expected discovery behavior | The provider shows only for users who hold a certificate with it |
| A configured provider never shows | Invalid credential, a provider name Signer does not know without an `Endpoint`, or an endpoint the server cannot reach | Search the log for `(ignoring service)` with the provider name. Check that the Signer server can reach the provider endpoint |
| Providers from the `TrustServices` section do not show, but Cloudhub is configured | Cloudhub takes precedence | Register the providers in Cloudhub or remove the `Cloudhub` section |

## See also

* [Signer settings](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/settings)
* [Checking the logs (Linux)](https://docs.lacunasoftware.com/en-us/articles/signer/on-premises/linux/troubleshoot/check-logs)
