Encontrar

Artículo
· 5 mar, 2025 Lectura de 6 min

Criação de JWT e integração com InterSystems IRIS

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
 
SymmetricKeyJWT

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.

 
AsymmetricWithx509

 

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.

Comentarios (0)1
Inicie sesión o regístrese para continuar
InterSystems Official
· 5 mar, 2025

Retirada de MultiValue en InterSystems IRIS 2025.1

A partir de la versión 2025.1 de la plataforma de datos IRIS® de InterSystems, InterSystems deja oficialmente de utilizar MultiValue y lo incluye en la lista de funciones obsoletas y descatalogadas. Aunque InterSystems seguirá dando soporte a los clientes actuales que utilicen MultiValue, no se recomienda para nuevas aplicaciones.

Qué significa esto para vosotros:

  • Soporte continuado: El soporte para MultiValue seguirá estando disponible a través del Worldwide Response Center (WRC) sobre la base del «mejor esfuerzo», como se proporciona para las versiones anteriores a nuestras Versiones Mínimas Soportadas.
  • Posibilidad de retirada en el futuro: Aunque no hay planes inmediatos para eliminar MultiValue de nuestros productos, InterSystems se reserva el derecho de hacerlo en una futura versión.
  • Orientación al cliente: Si tenéis alguna pregunta sobre el uso actual o previsto de MultiValue, os animamos a que os pongáis en contacto con vuestro equipo de cuentas de InterSystems para que os orienten.

La designación «obsoleto» indica que los clientes deben planificar la eliminación del uso de MultiValue. Somos conscientes de que esto puede afectar a los proyectos en curso, y agradecemos vuestra cooperación a medida que continuamos evolucionando nuestra plataforma.

Si deseáis más información o tenéis alguna duda, no dudéis en comentar a continuación o poneros en contacto con vuestro representante de InterSystems.

Comentarios (0)1
Inicie sesión o regístrese para continuar
Artículo
· 5 mar, 2025 Lectura de 8 min

How to set up an IRIS Sharding cluster in less than a minute

In this article I'll show you how to set up in your laptop, very quickly, a cluster of IRIS nodes in sharding. It's not the goal of this article neither to talk about sharding in detail nor define a deployment of a production ready architecture, but to show how to set up quickly, in your own machine, a cluster of IRIS instances configured as shard nodes, with which you'll able to play and test this functionality. If you're insterested in knowing more about sharding in IRIS, take a look at the documentation clicking here.  

First and foremost, I want to remark that IRIS sharding will allow us 2 things:

  • Define, load and query shard tables, which data will be distributed transparently between the cluster's nodes
  • Define  federated tables, which offer a global and composed view of data belonging to different tables that will be physically stored in different distributed nodes

So, as I said, we let for other article playing with shard or federated tables, and just focus now in the previous step, that is, setting up the cluster of shard nodes.

Well, for our example we're going to use Docker Desktop (for Windows or MacOS) and we will make use of an IRIS feature: CPF Merge; which allow us to use a plain text file within which we'll include IRIS sections/configuration properties that we want to apply to update the default configuration of an IRIS instance. Basically this file overwrites some parts of the iris.cpf file that defines the default configuration of the instance.

This merging is "triggered" automatically when we add the environment variable: ISC_CPF_MERGE_FILE and it's set with a valid path to a file that contains those sections of the cpf file that we want to change. When IRIS starts, it checks if there is a merge file to apply (basically, if it exists that environment variable and points to a valid file). If so, do the merge and starts.

I won't ramble on, here is the file docker-compose.yml that'll do the magic:

 
docker-compose.yml

Here you have also an example of CSP.conf and CSP.ini files:

 
CSP.conf
 
CSP.ini

In this example, we're instantiating 3 services:

  • irisnode1 - First node of the cluster, it has a special role, that's the reason we named it as node1
  • irisnode2 - Data node, an aditional node to the cluster, which role is data (we can have as many as we want of these)
  • webgateway - Webserver preconfigured to access the IRIS instances (Apache + Webgateway)

To build the image shardnode:latest, I've used the dockerfile below:

 
Dockerfile

Within the dockerfile we call this generic iris.script that would allow us to run ObjectScript code, to setup, import & compile code, etc.., in the IRIS image we're building:

 
iris.script

The files used for the CPF merge for nodo1 and the other IRIS cluster data nodes are:

 
merge_first_data-node.cpf
 
merge_data-node.cpf

We could have more nodes of type data as part of the cluster only adding additional services with the same definition that we have for irisnode2 (changing the name of course)

One more thing, in order to make our routing definition in the webserver to work properly, and so being able to access the System Management Portals for each instance, we have to change the parameter CSPConfigName in each one of them, and we do that with scripts in the files: configure_first_data-node.sh y configure_data-node.sh; for this example both are equal, but I've leave them as separated files because, at some point, we could want to execute different actions for each IRIS instance during start time, depending on if it's a cluster node of type nodo1 or type data.

 
configure_data-node.sh

And that's basically it.

You could define the nodes using the available API in %SYSTEM.Cluster class, but the truth is that the possibility of introducing actions altogether with the CPF Merge feature simplifies the task a lot. I recomend you to take a look at here, in particular at the part referred to the section [Actions].

To build the images and deploy the cluster, we could build our image sharnode:latest and launch our docker-compose from VS Code. Alternately we could do it in our command line, from within the folder in which we have the file: docker-compose.yml, executing these commands:

docker compose build
docker compose up

It'll take a bit the first time because the instance tagged as node1 has to start before whatever other data node in the cluster starts. But everything should be ready and working in 1 minute or less.

If everything went right, you should be able to access to the SMPs of each instance with the URLs below:

And, done! From here, the limits regarding DDBB storage and tables size it's determined by your hardware. You would have and IRIS cluster with sharding enabled to define your shard and/or federated tables.

Hope it's useful for you!! See you around... 

1 Comentario
Comentarios (1)1
Inicie sesión o regístrese para continuar
Pregunta
· 5 mar, 2025

Enable/Disable a scheduler task

Hi ,

I have a scheduler task and an associated class that works.

Class Sample.Util.CreateTask Extends (%SYS.Task.Definition, %Persistent)
{

Parameter PROPERTYVALIDATION = 1;

Parameter TaskName = "Sample.Util.CreateTask";

Method OnTask() As %Status
{
// Perform the logic
}

}

Is there a way to Enable or Disable the above task "CreateTask()" from an external function/Method/class ?

2 comentarios
Comentarios (2)1
Inicie sesión o regístrese para continuar
Artículo
· 4 mar, 2025 Lectura de 2 min

ObjectScriptを使用し、ローカルファイルを他のサーバーにアップロード(POST)する方法

これは InterSystems FAQ サイトの記事です。
 

ObjectScriptの%Netパッケージのライブラリクラスを利用して、ファイルを他のサーバーにアップロードすることができます。

以下のCurl コマンドと同じことを ObjectScript で実現する方法を紹介します。

curl -X POST "http://localhost/api/upload/csv?a=123&b=999" -F file=@"C:/temp/a.csv":/temp/a.csv"

クライアントのObjectScriptコードを以下の様に作成します。

Class User.MyRestClient Extends %Base
{

ClassMethod readMimeData() As %Status
{
    // form-data (for CSV)
    set msg= ##class(%Net.MIMEPart).%New()

    set msg.ContentType = "multipart/form-data"
    set inputstream=##class(%Stream.FileBinary).%New()
    set sc=inputstream.LinkToFile("c:¥temp¥a.csv")
    If $$$ISERR(sc) Do $system.OBJ.DisplayError(sc) Quit
    set filePart = ##class(%Net.MIMEPart).%New(inputstream)
    set filePart.ContentType = "text/csv; charset=utf-8"
    do filePart.SetHeader("Content-Disposition","form-data; name=""csvfile""; filename=""upload.csv"";")
    do msg.Parts.Insert(filePart) 
    set tempstream = ##class(%Stream.TmpCharacter).%New()

    set writer = ##class(%Net.MIMEWriter).%New()

    do writer.OutputToStream(.tempstream)

    do writer.WriteMIMEBody(msg)

    // POST with the above form-data
    set req=##class(%Net.HttpRequest).%New()

    set req.Server="127.0.0.1"
    set req.Port=80
    do req.SetParam("a","123")   ;; a=123
    do req.SetParam("b","999")   ;; b=999
    set req.EntityBody = tempstream

    set req.ContentType = "multipart/form-data; boundary="_msg.Boundary

    set sc = req.Post("/api/upload/csv")

    If $$$ISERR(sc) Do $system.OBJ.DisplayError(sc) Quit
    set res=req.HttpResponse

    write res.Data.Read(1000)
    quit $$$OK
}

}
Comentarios (0)1
Inicie sesión o regístrese para continuar