O que é JWT?
JWT (JSON Web Token) é um padrão aberto (RFC 7519) que oferece um método leve, compacto e auto-contido para transmitir informações de forma segura entre duas partes. É comumente usado em aplicações web para autenticação, autorização e troca de informações.
Um JWT é tipicamente composto por três partes:
1. Cabeçalho JOSE (JSON Object Signing and Encryption)
2. Payload (Carga útil)
3. Assinatura
Essas partes são codificadas no formato Base64Url e concatenadas com pontos (.) separando-as.
Estrutura de um JWT
Cabeçalho
{ "alg": "HS256", "typ": "JWT"}
Payload
{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
Assinatura:
A assinatura é usada para verificar se o remetente do JWT é quem ele diz ser e para garantir que a mensagem não foi adulterada.
Para criar a assinatura:
1. Cabeçalho e carga útil codificados em base64.
2. Aplicar o algoritmo de assinatura (por exemplo, HMAC SHA256 ou RSA) com uma chave secreta (para algoritmos simétricos como HMAC) ou uma chave privada (para algoritmos assimétricos como RSA).
3.Codificar o resultado em Base64Url para obter a assinatura..
JWT de exemplo. Veja o conteúdo do JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Criação de JWT no IRIS
Observação: Antes de 2024, a classe %OAuth2.JWT era usada para gerar JWTs no IRIS. A classe %Net.JSON.JWTé agora a classe primária para a criação de JWT, e usarei esta classe no código de exemplo.
Visão geral de JWK
JWK representa uma chave criptográfica, particularmente para assinar e verificar os JWTs. Os JWKs permitem que você represente chaves públicas (para verificação) e chaves privadas (para assinatura) em um formato padronizado que pode ser facilmente trocado entre sistemas. O JWKS contém múltiplos JWKs.
Fluxo de trabalho do JWT
1. Construa seu cabeçalho como um %DynamicObject e adicione cabeçalhos personalizados, se necessário.
2. Construa o corpo/claims diretamente como um %DynamicObject
3. Chame o método Create da classe %Net.JSON.JWT.
Set sc = ##Class(%Net.JSON.JWT).Create(header, , claims, jwks, , .JWT)
Create JWK
Set sc = ##Class(%Net.JSON.JWK).Create("HS256","1212ASD!@#!#@$@#@$$#SDFDGD#%+_)(*@$SFFS",.privateJWK,.publicJWK)
Isso deve retornar a chave privada
{"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"}
Algumas propriedades importantes do JWK
"kty": "oct" - representa o algoritmo simétrico
"kty": "RSA" / "kty": "EC" - representa o algoritmo assimétrico
Uma vez que o JWK é criado, ele pode ser adicionado ao JWKS.
Vamos criar JWKS no IRIS
Set sc = ##class(%Net.JSON.JWKS).PutJWK(jwk,.JWKS)
Este método retorna o JWKS.
Gerando o JWT no IRIS
Você pode criar JWTs de chave Simétrica ou Assimétrica no IRIS. A classe %Net.JSON.JWK é usada principalmente para gerar o JWT. Antes de chamar o método, certifique-se de criar e enviar o JWKS tanto para criptografia Simétrica quanto Assimétrica ao gerar o JWT.
Criptografia Simétrica
Algoritmos simétricos usam uma chave secreta compartilhada, onde tanto o remetente quanto o destinatário usam a mesma chave para assinar e verificar o JWT. Esses algoritmos, como HMAC (HS256, HS512, HS384), geram um hash (assinatura) para o payload do JWT. Essa abordagem não é recomendada para sistemas de alta segurança, pois tanto a assinatura quanto a verificação são expostas, apresentando potenciais riscos de segurança.
O método Create
da classe %Net.JSON.JWK
é usado para gerar o JWK. Ele recebe dois parâmetros de entrada e retorna dois parâmetros de saída:
1. algorithm - O algoritmo para o qual criar o JWK.
2. secret - A chave usada para assinar e verificar o JWT
3. privateJWK - A Chave Web JSON privada que é criada.
4. publicJWK - A chave Web JSON pública que é criada.
Para algoritmos de chave simétrica - você obterá privateJWK
Para algoritmos de chave assimétrica - você obterá privateJWK
e publicJWK
ClassMethod SymmetricKeyJWT()
{
Set secret = "1212ASD!@#!#@$@#@$$#SDFDGD#%+_)(*@$SFFS"
Set algorithm ="HS256"
Set header = {"alg": (algorithm), "typ": "JWT","x-c":"te"}
Set claims= {"sub": "1234567890","name": "John Doe", "iat": 1516239022 }
#; create JWK
Set sc = ##class(%Net.JSON.JWK).Create(algorithm,secret,.privateJWK)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
ZWrite privateJWK
#; Create JWKS
Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
ZWrite privateJWKS
Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
Write pJWT
Quit
}
Output
LEARNING>d ##class(Learning.JWT.NetJWT).SymmetricKeyJWT()
privateJWK={"kty":"oct","k":"MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT","alg":"HS256"} ; <DYNAMIC OBJECT>
privateJWKS="{""keys"":[{""kty"":""oct"",""k"":""MTIxMkFTRCFAIyEjQCRAI0AkJCNTREZER0QjJStfKSgqQCRTRkZT"",""alg"":""HS256""}]}"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsIngtYyI6InRlIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.PcCs_I8AVy5HsLu-s6kQYWaGvuwqwPAElIad11NpM_E
Criptografia Assimétrica
A criptografia assimétrica refere-se ao uso de um par de chaves: uma chave para assinar o token (chave privada) e outra chave para verificar o token (chave pública). Isso é diferente da criptografia simétrica.
Chave Privada: Esta chave é usada para assinar o JWT. Ela é mantida em segredo e nunca deve ser exposta.
Chave Pública: Esta chave é usada para verificar a autenticidade do JWT. Ela pode ser compartilhada e distribuída com segurança, pois não pode ser usada para assinar novos tokens.
Você pode gerar a criptografia assimétrica do JWT com chave privada/certificado via %SYS.X509Credentials. Portanto, você precisa armazenar seu certificado nesta classe persistente.
ClassMethod AsymmetricWithx509()
{
Set x509 = ##class(%SYS.X509Credentials).%OpenId("myprivateTest1")
Set algorithm ="RS256"
Set header = {"alg": (algorithm), "typ": "JWS","x-c":"te"}
Set claims= {"sub": "1234567890","name": "John Doe", "iat": 1516239022 }
#; create JWK
Set sc = ##class(%Net.JSON.JWK).CreateX509(algorithm,x509,.privateJWK,.publicJWK)
ZWrite privateJWK,publicJWK
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
#; Create JWKS
Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
ZWrite privateJWKS
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
; sigJWKS - private
Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
If $$$ISERR(sc) {
Write $SYSTEM.OBJ.DisplayError(sc)
}
Write pJWT
Quit
}
JWT em aplicações Web
A partir da versão 2023, o IRIS inclui a criação de JWT integrada para aplicações web por padrão. Certifique-se de que a Autenticação JWT esteja habilitada ao configurar sua aplicação web.
Adicionei uma breve explicação sobre a configuração:
1. Habilite a Autenticação JWT em sua aplicação web.
2. Se ainda não o fez, crie uma classe REST.
3. O recurso de endpoint padrão "/login" está incluído. Faça uma chamada de API REST usando autenticação básica com o payload como {"user": "_SYSTEM", "password": "SYS"}.
4. A resposta será um JSON contendo o "access_token", "refresh_token" e outros detalhes relevantes.
5. Use o "access_token" para autorização.