---
title: 28. Integração com o diretório
slug: 28-integracao-com-o-diretorio
docTags: 
createdAt: 2026-10-13T14:43:34.917Z
---

*Como a organização entra na plataforma, e um teste que prova.*

Duas formas de a organização entrar, e elas não são equivalentes.

**Cada tenant tem o seu.** O provedor (ou o LDAP) é configurado dentro do tenant, em Diretório e identidade, e vale só para ele: cada empresa entra pelo próprio diretório, e o de uma não serve a outra. Vale para os três sites do tenant — a plataforma, o **portal de atendimento** e o **responder** —, e a pessoa volta ao site de onde saiu. O provedor da instalação (o do console da instalação) é outro e não é de cliente nenhum.

***

### <font color="#15803D">OpenID Connect / OAuth 2.0 — a preferida</font>

A senha de rede do usuário **nunca chega à plataforma**: o navegador vai ao provedor, o provedor fala com o Active Directory, e o GRC recebe apenas o código de autorização. Um comprometimento do GRC não expõe credencial de rede de ninguém.

***

### <font color="#15803D">LDAP direto — a alternativa</font>

Serve quando não há gestor de identidade no meio, e é a inferior das duas: no bind a senha de rede do usuário passa pela plataforma. Por isso a conexão sem ldaps\:// é sinalizada — o canal carrega a credencial como ela é.

***

### <font color="#15803D">Configurar o login da empresa (OpenID Connect ou LDAP)</font>

A tela fica em **Administração ▸ Diretório e identidade** (o título da página é o mesmo do menu), com permissão admin\:usuarios. Dois blocos lado a lado: **OpenID Connect / OAuth 2.0** e **Diretório Ativo por LDAP**, cada um com o selo **em uso** ou **inativo**.

Para ligar o OpenID Connect:

1.     Em **Como as pessoas entram**, escolha **Os dois: login da empresa e senha local** (recomendado), **Só o login da empresa (OIDC)** ou **Só senha local**. "Só OIDC" deixa todo mundo de fora — inclusive o administrador — se o provedor cair.

2.     Preencha **Emissor (realm)** (ex.: https\://auth.exemplo.com/realms/producao), **Client ID**, **Segredo do cliente** (em branco para cliente público, só PKCE), **Redirect URI**, **Escopos**, **Claim do usuário**, **Claim de grupos** e, se o provedor declarar o tenant no token, **Claim do tenant**. Escolha o **Perfil padrão** na lista (o recomendado é **Solicitante**) e, se quiser, monte o mapa **Grupo do diretório → perfil** (veja Perfis).

3.     Clique em **Testar conexão** e confira os selos **emissor confere**, **PKCE suportado** e **tenant no token**.

4.     Clique em **Salvar OpenID Connect**. Vale na próxima entrada, sem reiniciar: o login lê a configuração do tenant a cada vez. Teste antes de salvar, e mantenha "os dois" até confirmar que o login da empresa funciona — com "só OIDC" e um emissor errado, ninguém deste tenant entra.

Para o LDAP, preencha **Servidor** (prefira ldaps\://), **Base DN**, **Filtro de usuário**, **Bind DN**, **Senha de serviço**, **Base de grupos** e **Filtro de grupos**, escolha o **Perfil padrão** na lista, marque **Usar o LDAP direto** e clique em **Salvar LDAP**.

O LDAP também é do tenant. **Servidor**, **Base DN**, **Bind DN**, **Senha de serviço** e **Base de grupos** são só dele: nenhuma variável de ambiente os preenche ou trava, e um tenant que não os salvou não tem LDAP. As variáveis GRC\_LDAP\_URL, GRC\_LDAP\_BASE\_DN, GRC\_LDAP\_BIND\_DN, GRC\_LDAP\_BIND\_PASSWORD, GRC\_LDAP\_GROUP\_BASE\_DN e GRC\_LDAP\_ENABLED não valem para tenant nenhum — uma variável da instalação valeria para todos de uma vez. **Filtro de usuário**, **Filtro de grupos** e **Perfil padrão** têm o padrão da instalação (grc.ldap.\*, ou seja, GRC\_LDAP\_USER\_FILTER, GRC\_LDAP\_GROUP\_FILTER e GRC\_LDAP\_DEFAULT\_ROLE; de fábrica, (sAMAccountName=\{0}), (member=\{0}) e Solicitante), que vale onde o tenant deixou o campo em branco.

GRC\_LDAP\_ALLOW\_PLAINTEXT=true continua sendo uma permissão da instalação, e não configuração de diretório: é o que deixa um servidor ldap\://, sem TLS, ser usado num ambiente de teste. Sem ela, o login por ldap\:// é recusado e o motivo vai para o log do servidor, porque a senha iria em claro pela rede.

Abaixo dos blocos, **Como ligar o Keycloak como ponte para o Active Directory** traz o passo a passo do lado do provedor, com a URL de retorno desta instalação pronta para copiar:

1.     No realm, crie um cliente OpenID Connect com *Standard flow* (Authorization Code) e *PKCE method* S256.

2.     Em *Valid redirect URIs*, informe a URL de retorno que a tela mostra.

3.     Adicione um *mapper* de grupos com nome de claim groups (nomes com caminho, como /GRC/Analistas, são aceitos).

4.     Preencha os campos da tela, use **Testar conexão** e só então tente entrar. A **Redirect URI** é a do endereço deste tenant (ex.: https\://empresa.exemplo.com/oidc/callback), e é ela que vai em *Valid redirect URIs* — cada tenant registra a sua no provedor dele.

5.     Em **Grupo do diretório → perfil**, ligue cada grupo do AD ao perfil da plataforma e salve. Em **Perfis de acesso** se define o que cada perfil pode fazer — o grupo só escolhe o perfil.

***

### <font color="#15803D">O provedor é do tenant, e só dele</font>

Emissor, client ID, segredo e redirect URI são de cada tenant, e nenhuma variável de ambiente os preenche ou trava: um tenant sem provedor salvo entra só com senha local. GRC\_OIDC\_SCOPES, GRC\_OIDC\_USERNAME\_CLAIM, GRC\_OIDC\_ROLE\_CLAIM e GRC\_OIDC\_DEFAULT\_ROLE, quando definidas, são só o padrão dos campos que o tenant deixou em branco. GRC\_OIDC\_ISSUER não liga o login de ninguém: serve para validar tokens de serviço quando a instalação usa GRC\_AUTH\_MODO=oidc ou ambos. Se o provedor declara o tenant numa claim (**Claim do tenant**), ela tem de bater com o tenant do endereço — um token de outra empresa não abre sessão aqui.

Quem entra pelo provedor pela primeira vez, sem convite, e não casa com nenhum grupo mapeado recebe o **perfil padrão** — **Solicitante**, se o tenant não escolher outro: abre chamado no portal e lê e pergunta sobre documentos, e nada mais. Quem veio por **convite** entra com o perfil do convite (Colaborador, por padrão), que também responde no /responder. Para dar mais, mapeie o grupo ou troque o perfil da pessoa em Usuários; a troca manual fica, a menos que um grupo mapeado diga outra coisa na próxima entrada.

***

### <font color="#15803D">Conta local com o mesmo login</font>

A entrada pelo provedor acha a pessoa pelo login que o token traz, e só entra em conta de **origem externa** — a que o próprio provedor criou na primeira entrada, ou a que nasceu de um convite aceito pelo diretório. **Nunca entra em conta local**, a que tem senha guardada na plataforma, nem quando a pessoa chega com um convite. Há provedor que deixa cada um escolher o próprio nome de usuário, e vincular pelo login entregaria o admin do tenant a quem criasse lá um usuário admin. (Origem não é o **Tipo** da tela de Usuários: uma conta local pode ser do tipo Interno ou Externo.)

Quando o login do provedor coincide com uma conta local, a entrada é recusada. A pessoa lê que já existe uma conta local com aquele login e que o administrador da organização precisa resolver; o log do servidor registra o tenant, o login e a conta. A conta local não é alterada.

A plataforma não tem ação que transforme conta local em externa, nem que troque o login de uma conta. Para resolver:

•     **A pessoa continua na conta local:** entra com login e senha, como antes. Desativar a conta local não libera o login para o provedor — ela continua existindo.

•     **A pessoa passa a entrar pelo provedor:** faça o provedor mandar um login que não colida — outro nome de usuário para ela no provedor, ou a **Claim do usuário** apontando para uma claim única, como o e-mail (essa troca vale para todo o tenant). Na primeira entrada nasce a conta externa; dê a ela o perfil e os grupos em Usuários e desative a conta local antiga.

•     **O login precisa continuar o mesmo:** quem administra a instalação, com acesso ao banco, renomeia o login da conta local (iam.usuario.login, por exemplo admin para admin.local); a próxima entrada pelo provedor cria a conta externa com o login que ficou livre.

O segredo do cliente e a senha de serviço nunca saem do servidor. A tela mostra **se eles existem**, nunca o valor, e o campo em branco mantém o que já está gravado: segredo que a tela desenha é segredo que vaza pelo print, pelo log do navegador e pela captura do suporte.

No banco, os dois ficam **cifrados** (AES-GCM, com o prefixo v1:), e não em claro: quem lê o banco ou um backup não vê as credenciais dos diretórios. A chave é a da instalação — GRC\_CONSOLE\_CHAVE, senão GRC\_INTEGRACAO\_CHAVE, senão uma chave sorteada e guardada no banco na primeira vez. Trocar a chave (ou restaurar a base noutra instalação) faz o segredo guardado deixar de abrir: ele passa a valer como não configurado, o log do servidor diz por quê, e é preciso informar o segredo do cliente e a senha de serviço de novo nesta tela. Trate a chave como parte do backup da instalação.

***

### <font color="#15803D">O que a entrada pelo provedor confere</font>

O id\_token que volta do provedor é conferido como ele pede: a **assinatura**, pelas chaves que o provedor publica no jwks\_uri do documento de descoberta; o **emissor**; a **audiência**, que tem de ser o client ID deste tenant; e a **validade**, com um minuto de folga de relógio. Token de outro emissor, emitido para outro cliente ou vencido não abre sessão, e a razão fica escrita. O provedor precisa publicar jwks\_uri: sem as chaves, a assinatura não tem como ser conferida, e a entrada é recusada. O **Testar conexão** não olha esse campo; se a entrada falhar dizendo isso, confira o documento de descoberta do provedor.

A ida ao provedor fica no banco (core.entrada\_oidc\_pendente, por dez minutos), e não na memória de uma instância: com várias instâncias atrás do balanceador, a volta pode cair em qualquer uma. A tabela tem RLS por tenant, então a volta só acha o pedido pelo endereço do mesmo tenant de onde a pessoa saiu. A chave da linha é o hash do state, e não o state.

***

### <font color="#15803D">O teste de conexão</font>

Busca o documento de descoberta do emissor, e é o que separa três coisas que a tela de login mostra como o mesmo erro:

| **Sintoma**               | **O que é**                             |
| ------------------------- | --------------------------------------- |
| HTTP 404                  | realm errado no emissor                 |
| responde, emissor diverge | o realm existe e não é o que se pensava |
| não responde              | rede bloqueada, ou provedor fora        |

Ele também confere duas coisas que só aparecem depois:

•     **PKCE**, que é o que protege o código de autorização em cliente público.

•     **O claim do tenant**, se houver. O tenant vem do endereço por onde a pessoa entrou, e o provedor é o daquele tenant. A claim é uma conferência a mais, opcional: preenchida, um token que declara outro tenant não abre sessão aqui; em branco, vale só o endereço.

***

### <font color="#15803D">Perfis</font>

O mapa **Grupo do diretório → perfil**, no bloco OIDC, é do tenant: cada empresa tem os próprios grupos. Cada linha liga um grupo (com caminho, como /GRC/Analistas, ou só o nome) a um perfil escolhido na lista — os de fábrica e os que o tenant criou em **Perfis de acesso**. **+ Grupo** acrescenta uma linha, **Tirar** remove, e o mapa vale a partir da próxima entrada de cada pessoa, quando é salvo com **Salvar OpenID Connect**. Enquanto o tenant não grava o próprio mapa, a tela mostra o padrão da instalação e diz que é esse o caso. Um perfil que não existe no tenant é recusado na gravação, e o mapa aceita até 200 grupos.

Um grupo mapeado para um perfil com escrita dá escrita a todo mundo do grupo: revise antes de salvar. Quem autentica e não casa com grupo nenhum fica com o **perfil padrão** — de fábrica, o **Solicitante**, que só usa o portal e não consome licença: autenticar no diretório não deve, por si, conceder escrita sobre auditoria.

O **Mapeamento por grupo** do LDAP continua declarado na configuração da implantação (grc.ldap.role-mappings) e aparece só à vista.

No LDAP, **sem nenhum mapeamento o mapeamento por grupo fica desligado** e todos entram com o perfil padrão — mesmo com a base de grupos preenchida. A tela avisa quando é esse o caso.
