Referência para as Classes Web JSON
Prefácio
O InterSystems IRIS a partir da versão 2022.2 inclui uma funcionalidade reformulada para JSON web tokens (JWTs). Antes localizada no pacote da classe %OAuth2, a classe JWT, junto com as outras classes da Web JSON (JWCs), agora está em %Net.JSON. Essa migração ocorreu para modularizar as JWCs. Antes, eles estavam estreitamente ligados à implementação do framework OAuth 2.0. Agora, eles podem ser mantidos e usados separadamente.
Observação: para a compatibilidade com as versões anteriores, as classes ainda existem no pacote %OAuth2, mas a codebase agora usa %Net.JSON.
O objetivo deste artigo é servir como uma espécie de referência para as JWCs porque, ao tentar escrever uma documentação, não encontrei nenhuma fonte com informações abrangentes sobre todas elas e como se relacionam entre si. Espero que este artigo seja essa fonte.
Prólogo
O que são as JWCs?
As classes da Web JSON são os protocolos da Web que usam estruturas de dados baseadas em JSON. Elas são úteis para a autorização e a troca de informações, como OAuth 2.0 e OpenID Connect.
No momento, o InterSystems IRIS 2022.2+ é compatível com sete classes em %Net.JSON: (clique para abrir a definição)
> JSON Web Token (JWT)
Uma maneira compacta e segura para o URL de representar informações transferidas entre duas partes que podem ser assinadas digitalmente, criptografadas ou ambos.> JSON Web Signature (JWS)
Uma JWS representa o conteúdo assinado usando estruturas de dados baseadas em JSON. O JWA define os algoritmos de assinatura e verificação para a JWS. Ou seja, um JWT assinado.> JSON Web Encryption (JWE)
Uma JWE representa o conteúdo criptografado usando estruturas de dados baseadas em JSON. A JWA define os algoritmos de criptografia e descriptografia para a JWE. Ou seja, um JWT criptografado.> JSON Web Algorithms (JWA)
Um JWA define um conjunto de algoritmos criptográficos e identificadores usados com as classes JWS, JWE e JWK.> JSON Web Key (JWK)
Uma JWK representa uma chave criptográfica usada como entrada para os algoritmos definidos na classe JWA.> JSON Web Key Set (JWKS)
Um JWKS é um conjunto de JWKsO diagrama a seguir demonstra a relação entre as JWCs, conforme definido abaixo: 
Vamos analisar cada parte na seção a seguir.
Um estudo do JWT
Um JSON web token (JWT) é uma maneira compacta e segura para o URL de representar informações transferidas entre duas partes que podem ser assinadas digitalmente, criptografadas ou ambos.
Há dois tipos de JWTs:
- JWS
- JWE
Uma JWS é um JWT assinado e uma JWE é um JWT criptografado. Na linguagem corrente, falamos "JWT" ou "JWT criptografado". Para JWTs, o padrão é que sejam assinados, ainda que possam não ser assinados (JWTs não seguros).
Mas vamos voltar um pouco — o que é uma informação? É apenas um pedaço de informação representado em um par de chave/valor que um cliente está afirmando ser verdadeiro. Por exemplo, pode ser uma informação sobre um cliente que está tentando fazer login de um determinado local. O seguinte objeto JSON contém três informações (username, location, and admin):
{
"username": "persephone",
"location": "underworld",
"admin": "true"
}
Então, os JWTs transferem informações assim entre duas partes, como cliente e servidor. No entanto, se apenas essas informações fossem transferidas, não haveria garantia de que ninguém adulterou ou viu o conteúdo, além do destinatário. Nossa mensagem não teria integridade ou confidencialidade. Felizmente, os JWTs fornecem uma maneira opcional de garantia com ambos os padrões JSON web signature (JWS) e JSON web encryption (JWE). Seja uma JWS ou JWE, um JWT tem várias partes.
JSON Web Signature (JWS)
Um JWT não criptografado e assinado (portanto, chamado de JWS) possui três partes:
- Header (cabeçalho)
- Payload (carga útil)
- Signature (assinatura)
Cada parte é um objeto JSON. Se você fizer a codificação Base64URL de cada parte e concatená-las com um ponto (.) entre elas, você terá um JWT (header.payload.signature).
Vamos analisar cada parte.
Cabeçalho
O cabeçalho de uma JWS consiste em metadados sobre o tipo de token e, se especificado, o JSON web algorithm (JWA) necessário para a validação da assinatura do token. Por exemplo:
{
"alg": "HS256",
"typ": "JWT"
}
Codifique o texto abaixo em Base64URL e você terá a primeira parte de um JWT!
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Para resumir, o cabeçalho contém o JWA e o tipo do token.
Carga útil
A segunda parte de uma JWS é a carga útil. Ela contém as informações. Usando o exemplo anterior, a carga útil pode ser o seguinte:
{
"username": "persephone",
"location": "underworld",
"admin": "true"
}
Depois de codificar em Base64URL, obtemos isto:
eyJ1c2VybmFtZSI6InBlcnNlcGhvbmUiLCJsb2NhdGlvbiI6InVuZGVyd29ybGQiLCJhZG1pbiI6InRydWUifQ
Agora, nossa JWS está desta forma:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InBlcnNlcGhvbmUiLCJsb2NhdGlvbiI6InVuZGVyd29ybGQiLCJhZG1pbiI6InRydWUifQ
Para resumir, a carga útil contém as informações que você quer transmitir.
Assinatura
A terceira parte de uma JWS é a assinatura. Você pega o JWT até o momento (o cabeçalho e a carga útil criptografados), um segredo [também chamado de chave privada ou JSON web key (JWK)], o algoritmo especificado no JWA e assina isso. Desta forma:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Usando o segredo/valor da JWK thecatsmeow, nossa JWS ficará assim no final:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InBlcnNlcGhvbmUiLCJsb2NhdGlvbiI6InVuZGVyd29ybGQiLCJhZG1pbiI6InRydWUifQ.KAZcjC9tqRV4DunI3sSma3k6fvL5ntgLXe9Gl7hKg5o
Para resumir, a assinatura contém a validação da integridade.
Abstraindo um pouco, temos:

Você notou que eu falei...
Talvez você tenha percebido que eu qualifiquei nosso JWT como "pode ser assinado digitalmente, criptografado ou ambos".
Vamos falar sobre a parte da assinatura primeiro e depois abordar a criptografia na próxima seção. É possível não assinar a JWS e só ter um cabeçalho e uma carga útil (então, não é mais uma JWS, e sim um JWT não assinado e não criptografado). Isso é possível se o JWA especificado no cabeçalho para "none".
Desta forma:
{
"alg": "none",
"typ": "JWT"
}
Então, o JWT resultante seria apenas o cabeçalho criptografado em Base64URL + . + carga útil criptografada em Base64URL + .. A assinatura seria uma string vazia, então um JWT não seguro ficaria, por exemplo, desta forma:
eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.
Mas não envie JWTs não seguros, porque qualquer pessoa poderá adulterá-los e você não saberá se as informações são válidas.
JSON Web Encryption (JWE)
Repetindo, um JWT pode ser assinado digitalmente, criptografado ou ambos. Já discutimos as assinaturas com JWSs, então vamos seguir para a criptografia.
Como observado acima, um JWT não criptografado e assinado (JWS) tem três partes: cabeçalho, carga útil e assinatura.
Agora, um JWT criptografado (portanto, uma JWE) possui cinco partes:
- Cabeçalho protegido
- Chave criptografada
- Vetor de inicialização (IV)
- Carga útil/texto cifrado
- Tag de autenticação
Cabeçalho protegido
O cabeçalho protegido é a primeira parte de uma JWE. Ele não é criptografado porque o destinatário precisa saber como descriptografar o restante da JWE. Para informá-lo sobre como fazer isso, ele contém informações, como 1) o algoritmo usado para criptografar a chave de criptografia do conteúdo (CEK) e também produzir a chave criptografada e 2) o algoritmo usado para criptografar a carga útil e produzir o texto cifrado e a tag de autenticação.
Veja a seguir um exemplo de cabeçalho protegido:
{
"alg":"RSA-OAEP",
"enc":"A256GCM"
}
Ele é codificado em Base64URL para produzir o seguinte:
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ
Chave criptografada
A segunda parte da JWE é a chave criptografada. A chave criptografada é a forma criptografada da CEK, que é uma chave simétrica usada para criptografar a carga útil e produzir o texto cifrado e a tag de autenticação. A CEK é criptografada usando o algoritmo especificado no valor "alg" no cabeçalho protegido e na chave pública do destinatário.
Com uma CEK de thecatsmeowmeows e uma chave pública RSA de 1024 bits gerada aleatoriamente, o valor da chave criptografada usando o algoritmo RSA-OAEP pode ser:
X6znPIKWHnO8MhHD2scnUv7PVAo8VfxHYxmZQR0J8/rqGOB+udq8DkXd93n7S2cS3LT1Inx4qQ5J8GquQyc2xfS5n2INgKjSedYac4LBCkmpYRbRyNawK2eMEUDkcdBlqBE4NlWcAhl6X0H4AiNs7r+P8ffipvyztd51JdLoTlw=
A chave criptografada é codificada em Base64URL e concatenada ao cabeçalho protegido. Portanto, temos esta JWE até o momento:
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ
Vetor de inicialização (IV)
O IV é a terceira parte da JWE. Ele é gerado aleatoriamente e codificado em Base64URL. Não precisa ser secreto, portanto não é criptografado. Por exemplo, catsarefantastic. Em seguida, codificamos em Base64URL e concatenamos com o cabeçalho protegido codificado e as partes da chave criptografada para obter:
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ.Y2F0c2FyZWZhbnRhc3RpYw
Carga útil/texto cifrado
A quarta parte de uma JWE é a carga útil/texto cifrado. É onde aninhamos o JWT. Até aqui, abordamos como proteger e depois ler esses dados após o recebimento, mas agora podemos falar sobre os dados. Tudo o que discutimos na seção de JWS é aplicável aqui. Temos nossa JWS de três partes com o cabeçalho, a carga útil e a assinatura. Em seguida, usando a CEK e o IV, criptografamos a JWS usando AES GCM e solicitamos uma saída de tag de autenticação de 128 bits.
Um exemplo de um possível texto cifrado codificado em Base64URL:
NjI0YjZkZTlmMGEzNjk0MTgyMTYyNTc3MmEyMjM4ZWY0MTJhMzljMzJiOGVjNzVjMzU4MGIzNTVhMGUyN2M1MWYyY2Y2OGIyYmNkODM2YmNiZjBkOGIzZjMzMmQyODBlZWZhNjBkYTQ5M2VlNjRhMTg4NmMzYTFlY2E2OGQ0NjkyOGQzNTFjOWFjODdhY2QzZDc0ZTY4OTc1MTA4NzQ0NTEyNTJhOGM5N2U3OGFkNjJhMmNmMWQwNzM5MmQwYzcyM2EzMjg5MWI2YjlmMzRkNmYxMDU5YTVlMTljZThjMTNkNzFlMjgzZWY1ZGM0ZDdmZTNhMzk1YmM2MDE5NjRmZmMwYmZlMDM2YWY1MzZmYTdiYTYzNWU3NTJmMzk1OTBhY2Y2ZWM4YjlmZjBmYzY1ZTM0M2U5YzE4OTk0ZjAyYTZlNDA0NjEzNDM1ZTVhMQ
Temos esta JWE até o momento:
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ.Y2F0c2FyZWZhbnRhc3RpYw.NjI0YjZkZTlmMGEzNjk0MTgyMTYyNTc3MmEyMjM4ZWY0MTJhMzljMzJiOGVjNzVjMzU4MGIzNTVhMGUyN2M1MWYyY2Y2OGIyYmNkODM2YmNiZjBkOGIzZjMzMmQyODBlZWZhNjBkYTQ5M2VlNjRhMTg4NmMzYTFlY2E2OGQ0NjkyOGQzNTFjOWFjODdhY2QzZDc0ZTY4OTc1MTA4NzQ0NTEyNTJhOGM5N2U3OGFkNjJhMmNmMWQwNzM5MmQwYzcyM2EzMjg5MWI2YjlmMzRkNmYxMDU5YTVlMTljZThjMTNkNzFlMjgzZWY1ZGM0ZDdmZTNhMzk1YmM2MDE5NjRmZmMwYmZlMDM2YWY1MzZmYTdiYTYzNWU3NTJmMzk1OTBhY2Y2ZWM4YjlmZjBmYzY1ZTM0M2U5YzE4OTk0ZjAyYTZlNDA0NjEzNDM1ZTVhMQ
Tag de autenticação
A tag de autenticação é a parte final da JWE. É um resultado do texto cifrado (JWS aninhada criptografada). A tag de autenticação recebida ao criptografar o texto cifrado na última seção é:
9f19e30efeddf20f5232b76f07c755ac
Codificamos em Base64URL e concatenamos com a JWE para obter a JWE finalizada como:
eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.WDZ6blBJS1dIbk84TWhIRDJzY25VdjdQVkFvOFZmeEhZeG1aUVIwSjgvcnFHT0IrdWRxOERrWGQ5M243UzJjUzNMVDFJbng0cVE1SjhHcXVReWMyeGZTNW4ySU5nS2pTZWRZYWM0TEJDa21wWVJiUnlOYXdLMmVNRVVEa2NkQmxxQkU0TmxXY0FobDZYMEg0QWlOczdyK1A4ZmZpcHZ5enRkNTFKZExvVGx3PQ.Y2F0c2FyZWZhbnRhc3RpYw.NjI0YjZkZTlmMGEzNjk0MTgyMTYyNTc3MmEyMjM4ZWY0MTJhMzljMzJiOGVjNzVjMzU4MGIzNTVhMGUyN2M1MWYyY2Y2OGIyYmNkODM2YmNiZjBkOGIzZjMzMmQyODBlZWZhNjBkYTQ5M2VlNjRhMTg4NmMzYTFlY2E2OGQ0NjkyOGQzNTFjOWFjODdhY2QzZDc0ZTY4OTc1MTA4NzQ0NTEyNTJhOGM5N2U3OGFkNjJhMmNmMWQwNzM5MmQwYzcyM2EzMjg5MWI2YjlmMzRkNmYxMDU5YTVlMTljZThjMTNkNzFlMjgzZWY1ZGM0ZDdmZTNhMzk1YmM2MDE5NjRmZmMwYmZlMDM2YWY1MzZmYTdiYTYzNWU3NTJmMzk1OTBhY2Y2ZWM4YjlmZjBmYzY1ZTM0M2U5YzE4OTk0ZjAyYTZlNDA0NjEzNDM1ZTVhMQ.OWYxOWUzMGVmZWRkZjIwZjUyMzJiNzZmMDdjNzU1YWM
Vamos abstrair a codificação em Base64URL e analisar a visão geral de alto nível de uma JWE:

Observações sobre os termos
Em busca de clareza, em vez de usar alguns nomes de classes da Web JSON, dei preferência para os nomes descritivos. Especificamente, JWK/JWKS em vez de chaves públicas, criptográficas, de criptografia, etc. A chave usada para a criptografia ou assinatura é uma JSON web key (JWK) e o conjunto delas (a chave simétrica e os pares de chaves assimétricas) é um JSON web key set (JWKS).
Queria fazer uma pausa para mencionar isso e retomar a terminologia. Um JWT é uma JWS ou JWE. Os algoritmos usados em uma JWS/JWE são definidos no JWA. As chaves usadas como entrada para os algoritmos no JWA são JWKs, armazenadas como um conjunto JWKS.
E o que é JOSE? JOSE é a coleção de padrões. Assim como temos bando para corvos ou gataria para gatos, temos JOSE para os padrões da Web JSON.
Conclusão
Espero que este artigo seja um bom ponto de referência para quem quer trabalhar com as classes da Web JSON (JWCs).
As JWCs têm três casos de uso diferentes:
- Autenticação
- Autorização
- Troca de informações
No InterSystems IRIS 2022.2+, você pode configurar o OAuth 2.0 para usar JWTs. Isso está descrito no OAuth 2.0 e OpenID Connect. Seu código personalizado pode usar as JWCs conforme definido no %Net.JSON para esses casos de uso.
Me avise se você achou este artigo útil!