Na documentação oficial do IdentityServer4, na seção Deployment há uma menção sobre Key Material e sua importancia no ambiente de produção. Mas você sabe o que é Key Material?

Em criptografia Key Material são os dados privados que compõem uma chave criptográfica. Esses dados permitem transformar um texto plano em texto cifrado. Ou seja, é a parte da chave que permite criptografar a mensagem.

crypto

Nem todas informações para criptografar uma mensagem são privados. Na criptografia assimétrica, parte dessas informações podem ser públicas. Assim o conteúdo da mensagem pode ser lido utilizando a chave pública. Porém para gerar o texto cifrado é necessário a chave privada.

Criptografia simétrica

Em um algoritmo simétrico uma única chave é utilizada. Tanto para criptografar os dados quanto na descriptografia. Portanto as duas partes envolvidas numa comunicação precisam ter a mesma chave. Seja para leitura, ou para escrever uma nova.

symmetric-encryption-1

Esse formato exige que ambos sistemas cuidem corretamente da chave de criptografia. A chave de criptografia aumenta o Surface of Attack (Área de ataque) da sua aplicação, aumentando as chances de um ataque.

Chave Assimétrica

Um algoritmo assimétrico envolve duas chaves. Uma chave pública e outra chave privada. Enquanto uma chave (privada) é usada para assinar digitalmente a mensagem a outra chave (pública) só pode ser usada para verificar a autenticidade da assinatura.

asymmetric-encryption-1

IdentityServer4 - JWK & JWKS

O IdentityServer4, assim como outros providers de OAuth 2.0, utiliza o JWT para geração de Bearer tokens. Um dos motivos para utilizar o JWT é que ele possui conceitos de JWK e JWKS. É por causa desses dois conceitos que é possível compartilhar o JWT entre as diversas aplicações com segurança.

Json Web Key (JWK)

JWK é uma estrutura JSON que representa uma chave de criptografia. Na sua estrutura contém as informações para criptografar um JWT (JWE) ou Assinar Digitalmente (JWS).

Dentro de um ambiente OAuth 2.0, o responsável por criar e gerenciar o JWK é o Authorization Server. Como no OAuth 2.0 todos os JWT's são emitidos por um único servidor ele é quem gerencia o JWK. Assim somente o Authorization Server pode emitir um JWT.

Certos parâmetros do JWK podem ser públicos, dessa forma os consumidores do JWT podem validar se o JWT não foi adulterado.

Exemplo de um JWK público (Google):

Exemplo de um JWK privado:

Json Web Key Set (JWKS)

JWKS é um array de JWK.

Os algoritmos de criptografia se tornam mais fracos com o tempo. Seja por que as técnicas de análise de criptografia melhoram ou por causa do desempenho dos computadores que melhoram dia após dias. Ambos contribuem para diminuir o tempo necessário para quebrar um algoritmo específico. Portanto, o objetivo do JWK e JWKS é permitir que um servidor OAuth 2.0 seja modular em relação a criptografia. Permitindo que novos algoritmos sejam facilmente inseridos.

Por esse motivo as boas práticas dizem que o JWK deve mudar a cada 90 dias. E com o auxilio do JWKS, ao efetuar a troca do algoritmo, não irá invalidar os tokens que foram gerados com o algoritmo anterior. Permitindo uma troca gradual, sem afetar os sistemas.

Atualmente o OAuth 2.0 utiliza o mesmo JWK para assinar o access_token e o identity_token. Há uma discussão no OAuth Working Group sobre separar a responsabilidade. Em breve teremos novidades.

Todo servidor OAuth 2.0 mantém um link público de seus JWKS.

Exemplo de um JWKS público Google:

Repare que apesar de público, não possui os dados privados. Utilizado para assinar o JWT.

Por que é importante?

Os demos e samples do IdentityServer4 não são bons exemplos para subir em produção. Além da segurança com o correto gerenciamento das chaves de criptografia. Você eventualmente terá problemas em situações de Load Balance, quando precisar escalar seu servidor de IdentityServer4.

Se a chave do seu JWT vazar, um usuário mal intencionado consegue impersonar qualquer usuário e ter acesso a qualquer API.

A documentação menciona a importância do Key Material, mas não dá detalhes sobre como gerenciar corretamente. Então se ninguém no time fez a configuração correta. Terá que contar com a sorte. Pois nem todos materiais disponíveis na internet leva em consideração cenários de Load Balance.

Como gerenciar o Key Material do IdentityServer4

O IdentityServer4 provê a extensão AddSigningCredential() e AddValidationKey(). A primeira é responsável por adicionar a Chave de Criptografia principal. E será utilizado para assinar digitalmente seu JWT.

Ao adicionar uma chave ao IdentityServer pela primeira vez, por exemplo chave1, você utilizr o AddSigningCredential(). E pode manter em produção por um certo período de tempo. 90 dias, 1 ou 2 anos.

Após esse período, é necessário preparar a chave2, para substituir a anterior. No entanto, se mudar imediatamente haverá bugs com os Clients e API's que ainda estão fazendo o cachê da chave1. Invalidando as requisições e eventualmente deslogando seu usuário. Por isso é necessário é introduzir a chave1 no discovery document antes de tornar a chave2 principal.

O OAuth 2.0 disponibiliza o endpoint /.well-known/openid-configuration/jwks. O primeiro item do Array corresponde a chave ativa. Os demais são as chaves anteriores. A extensão AddValidationKey() é a responsável por adicionar as chaves anteriores.

Veja um exemplo de como irá ficar o jwks endpoint.

O mais importante aqui é que a Chave utilizada deverá ser a mesmas entre todas as instâncias do AuthServer.

Estratégia para gerenciar as chaves

O objetivo final é o mesmo: Garantir que a mesma chave será utilizada em todas as instâncias. Sem abrir mão da segurança da chave. Afinal, se ela cair em mãos erradas, essa pessoa teria capacidade de gerar qualquer JWT e se passar por qualquer usuário. Isso seria desastroso.

IdentityServer Key Management

Esse é um produto oficial do IdentityServer4. Custa uma bagatela de €3.000,00. E você teria suporte oficial.

Azure Key Vault / AWS KMS

É possível utilizar o Azure Key Vault ou Amazon KMS para armazenar um certificado auto gerado. Para quem pretende utilizar certificados autogerados considero a melhor opção, devido à natureza da segurança de armazenamento.

JWKS.Manager

É uma biblioteca Open Source, que é uma alternativa direta ao IdentityServer Key Management. Sua arquitetura foi baseado no componente Microsoft.AspNetCore.DataProtection e possui uma extensão que implementa as interfaces ISigningCredentialStore e IValidationKeysStore do IdentityServer4.

Se você olhar no código fonte do IdentityServer4, ele implementa essas interfaces com os objetos InMemorySigningCredentialsStore e InMemoryValidationKeysStore, respectivamente.

A biblioteca segue as melhores práticas recomendados pelas RFC 7518 e RFC 7517. E também segue as recomendações do NIST.

Evite utilizar essas estratégias

Algumas estratégias parecem boas, mas não são aconselháveis.

Azure Blob store - Amazon S3

Ao armazenar o certificado em um Blob Store ou Amazon S3 ao invés do Azure Key Vault ou KMS. A diferença, recai na segurança, pois esses serviços não tem como premissa a segurança do arquivo.

Gerar uma imagem Docker com o arquivo embutido

Uma estratégia que alguns times fazem é gerar uma imagem docker com o arquivo dentro.

O problema dessa prática é na renovação das chaves de criptografia. O recomendado é renovar a cada 90 dias. Manter a chave anterior disponível por um período. E remover as partes privadas das chaves anteriores.

Conclusão

Espero que esse material te ajude mais do que o material oficial do IdentityServer4. Ele carece de exemplos e estratégias. Até mesmo de informações que guiem o seu time ao produto oficial deles (Key Management). E esse assunto pode gerar grande dor de cabeça em times que possuem o IdentityServer4 em produção.

Referências