New post

Find

Digest
· Dec 16, 2024

InterSystems 开发者出版物,十二月 09 - 15, 2024,摘要

Article
· Dec 16, 2024 3m read

No More Local Limits: Exposing InterSystems IRIS with ngrok

At hackathons that InterSystems participated and I supported, many students were asking how all their teammates could use the same IRIS database that they spun up in a container. I suggested using ngrok to expose their localhost IRIS and realized we don't have documentation on that. Hence, I thought this would be great to let more people knwo about this powerful technique for enhancing collaboration during development and testing.

Discussion (0)1
Log in or sign up to continue
Question
· Dec 15, 2024

ERROR #9761: No key in provided JWKS for alg ES512 and kid

I am trying to work with Epic on FHIR. Epic's documentation stated, your application makes a HTTP POST request to the authorization server's OAuth 2.0 token endpoint to obtain access token.

Set tSC = ##class(%SYS.OAuth2.Authorization).GetAccessTokenClient(pClient,pScopes,.prop,.err) returns

ERROR #9761: No key in provided JWKS for alg ES512 and kid  

I check this /csp/sys/oauth2/OAuth2.JWTServer.cls?client_name=medbank and I see this:

{
  "keys": [
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RS256",
      "use": "sig",
      "kid": "1"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RS384",
      "use": "sig",
      "kid": "2"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RS512",
      "use": "sig",
      "kid": "3"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RSA1_5",
      "use": "enc",
      "kid": "4"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RSA-OAEP",
      "use": "enc",
      "kid": "5"
    }
  ]
}

Previously I had a similar or same configuration return

{
  "keys": [
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RS256",
      "use": "sig",
      "kid": "1"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RS384",
      "use": "sig",
      "kid": "2"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RS512",
      "use": "sig",
      "kid": "3"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RSA1_5",
      "use": "enc",
      "kid": "4"
    },
    {
      "kty": "RSA",
      "n": "znrmjuKwUAI3eH6OiLANiNDkGP6EC8HoA5sr5sEJwAuc3U3IPSQ2SsNgFmNtaArAc7tpovz3_IRxYKOQNz_riq0mBWhtdwc9hp-PAzQOix-cCRz69IXh3nErLrVJ777taO9ARzvxTmcjE_X3TkDq-F5F4fO7OwhvLsl1hjC3nmemkF-gVFD4DQumx84UkwHNu4astSvQrlqFAEvpjbHJ0LP-HNIZe6HP_wUPSCBnE_cFVjR2oxSV5SZEo_Blo2n0d02YVDrqBxccTWEhjbopBWv9JG0IWSL3M7AK7CAa5Oboeub02VBKwTtwNMRmcnKOOMAzDKa-gur7_S_HJWAnvQ",
      "e": "AQAB",
      "alg": "RSA-OAEP",
      "use": "enc",
      "kid": "5"
    }
  ]
}

How can I get JWKS to include ES512 algorithm?

1 Comment
Discussion (1)1
Log in or sign up to continue
Article
· Dec 15, 2024 4m read

第五十一章 File 输入 输出 - 文件路径名工具

第五十一章 File 输入 输出 - 文件路径名工具

文件路径名工具

如果当前设备是顺序文件,则$ZIO包含该文件的完整路径名。

可以使用$ZSEARCH返回指定文件或目录的完整文件规范(路径名和文件名)。文件名可能包含通配符, $ZSEARCH使用通配符返回一系列满足通配符的完全限定路径名。

%Library.File 类包含许多提供文件系统服务的方法。这些包括:

Discussion (0)1
Log in or sign up to continue
Article
· Dec 15, 2024 6m read

Composing an OpenAPI 2.0 specification.

REST API (Representational State Transfer Application Programming Interface) is a standardized way for web applications to communicate with each other using HTTP methods like GET, POST, PUT, DELETE, etc. It's designed around resources, which can be anything from a user to a file. Each resource is identified by a unique URL, and interactions with these resources are stateless, meaning each request from a client to a server must contain all the information needed to understand and process the request. This statelessness, along with the use of standard HTTP methods, makes REST APIs highly scalable, easy to understand, and straightforward to integrate with different systems. By following REST principles, developers can create APIs that are consistent, easy to use, and capable of handling a wide range of tasks.

InterSystems supports REST API development with a variety of tools and techniques. In this article series, I am going to go over the ones that I personally prefer. The articles are divided as listed below.

  • Composing an OpenAPI 2.0 specification.
  • Documenting and Developing REST APIs using OpenAPI 2.0 specification.
  • Developing an IRIS production pipeline to serve REST API calls.

As perquisite to following the steps and instructions laid out in this article series, you should have the below setup.

  1. InterSystems IRIS for Health
  2. InterSystems IAM with Dev Portal deployed and enabled.
  3. Postman or any other API testing software.

Let’s assume that we are developing a workflow for managing clinic appointments. We will focus on an appointment resource and how to develop GET, POST, PUT methods for it. You can use the same steps even to develop a DELETE method, but I am not going to do it because I personally do not prefer it.

First, you need to start with composing an OpenAPI 2.0 spec for your application APIs. I use the swagger editor for this task to be able to develop in YAML format, and then convert the spec file to JSON. I then can use the JSON file to use with IRIS API management tools. You can use the online swagger editor for free or you can download and deploy a container of it locally from here.

When I compose an OpenAPI spec, I think of the file as three sections. The intro section is where you lay out the description information. It includes fields that describe the nature of the application such as the description, license, tags that categorizes different endpoints and the URL by combining the host and base URL. It also includes the confines in the which it can operate if any such as the schemas and security definitions.

The below code block has a sample intro section that going to be reference from here on. If you paste it into an open swagger editor, you will notice that the groundwork of the API documentation is taking shape.

 

swagger: "2.0"
info:
  description: "This is a sample server to be as an example Clinic server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io). For this sample, you can use the api key `special-key` or Basic Auth user `Basic` with password `Basic` to test the authorization filters."
  version: "1.0.0"
  title: "Clinic Management"
  termsOfService: "http://swagger.io/terms/"
  contact:
    email: "raef.youssef@intersystems.com"
  license:
    name: "Apache 2.0"
    url: "http://www.apache.org/licenses/LICENSE-2.0.html"
host: "apigatewaydns"
basePath: "/clinic"
tags:
- name: "Scheduling"
  description: "Everything about your Pets"
  externalDocs:
    description: "Find out more"
    url: "http://intersystems.com"
schemes:
- "http"
- "https"
securityDefinitions:
  BasicAuth:
    type: "basic"
    name: "Basic"
  api_key:
    type: "apiKey"
    name: "api_key"
    in: "header"

Second section of the spec file is the body. This is where you list the different paths, aka endpoints, and the methods that are available for each. For the purpose of this demo, we will just compose spec for the “/appointment” end point. Below is the text for that.


paths:
  /appointment:
    get:
      tags:
        - Scheduling
      summary: "Fetches an existing appointment details"
      security:
      - Basic: []
      description: "Fetches an existing appointment details by providing its ID"
      operationId: "getAppointmentByID"
      produces:
      - "application/json"
      parameters:
      - in: "query"
        name: "id"
        type: "integer"
        format: "int64"
        description: "ID of the appointment sought"
        required: true
      responses:
        '200':
          description: successful operation
#          schema:
#            $ref: '#/definitions/appointment'
    post:
      tags:
        - Scheduling
      summary: ""
      security:
      - api_key: []
      description: ""
      operationId: "postAppointment"
      consumes:
      - "application/json"
      - "application/xml"
      produces:
      - "application/json"
      - "application/xml"
      parameters:
      - in: "formData"
        name: "Date"
        type: "string"
        format: "date-time"
        description: ""
        required: true
      - in: "formData"
        name: "duration"
        type: "integer"
        format: "int64"
        description: "number of half hour slots of the appointment duration"
        required: true
      responses:
        '200':
          description: successful operation
        '405':
          description: Time not available
    put:
      tags:
        - Scheduling
      summary: ""
      security:
      - BasicAuth: []
      description: ""
      operationId: "updateAppointment"
      consumes:
      - "application/json"
      - "application/xml"
      produces:
      - "application/json"
      - "application/xml"
      parameters:
      - in: "query"
        name: "id"
        type: "integer"
        format: "int64"
        description: "ID of the appointment sought"
        required: true
      - in: "body"
        name: "body"
        description: ""
        required: true
#        schema:
#          $ref: "#/definitions/appointment"
      responses:
        '200':
          description: successful operation
        '405' :
          description: Time not available
        '406' :
          description: Appointment Not Found

A few things to note in the paths section. First, you can assign a different authentication mechanism for each method. There is an “OperationID” field which would be used to name the backend process that serves the respective method call. Furthermore, you can define a schema for a request JSON body and response, it commented out here so it won’t error when you paste as we have not defined it yet. Finally, you can define custom response codes and messages.

The last section is where different message schemas are defined. In this example, we will compose the appointment schema to include appointment ID, Date, Duration, and Provider of service name. Below is the text of the YAML definition. After pasting the below in your editor, you can uncomment the lines where the schema definition is referenced.

definitions:
    appointment:
        type: "object"
        properties:
            id:
                type: "integer"
                format: "int64"
            Provider:
                type: "string"
                format: "string"
            Date:
                type: "string"
                format: "date-time"
            Duration:
                type: "integer"
                format: "int64"

This concludes this part of the series. We are going to use this spec in the later parts of the series. They are coming soon so be on the lookout. For more information on developing OpenAPI 2.0 specification please refer to the documentation here.

Discussion (0)1
Log in or sign up to continue