<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dmitrii Kuznetsov</title>
    <description>The latest articles on DEV Community by Dmitrii Kuznetsov (@torgeek).</description>
    <link>https://dev.to/torgeek</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F149916%2F51844aa6-f627-483b-8da9-8afe51af3f0a.jpg</url>
      <title>DEV Community: Dmitrii Kuznetsov</title>
      <link>https://dev.to/torgeek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/torgeek"/>
    <language>en</language>
    <item>
      <title>Four Database APIs</title>
      <dc:creator>Dmitrii Kuznetsov</dc:creator>
      <pubDate>Fri, 24 Sep 2021 15:14:27 +0000</pubDate>
      <link>https://dev.to/intersystems/four-database-apis-4f7n</link>
      <guid>https://dev.to/intersystems/four-database-apis-4f7n</guid>
      <description>&lt;h1&gt;
  
  
  A concurrent session in IRIS:
&lt;/h1&gt;

&lt;h1&gt;
  
  
  SQL, Objects, REST, and GraphQL
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6zrh0ab7t2f0r2avb22.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6zrh0ab7t2f0r2avb22.jpg" alt="Kazimir Malevich, " width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;painting by Kazimir Malevich, "Athletes" (1932)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"But of course you don't understand! How can a person who has always traveled in a horse-drawn carriage understand the feelings and impressions of the express traveler or the pilot in the air?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kazimir Malevich (1916)&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We’ve already addressed the topic of &lt;a href="https://community.intersystems.com/post/should-you-trust-codd-or-your-objects" rel="noopener noreferrer"&gt;why object/type representation is superior&lt;/a&gt; to SQL for implementing subject area models. And those conclusions and facts are as true now as they have ever been. So why should we take a step back and discuss technologies that drag abstractions back to the global level, where they had been in the pre-object and pre-type era? Why should we encourage the use of spaghetti code, which results in bugs that are hard to track down, and which relies only on virtuoso developer skills? &lt;/p&gt;

&lt;p&gt;There are several arguments in favor of transmitting data via SQL/REST/GraphQL-based APIs as opposed to representing them as types/objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These technologies are very well-studied and fairly easy to deploy.&lt;/li&gt;
&lt;li&gt;They enjoy incredible popularity, and have been widely implemented in accessible, open-source software.&lt;/li&gt;
&lt;li&gt;You often have no choice but to use these technologies, especially on the web and in databases.&lt;/li&gt;
&lt;li&gt;Most importantly, APIs still use objects, since they provide the most appropriate way of implementing the APIs in code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we talk about implementing APIs, let's first take a look at the underlying abstraction layers. The diagram below shows how data moves between the place where it is permanently stored and the place where it is processed and presented to the user of our applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhsdwh3dnz5k7j6tspfqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhsdwh3dnz5k7j6tspfqc.png" alt="the underlying abstraction layers" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, data is stored either on spinning hard-disk drives (HDD) or, to use a more modern technology, in flash memory chips on an SSD. Data is written and read using a stream that consists of separate storage blocks on the HDD/SSD. &lt;/p&gt;

&lt;p&gt;The division into blocks is not random. Rather, it is determined by the physics, mechanics, and electronics of the data storage medium. In an HDD, these are the tracks/sectors on a rotating magnetic disk. In an SSD, these are the memory segments in a rewritable silicon chip. &lt;/p&gt;

&lt;p&gt;The essence is the same: these are blocks of information, which we must find and put together in order to retrieve the pieces of data we need. Data must be assembled into structures that match our data model/type with the values that correspond to the time of the query. The DBMS bundled with the file subsystem in the operating system is responsible for the process of assembling and retrieving data.&lt;/p&gt;

&lt;p&gt;We can bypass the DBMS by directly addressing to the file system or even the HDD/SSD. But then we lose two super important bridges to data: between the storage blocks and the file streams, and between the files and the ordered structure in the database model. In other words, we take responsibility for the development of all the code for processing blocks, files, and models, including all optimizations, careful debugging, and long-term reliability tests.&lt;/p&gt;

&lt;p&gt;The DBMS gives us an excellent opportunity to deal with data in a high-level language, using understandable models and representations. This is one of the great advantages of these systems. DBMS and data platforms, such as &lt;a href="https://www.intersystems.com/products/intersystems-iris/" rel="noopener noreferrer"&gt;InterSystems IRIS&lt;/a&gt;, offer even more: the ability to simultaneously access ordered data in a wide variety of ways. And it is up to you which to use in your project.&lt;/p&gt;

&lt;p&gt;Let's take advantage of the variety of tools that IRIS gives us. Let's make the code prettier and cleaner. We will make direct use of the ObjectScript object-oriented language for utilizing and developing APIs. In other words, for example, we will call the SQL code directly from inside the ObjectScript software. For other APIs, we will use ready-made libraries and built-in ObjectScript tools.&lt;/p&gt;

&lt;p&gt;We’ll take our examples from the &lt;a href="https://sqlzoo.net/" rel="noopener noreferrer"&gt;SQLZoo Internet project&lt;/a&gt;, which offers learning resources for SQL. We will use the same data in our other API examples.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you would like to get an overview of the variety of approaches to API design and take advantage of ready-made solutions, here is an interesting and useful collection of public APIs, which have been gathered into &lt;a href="https://github.com/public-apis/public-apis" rel="noopener noreferrer"&gt;a single project on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  SQL
&lt;/h2&gt;

&lt;p&gt;There is no more natural way to start than with SQL. Who here isn't familiar with it? &lt;/p&gt;

&lt;p&gt;There is a huge volume of tutorials and books on SQL. We'll be relying on &lt;a href="https://sqlzoo.net/" rel="noopener noreferrer"&gt;SQLZoo&lt;/a&gt;. This is a good beginner's SQL course with examples, walkthroughs, and a language reference. &lt;/p&gt;

&lt;p&gt;Let's carry over some tasks from SQLZoo to the IRIS platform and solve them using a variety of methods.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How quickly can you access InterSystems IRIS on your computer? One of the fastest options is to deploy a container in Docker from a ready-made InterSystems IRIS Community Edition image. InterSystems IRIS Community Edition is a free developer version of the &lt;a href="https://hub.docker.com/_/intersystems-iris-data-platform" rel="noopener noreferrer"&gt;InterSystems IRIS Data Platform&lt;/a&gt;.&lt;br&gt;
Other ways to access &lt;a href="https://learning.intersystems.com/course/view.php?id=1075&amp;amp;ssoPass=1" rel="noopener noreferrer"&gt;InterSystems IRIS Community Edition in the Learning Portal&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To move the data from SQLZoo to our own IRIS instance storage.&lt;/p&gt;

&lt;p&gt;To do this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the management portal (mine, for example, at &lt;a href="http://localhost:52773/csp/sys/UtilHome.csp" rel="noopener noreferrer"&gt;http://localhost:52773/csp/sys/UtilHome.csp&lt;/a&gt;), &lt;/li&gt;
&lt;li&gt;Switch to the USER area - in Namespace %SYS click the “Switch” link and select USER&lt;/li&gt;
&lt;li&gt;Go to System &amp;gt; SQL - open System Explorer, then SQL and click the “Go” button.&lt;/li&gt;
&lt;li&gt;On the right side will open the tab "Execute query" with the button "Execute" - that's what we need.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To learn more about working with &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GSQL_smp" rel="noopener noreferrer"&gt;SQL through the management portal, see the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have a look at ready-made scripts for deploying the database and SQLZoo test data set in the &lt;a href="https://sqlzoo.net/wiki/SQLZOO:About" rel="noopener noreferrer"&gt;description in the Data section&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here are a couple of direct links for the world table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="http://sqlzoo.net/w/index.php?title=Createworld.txt&amp;amp;action=raw" rel="noopener noreferrer"&gt;script&lt;/a&gt; that is used to create the world database&lt;/li&gt;
&lt;li&gt;The &lt;a href="http://sqlzoo.net/w/index.php?title=Tabworld.txt&amp;amp;action=raw" rel="noopener noreferrer"&gt;data&lt;/a&gt; that goes into that table&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The script for creating the database can be executed in the Query Executor form in the IRIS management portal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;world&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;continent&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;area&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;population&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;gdp&lt;/span&gt; &lt;span class="nb"&gt;DECIMAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;capital&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tld&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;flag&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To load the test set for the &lt;strong&gt;Query Executor&lt;/strong&gt; form, go to the &lt;strong&gt;Wizards &amp;gt; Data Import&lt;/strong&gt; menu. Note that the directory with the test data file must be added in advance, when you create the container, or loaded from your computer through the browser. This option is available in the control panel in the data import wizard.&lt;/p&gt;

&lt;p&gt;Check whether the table with the data is present by running this script in the &lt;strong&gt;Query Executor&lt;/strong&gt; form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;world&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can access the examples and tasks from the SQLZoo website. All of the examples below require that you implement an SQL query in the first assignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;population&lt;/span&gt; 
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;world&lt;/span&gt; 
 &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'France'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9kqpp17hd6y4ygws47i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9kqpp17hd6y4ygws47i.png" alt="the first assignment" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That way, you will be able to keep seamlessly working with the API by transferring tasks from SQLZoo to the IRIS platform.&lt;/p&gt;

&lt;p&gt;Please note: as I’ve discovered, the data at the SQLZoo site interface is different from the exported data. At least in the first example, the values for the population of France and Germany differ. Don't get hung up about it. Use the &lt;a href="https://ec.europa.eu/eurostat/tgm/table.do?tab=table&amp;amp;language=en&amp;amp;pcode=tps00001&amp;amp;tableSelection=1&amp;amp;footnotes=yes&amp;amp;labeling=labels&amp;amp;plugin=1" rel="noopener noreferrer"&gt;Eurostat data&lt;/a&gt; for reference.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Another convenient way to gain SQL access to the database in IRIS is the Visual Studio Code editor with the SQLTools plugin and the &lt;a href="https://github.com/intersystems-community/%20sqltools-intersystems-driver" rel="noopener noreferrer"&gt;SQLTools Driver for InterSystems IRIS&lt;/a&gt;. This solution is popular with developers — give it a spin.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to proceed smoothly to the next step and gain object access to our database, let's take a small detour from "pure" SQL queries to SQL queries &lt;a href="https://docs.intersystems.com/iris20203/csp/docbook/Doc.View.cls?KEY=GSQL_esql" rel="noopener noreferrer"&gt;embedded in the application code in ObjectScript&lt;/a&gt;, which is an object-oriented language built into IRIS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How to set up IRIS access and develop &lt;a href="https://intersystems-community.github.io/vscode-objectscript/" rel="noopener noreferrer"&gt;in ObjectScript in VSCode&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class User.worldquery
{
ClassMethod WhereName(name As %String)
{
    &amp;amp;sql(
        SELECT population INTO :population
          FROM world 
         WHERE name = :name
    )

    IF SQLCODE&amp;lt;0 {WRITE "SQLCODE error ",SQLCODE," ",%msg  QUIT}
    ELSEIF SQLCODE=100 {WRITE "Query returns no results"  QUIT}
    WRITE name, " ", population
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's check the result in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;do ##class(User.worldquery).WhereName("France")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive the name of the country and the number of inhabitants as a response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objects/Types
&lt;/h2&gt;

&lt;p&gt;So, on to the REST/GraphQL story. We are implementing an API for web protocols. More often than not, we would have source code under the hood on the server side in a language that has good support for types, or even an entirely object-oriented paradigm. Here are some of the languages we are talking about: Spring in Java/Kotlin, Django in Python, Ruby on Rails, ASP.NET in C#, or Angular in TypeScript. And, needless to say, objects in ObjectScript, which is native to the IRIS platform. &lt;/p&gt;

&lt;p&gt;Why is this important? The types and objects in your code will be simplified to data structures when they are sent out. You need to consider how models are simplified in the program, which is similar to taking into account the losses in relational models. You also need to make sure that, on the other side of the API, the models are adequately restored and can be used without any distortions. This presents an additional burden: an additional responsibility for you as a programmer. Outside the code and beyond the help of translators, compilers, and other automatic tools, you need to continuously ensure that models are correctly transferred.&lt;/p&gt;

&lt;p&gt;If we look at the above issue from a different perspective, we don’t yet see any technologies and tools on the horizon that can be used to easily transfer types/objects from a program in one language to a program in another. What is left? There are simplified implementations of SQL/REST/GraphQL, and an ocean of documentation describing the API in human-friendly language. Informal (from the computer’s perspective) documentation for developers describes exactly what should be translated into formal code using all the available means, so the computer can process it.&lt;/p&gt;

&lt;p&gt;Programmers constantly develop different approaches to solving the above problems. One of the successful approaches is the cross-language paradigm in the object DBMS of the IRIS platform.&lt;/p&gt;

&lt;p&gt;The following table should help you understand the relationship between the OPP and SQL models in IRIS:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Object-oriented programming (OOP)&lt;/th&gt;
&lt;th&gt;Structured query language (SQL)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Package&lt;/td&gt;
&lt;td&gt;Schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Class&lt;/td&gt;
&lt;td&gt;Table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Property&lt;/td&gt;
&lt;td&gt;Column&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Method&lt;/td&gt;
&lt;td&gt;Stored procedure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relationship between two classes&lt;/td&gt;
&lt;td&gt;Foreign key constraint, built-in join&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object (in memory or on disk)&lt;/td&gt;
&lt;td&gt;Row (on disk)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can learn more about displaying object and relational models from the &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GOBJ_persobj_intro" rel="noopener noreferrer"&gt;IRIS documentation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;When executing our SQL query to create the world table from the example above, IRIS will automatically generate descriptions of the corresponding object in the class named User.world.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class User.world Extends %Persistent [ ClassType = persistent, DdlAllowed, Final, Owner = {_SYSTEM}, ProcedureBlock, SqlRowIdPrivate, SqlTableName = world ]
{
    Property name As %Library.String(MAXLEN = 50) [ Required, SqlColumnNumber = 2 ];

    Property continent As %Library.String(MAXLEN = 60) [ SqlColumnNumber = 3 ];

    Property area As %Library.Numeric(MAXVAL = 9999999999, MINVAL = -9999999999, SCALE = 0) [ SqlColumnNumber = 4 ];

    Property population As %Library.Numeric(MAXVAL = 99999999999, MINVAL = -99999999999, SCALE = 0) [ SqlColumnNumber = 5 ];

    Property gdp As %Library.Numeric(MAXVAL = 99999999999999, MINVAL = -99999999999999, SCALE = 0) [ SqlColumnNumber = 6 ];

    Property capital As %Library.String(MAXLEN = 60) [ SqlColumnNumber = 7 ];

    Property tld As %Library.String(MAXLEN = 5) [ SqlColumnNumber = 8 ];

    Property flag As %Library.String(MAXLEN = 255) [ SqlColumnNumber = 9 ];

    Parameter USEEXTENTSET = 1;

    /// Bitmap Extent Index auto-generated by DDL CREATE TABLE statement.  Do not edit the SqlName of this index.

    Index DDLBEIndex [ Extent, SqlName = "%%DDLBEIndex", Type = bitmap ];

    /// DDL Primary Key Specification

    Index WORLDPKey2 On name [ PrimaryKey, Type = index, Unique ];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a template you can use to develop your application in an object-oriented style. All you need to do is add methods to the class in ObjectScript, which has ready-made bundles for the database. In fact, the methods for this class are "stored procedures," to borrow the SQL terminology. &lt;/p&gt;

&lt;p&gt;Let's try to implement the same example that we completed before using SQL. Add the WhereName method to the User.world class, which will play the role of the "Country information" object designer for the entered country name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ClassMethod WhereName(name As %String) As User.world
{
    Set id = 1
    While ( ..%ExistsId(id) ) {
        Set countryInfo = ..%OpenId(id)
        if ( countryInfo.name = name ) { Return countryInfo }
        Set id = id + 1
    }
    Return countryInfo = ""
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the following in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set countryInfo = ##class(User.world).WhereName("France")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;write countryInfo.name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;write countryInfo.population
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see from this example that, in order to find the desired object by country name, unlike in an SQL query, we need to manually sort through the database records one by one. In the worst-case scenario, if our object is at the end of the list (or is not there at all), we’ll have to sort through all the records. There is a separate discussion about how you can speed up the search process by indexing object fields and autogenerating class methods in IRIS. You can read more in the &lt;a href="https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GSQLOPT_indices#GSQLOPT_indices_openinstance" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and in the posts in the &lt;a href="https://community.intersystems.com/post/useful-auto-generated-methods" rel="noopener noreferrer"&gt;developer community portal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, for our class, knowing the IRIS generated index name from the WORLDPKey2 country name, you can initialize/design an object from the database using a single rapid query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set countryInfo = ##class(User.world).WORLDPKey2Open("France")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;write countryInfo.name
write countryInfo.population
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find some guidelines for deciding whether to use object or SQL access for stored objects in &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GORIENT_ch_persistence#GORIENT_persistence_data_programmatically" rel="noopener noreferrer"&gt;this documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Of course, you should always keep in mind that you may only fully utilize one of them for your tasks.&lt;/p&gt;

&lt;p&gt;Furthermore, thanks to the availability of ready-made binary bundles in IRIS that support common OOP languages, such as Java, Python, C, C# (.Net), JavaScript, and even Julia (see &lt;a href="https://github.com/intersystems-community/JuliaGateway" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and &lt;a href="https://openexchange.intersystems.com/package/JuliaGateway" rel="noopener noreferrer"&gt;OpenExchange&lt;/a&gt;), which is rapidly gaining popularity, you’ll always be able to choose whatever language development tools that are most convenient for you.&lt;/p&gt;

&lt;p&gt;Now let's dive into the discussion on data in the web API.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST, or the RESTful Web API
&lt;/h2&gt;

&lt;p&gt;Let's step outside the boundaries of the server and the familiar terminal and utilize some more mainstream interfaces: the browser and similar applications. These applications rely on the hypertext protocols from the HTTP family to manage interactions between systems. IRIS comes with a bunch of tools that are suited for this purpose, including an actual database server and the Apache HTTP server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer" rel="noopener noreferrer"&gt;Representational state transfer&lt;/a&gt; (REST) is an architectural style for designing distributed applications and, in particular, web applications. Though popular, REST is just a set of architectural principles, while SOAP is a standard protocol maintained by the World Wide Web Consortium (W3C), and thus technologies based on SOAP are backed up by a standard. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The global ID in REST is a URL, and it defines each successive information unit when exchanged with a database or a back-end application. See &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GREST" rel="noopener noreferrer"&gt;documentation for developing REST services in IRIS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In our example, the base identifier will be something like the base from the address of the IRIS server, &lt;a href="http://localhost:52773" rel="noopener noreferrer"&gt;http://localhost:52773&lt;/a&gt;, and the /world/ path to our data that is a subdirectory of it. In particular, we are talking about our /world/France country directory. &lt;/p&gt;

&lt;p&gt;It will look something like the following in a Docker container:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:52773/world/France" rel="noopener noreferrer"&gt;http://localhost:52773/world/France&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are developing a complete application, be sure to check out the &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GREST_intro#GREST_intro_create_overview" rel="noopener noreferrer"&gt;IRIS documentation recommendations&lt;/a&gt;. One of them is based on the REST API description in accordance with the OpenAPI 2.0 specification. &lt;/p&gt;

&lt;p&gt;Let's do this the easy way, by implementing the API manually. In our example, we will create the simplest REST solution that requires just two steps in IRIS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a class path monitor in the URL, which will inherit from the %CSP.REST system class&lt;/li&gt;
&lt;li&gt;Add a call to our monitor class when configuring the IRIS web application&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1: Class Monitor
&lt;/h3&gt;

&lt;p&gt;It should be clear how you can implement a class. Follow &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GREST_csprest#GREST_csprest_urlmap" rel="noopener noreferrer"&gt;instructions in the documentation&lt;/a&gt; for creating a "manual" REST.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/// Description
Class User.worldrest Extends %CSP.REST
{
    Parameter UseSession As Integer = 1;
    Parameter CHARSET = "utf-8";
    XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
    &amp;lt;Routes&amp;gt;
    &amp;lt;Route Url="/:name" Method="GET" Call="countryInfo" /&amp;gt;
    &amp;lt;/Routes&amp;gt;
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to include a handler method. It should perform exactly the same function as the calls in the terminal from the previous example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ClassMethod countryInfo(name As %String) As %Status
{
    set countryInfo = ##class(User.world).WhereName(name)
    write "Country: ", countryInfo.name
    write "&amp;lt;br&amp;gt;"
    write "Population: ", countryInfo.population
    return $$$OK
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the parameter that starts with a colon, :name, is indicated to pass the name of the called handler method in the monitor from the incoming REST query to the parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configuring the IRIS Web Application
&lt;/h3&gt;

&lt;p&gt;Under &lt;strong&gt;System Administration &amp;gt; Security &amp;gt; Applications &amp;gt; Web Applications&lt;/strong&gt;,&lt;/p&gt;

&lt;p&gt;add a new web application with a URL entry address at /world and the following handler: our worldrest monitor class. &lt;/p&gt;

&lt;p&gt;After it is configured, the web application should immediately respond when you go to &lt;a href="http://localhost:52773/world/France" rel="noopener noreferrer"&gt;http://localhost:52773/world/France&lt;/a&gt;. Keep in mind that the database is case sensitive, so the correct letter case must be used when transmitting the request data to the method parameter. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lifehacks:&lt;/p&gt;

&lt;p&gt;Use the debugging tools if necessary. You can find a good description in this &lt;a href="https://community.intersystems.com/post/debugging-web" rel="noopener noreferrer"&gt;two-part article&lt;/a&gt; (check out the comments as well). &lt;br&gt;
If the error "401 Unauthorized" appears, and you are sure that the monitor class is on the server and that there are no errors in the link, try &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GCAS_apps#GCAS_apps_smpapproles" rel="noopener noreferrer"&gt;adding the %All role&lt;/a&gt; on the Application Roles tab in the web application settings. This is not an entirely secure method, and you need to understand the possible implications of allowing access for all roles, but it is acceptable for a local installation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  GraphQL
&lt;/h2&gt;

&lt;p&gt;This is new territory in the sense that you won't find anything in the current IRIS documentation about APIs using GraphQL. However, this shouldn't stop us from using this wonderful tool.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's only five years since &lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL&lt;/a&gt; has gone public. Developed by the Linux Foundation, GraphQL is a query language for APIs. And it is probably safe to say that this is the best technology that resulted from improvement of the REST architecture and the various web APIs. Here is a short &lt;a href="https://dev.to/davinc/graphql-for-beginners-3f1a"&gt;introductory article&lt;/a&gt; about it for beginners. And, thanks to the efforts of InterSystems enthusiasts and engineers, IRIS has offered &lt;a href="https://openexchange.intersystems.com/package/GraphQL" rel="noopener noreferrer"&gt;support for GraphQL&lt;/a&gt; since 2018.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the related article “&lt;a href="https://habr.com/ru/company/intersystems/blog/358720/" rel="noopener noreferrer"&gt;Implementing GraphQL for InterSystems Platforms&lt;/a&gt;”. And here is &lt;a href="https://speakerdeck.com/hellsquirrel/graphql-ponimaiem-obiasniaiem-vniedriaiem?slide=54" rel="noopener noreferrer"&gt;GraphQL understood, explained, and implemented&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The GraphQL application consists of two modules: the back end of the application on the IRIS side and the front end part that runs in the browser. In other words, you need to configure it according to the instructions for the &lt;a href="https://github.com/intersystems-community/GraphQL" rel="noopener noreferrer"&gt;GraphQL and GraphiQL web application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, this is how the application configuration looks for me in IRIS inside a Docker container. These are the settings for a GraphQL web application that acts as a REST monitor and a database schema handler:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyepdqpgvk64jzfpaeu8x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyepdqpgvk64jzfpaeu8x.png" alt="the settings for a GraphQL web application" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the second GraphQL application is a user interface for the browser, written in HTML and JavaScript:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xvz2sq4oaxhrttjjjn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4xvz2sq4oaxhrttjjjn9.png" alt="the second GraphQL application" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It can be run by going to &lt;a href="http://localhost:52773/graphiql/index.html" rel="noopener noreferrer"&gt;http://localhost:52773/graphiql/index.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Without any additional restrictive settings, the application will immediately pick up all the database schemas it can find in the installation area. This means our examples will start working right away. Plus, the front end provides a wonderful organized array of hints from the available objects.&lt;/p&gt;

&lt;p&gt;Here is an example of a GraphQL query for our database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;User_world&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;France&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;population&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here is the matching response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"User_world"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"France"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"population"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;65906000&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what it looks like in the browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2545z5u336b4pe0778h3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2545z5u336b4pe0778h3.png" alt="This is what it looks like in the browser" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngxot7jcva94kj57qejk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngxot7jcva94kj57qejk.png" alt="Summary" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is a lot of energy being invested in such technologies as SQL, REST, and probably also GraphQL. There is also a lot of history behind them. They all play well with each other, within the IRIS platform, to create programs that handle data.&lt;/li&gt;
&lt;li&gt;Although it was not mentioned in this article, IRIS also supports other APIs, based on XML (SOAP) and JSON, that are well implemented.&lt;/li&gt;
&lt;li&gt;Unless you specifically take care of, for example, marshaling your objects, remember that data exchanged via API still represents an incomplete, stripped-down version of an object transfer. You as a developer (not the code) are responsible for ensuring the correct transfer of information about the data type of an object .&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Question for You, Dear Readers
&lt;/h2&gt;

&lt;p&gt;The purpose of this article was not to just compare modern APIs, and not even to review the basic capabilities of IRIS. It was to help you see how easy it is to switch between APIs when accessing a database, take your first steps in IRIS, and obtain rapid results from your task.&lt;/p&gt;

&lt;p&gt;That is why I would be very interested to know what you think: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this type of approach help you get up and running with the software?&lt;/li&gt;
&lt;li&gt;Which process steps make it difficult to master the tools for working with the API in IRIS?&lt;/li&gt;
&lt;li&gt;Could you name an obstacle that you would not have been able to foresee?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you know a user who is still learning how to use IRIS, please ask them to leave a comment below. The resulting discussion will be useful for all involved.&lt;/p&gt;

</description>
      <category>api</category>
      <category>sql</category>
      <category>json</category>
      <category>objectscript</category>
    </item>
    <item>
      <title>OAuth Authorization and InterSystems IRIS: Taming Trust Protocols</title>
      <dc:creator>Dmitrii Kuznetsov</dc:creator>
      <pubDate>Thu, 08 Oct 2020 19:01:24 +0000</pubDate>
      <link>https://dev.to/intersystems/oauth-authorization-and-intersystems-iris-taming-trust-protocols-5abc</link>
      <guid>https://dev.to/intersystems/oauth-authorization-and-intersystems-iris-taming-trust-protocols-5abc</guid>
      <description>&lt;h1&gt;
  
  
  How can you allow computers to trust one another in your absence while maintaining security and privacy?
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk4d8wjpxudubtsoxwvzr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk4d8wjpxudubtsoxwvzr.jpg" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A Dry Martini”, he said. “One. In a deep champagne goblet.”&lt;br&gt;
“Oui, monsieur.”&lt;br&gt;
“Just a moment. Three measures of Gordons, one of vodka, half a measure of Kina Lillet. Shake it very well until it’s ice-cold, then add a large thin slice of lemon peel. Got it?”&lt;br&gt;
"Certainly, monsieur." The barman seemed pleased with the idea.&lt;br&gt;
Casino Royale, Ian Fleming, 1953&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OAuth helps to separate services with user credentials from “working” databases, both physically and geographically. It thereby strengthens the protection of identification data and, if necessary, helps you comply with the requirements of countries' data protection laws.&lt;/p&gt;

&lt;p&gt;With OAuth, you can provide the user with the ability to work safely from multiple devices at once, while "exposing" personal data to various services and applications as little as possible. You can also avoid taking on "excess" data about users of your services (i.e. you can process data in a depersonalized form).&lt;/p&gt;

&lt;p&gt;If you use Intersystems IRIS, you get a complete set of ready-made tools for testing and deploying OAuth and OIDC services, both autonomously and in cooperation with third-party software products.&lt;/p&gt;

&lt;h2&gt;
  
  
  OAuth 2.0 and OpenID Connect
&lt;/h2&gt;

&lt;p&gt;OAuth and OpenID Connect — known as OIDC or simply OpenID — serve as a universal combination of open protocols for delegating access and identification — and in the 21st century, it seems to be a favorite. No one has come up with a better option for large-scale use. It's especially popular with frontenders because it sits on top of HTTP(S) protocols and uses a &lt;a href="https://en.wikipedia.org/wiki/JSON_Web_Token" rel="noopener noreferrer"&gt;JWT (JSON Web Token) container&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OpenID works using OAuth — it is, in fact, a wrapper for OAuth. Using OpenID as an open standard for the authentication and creation of digital identification systems is nothing new for developers. As of 2019, it is in its 14th year (and its third version). It is popular in web and mobile development and in enterprise systems.&lt;/p&gt;

&lt;p&gt;Its partner, the OAuth open standard for delegating access, is 12 years old, and it's been nine years since the relevant RFC 5849 standard appeared. For the purposes of this article, we will rely on the current version of the protocol, OAuth 2.0, and the current &lt;a href="https://tools.ietf.org/html/rfc6749" rel="noopener noreferrer"&gt;RFC 6749&lt;/a&gt;. (OAuth 2.0 is not compatible with its predecessor, OAuth 1.0.)&lt;/p&gt;

&lt;p&gt;Strictly speaking, OAuth is not a protocol, but a set of rules (a scheme) for separating and transferring user identification operations to a separate trusted server when implementing an access-rights restriction architecture in software systems.&lt;/p&gt;

&lt;p&gt;Be aware: OAuth can't say anything about a specific user! Who the user is, or where the user is, or even whether the user is currently at a computer or not. But OAuth makes it possible to interact with systems without user participation, using pre-issued access tokens. This is an important point (see "&lt;a href="https://oauth.net/articles/authentication/" rel="noopener noreferrer"&gt;User Authentication with OAuth 2.0&lt;/a&gt;" on the OAuth site for more information).&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://tools.ietf.org/html/draft-hardjono-oauth-umacore-14" rel="noopener noreferrer"&gt;User-Managed Access (UMA)&lt;/a&gt; protocol is also based on OAuth. Using OAuth, OIDC and UMA together make it possible to implement a protected identity and access management (IdM, IAM) system in areas such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using a patient's &lt;a href="https://openid.net/wg/heart/" rel="noopener noreferrer"&gt;HEART (Health Relationship Trust)&lt;/a&gt; personal data profile in medicine.&lt;/li&gt;
&lt;li&gt;Consumer Identity and Access Management (CIAM) platforms for manufacturing and trading companies.&lt;/li&gt;
&lt;li&gt;Personalizing digital certificates for smart devices in IoT (Internet of Things) systems using the &lt;a href="https://tools.ietf.org/html/draft-tschofenig-ace-oauth-iot-00" rel="noopener noreferrer"&gt;OAuth 2.0 Internet of Things (IoT) Client Credentials Grant&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmzhh2ym7tocqdrcdx6b2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmzhh2ym7tocqdrcdx6b2.png" width="800" height="771"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.csoonline.com/article/2136119/a-new-venn-of-access-control-for-the-api-economy.html" rel="noopener noreferrer"&gt;A New Venn Of Access Control For The API Economy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above all, do not store personal data in the same place as the rest of the system. Separate authentication and authorization physically. And ideally, give the identification and authentication to the individual person. Never store them yourself. Trust the owner's device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trust and Authentication
&lt;/h2&gt;

&lt;p&gt;It is not a best practice to store users' personal data either in one’s own app or in a combined storage location along with a working database. In other words, we choose someone we trust to provide us with this service.&lt;/p&gt;

&lt;p&gt;It is made up of the following parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user&lt;/li&gt;
&lt;li&gt;The client app&lt;/li&gt;
&lt;li&gt;The identification service&lt;/li&gt;
&lt;li&gt;The resource server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The action takes place in a web browser on the user's computer. The user has an account with the identification service. The client app has a signed contract with the identification service and reciprocal interfaces. The resource server trusts the identification service to issue access keys to anyone it can identify.&lt;/p&gt;

&lt;p&gt;The user runs the client web app, requesting a resource. The client app must present a key to that resource to gain access.&lt;br&gt;
If the user doesn’t have a key, then the client app connects with an identification service with which it has a contract for issuing keys to the resource server (passing the user on to the identification service).&lt;/p&gt;

&lt;p&gt;The Identification Service asks what kind of keys are required.&lt;/p&gt;

&lt;p&gt;The user provides a password to access the resource. At this point, the user has been authenticated and identification of the user has been confirmed, thus providing the key to the resource (passing the user back to the client app), and the resource is made available to the user.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementing an Authorization Service
&lt;/h2&gt;

&lt;p&gt;On the Intersystems IRIS platform, you can assemble a service from different platforms as needed. For example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure and launch an OAuth server with the demo client registered on it.&lt;/li&gt;
&lt;li&gt;Configure a demo OAuth client by associating it with an OAuth server and web resources.&lt;/li&gt;
&lt;li&gt;Develop client apps that can use OAuth. You can use Java, Python, C#, or NodeJS. Below is an example of the application code in ObjectScript.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are multiple settings in OAuth, so checklists can be helpful. Let's walk through an example. Go to the IRIS management portal and select the section System Administration &amp;gt; Security &amp;gt; OAuth 2.0 &amp;gt; Server.&lt;/p&gt;

&lt;p&gt;Each item will then contain the name of a settings line and a colon, followed by an example or explanation, if necessary. As an alternative, you can use the screenshot hints in Daniel Kutac's three-part article, &lt;a href="https://community.intersystems.com/post/intersystems-iris-open-authorization-framework-oauth-20-implementation-part-1" rel="noopener noreferrer"&gt;InterSystems IRIS Open Authorization Framework (OAuth 2.0) implementation - part 1&lt;/a&gt;, &lt;a href="https://community.intersystems.com/post/intersystems-iris-open-authorization-framework-oauth-20-implementation-part-2" rel="noopener noreferrer"&gt;part 2&lt;/a&gt;, and &lt;a href="https://community.intersystems.com/post/intersystems-iris-open-authorization-framework-oauth-20-implementation-part-3" rel="noopener noreferrer"&gt;part 3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that all of the following screenshots are meant to serve as examples. You’ll likely need to choose different options when creating your own applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffgas4dddabwe49tqq6nv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffgas4dddabwe49tqq6nv.png" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the General Settings tab, use these settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Description: provide a description of the configuration, such as "Authorization server".&lt;/li&gt;
&lt;li&gt;The endpoint of the generator (hereinafter EPG) host name: DNS name of your server.&lt;/li&gt;
&lt;li&gt;Supported permission types (select at least one):&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Authorization code&lt;br&gt;
Implicit&lt;br&gt;
Account details: Resource, Owner, Password&lt;br&gt;
Client account details&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;SSL/TLS configuration: oauthserver&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the Scopes tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add supported scopes: scope1 in our example&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the Intervals tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access Key Interval: 3600&lt;/li&gt;
&lt;li&gt;Authorization Code Interval: 60&lt;/li&gt;
&lt;li&gt;Update Key Interval: 86400&lt;/li&gt;
&lt;li&gt;Session Interruption Interval: 86400&lt;/li&gt;
&lt;li&gt;Validity period of the client key (client secret): 0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the JWT Settings tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entry algorithm: RS512&lt;/li&gt;
&lt;li&gt;Key Management Algorithm: RSA-OAEP&lt;/li&gt;
&lt;li&gt;Content Encryption Algorithm: A256CBC-HS512&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the Customization tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify Class: %OAuth2.Server.Authenticate&lt;/li&gt;
&lt;li&gt;Check User Class: %OAuth2.Server.Validate&lt;/li&gt;
&lt;li&gt;Session Service Class: OAuth2.Server.Session&lt;/li&gt;
&lt;li&gt;Generate Key Class: %OAuth2.Server.JWT&lt;/li&gt;
&lt;li&gt;Custom Namespace: %SYS&lt;/li&gt;
&lt;li&gt;Customization Roles (select at least one): %DB_IRISSYS and %Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now save the changes.&lt;/p&gt;

&lt;p&gt;The next step is registering the client on the OAuth server. Click the Customer Description button, then click Create Customer Description.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwpgmjlemimj9huhglaib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwpgmjlemimj9huhglaib.png" alt="Client Description" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the General Settings tab, enter the following information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: OAuthClient&lt;/li&gt;
&lt;li&gt;Description: provide a brief description&lt;/li&gt;
&lt;li&gt;Client Type: Confidential&lt;/li&gt;
&lt;li&gt;Redirect URLs: the address of the point to return to the app after identification from oauthclient.&lt;/li&gt;
&lt;li&gt;Supported grant types:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Authorization code: yes&lt;br&gt;
Implicit&lt;br&gt;
Account details: Resource, Owner, Password&lt;br&gt;
Client account details&lt;br&gt;
JWT authorization&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Supported response types: Select all of the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;code&lt;br&gt;
id_token&lt;br&gt;
id_token key&lt;br&gt;
token&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Authorization type: Simple&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Client Account Details tab should be auto-completed, but ensure the information here is correct for the client.&lt;br&gt;
On the Client Information tab:&lt;/p&gt;

&lt;p&gt;Authorization screen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client name&lt;/li&gt;
&lt;li&gt;Logo URL&lt;/li&gt;
&lt;li&gt;Client homepage URL&lt;/li&gt;
&lt;li&gt;Policy URL&lt;/li&gt;
&lt;li&gt;Terms of Service URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now configure the binding on the OAuth server client by going to System Administration &amp;gt; Security &amp;gt; OAuth 2.0 &amp;gt; Client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvtn3nd7nm4sfz3a95j6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvtn3nd7nm4sfz3a95j6r.png" alt="System Administration &amp;gt; Security &amp;gt; OAuth 2.0 &amp;gt; Client" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a Server Description:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The endpoint of the generator: taken from the general parameters of the server (see above).&lt;/li&gt;
&lt;li&gt;SSL/TLS configuration: choose from the preconfigured list.&lt;/li&gt;
&lt;li&gt;Authorization server:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Authorization endpoint: EPG + /authorize&lt;br&gt;
Key endpoint: EPG + /token&lt;br&gt;
User endpoint: EPG + /userinfo&lt;br&gt;
Key self-test endpoint: EPG + /revocation&lt;br&gt;
Key termination endpoint: EPG + /introspection&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;JSON Web Token (JWT) settings:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Other source besides dynamic registration: choose JWKS from URL&lt;br&gt;
URL: EPG + /jwks&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyegdnb6zo6ya33a7zpxm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyegdnb6zo6ya33a7zpxm.png" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From this list, for example, you can see (scopes_supported and claims_supported) that the server can provide the OAuth-client with different information about the user. And it's worth noting that when implementing your application, you should ask the user what data they are ready to share. In the example below, we will only ask for permission for scope1.&lt;/p&gt;

&lt;p&gt;Now save the configuration.&lt;/p&gt;

&lt;p&gt;If there is an error indicating the SSL configuration, then go to Settings &amp;gt; System Administration &amp;gt; Security &amp;gt; SSL/TSL Configurations and remove the configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl8ejvf8jp0sw0yc1k77l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl8ejvf8jp0sw0yc1k77l.png" width="800" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we're ready to set up an OAuth client:&lt;br&gt;
System Administration &amp;gt; Security &amp;gt; OAuth 2.0 &amp;gt; Client &amp;gt; Client configurations &amp;gt; Create Client configurations&lt;br&gt;
On the General tab, use these settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Name: OAuthClient&lt;/li&gt;
&lt;li&gt;Client Name: OAuthClient&lt;/li&gt;
&lt;li&gt;Description: enter a description&lt;/li&gt;
&lt;li&gt;Enabled: Yes&lt;/li&gt;
&lt;li&gt;Client Type: Confidential&lt;/li&gt;
&lt;li&gt;SSL/TCL configuration: select oauthclient&lt;/li&gt;
&lt;li&gt;Client Redirect URL: the DNS name of your server&lt;/li&gt;
&lt;li&gt;Required Permission Types:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Authorization code: Yes&lt;br&gt;
Implicit&lt;br&gt;
Account details: Resource, Owner, Password&lt;br&gt;
Client account details&lt;br&gt;
JWT authorization&lt;br&gt;
Authorization type: Simple&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On Client Information tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorization screen:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Logo URL&lt;br&gt;
Client homepage URL&lt;br&gt;
Policy URL&lt;br&gt;
Terms of Service URL&lt;br&gt;
Default volume: taken from those specified earlier on the server (for example, scope1)&lt;br&gt;
Contact email addresses: enter addresses, separated by commas&lt;br&gt;
Default max age (in seconds): maximum authentication age or omit this option&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On the JWT Settings tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON Web Token (JWT) settings&lt;/li&gt;
&lt;li&gt;Creating JWT settings from X509 account details&lt;/li&gt;
&lt;li&gt;IDToken Algorithms:&lt;/li&gt;
&lt;li&gt;Signing: RS256&lt;/li&gt;
&lt;li&gt;Encryption: A256CBC&lt;/li&gt;
&lt;li&gt;Key: RSA-OAEP&lt;/li&gt;
&lt;li&gt;Userinfo Algorithms&lt;/li&gt;
&lt;li&gt;Access Token Algorithms&lt;/li&gt;
&lt;li&gt;Query Algorithms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the Client Credentials tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client ID: as issued when the client registered on the server (see above).&lt;/li&gt;
&lt;li&gt;Client ID Issued: isn't filled in&lt;/li&gt;
&lt;li&gt;Client secret: as issued when the client registered on the server (see above).&lt;/li&gt;
&lt;li&gt;Client Secret Expiry Period: isn't filled in&lt;/li&gt;
&lt;li&gt;Client Registration URI: isn't filled in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Save the configuration.&lt;/p&gt;
&lt;h2&gt;
  
  
  Web app with OAuth authorization
&lt;/h2&gt;

&lt;p&gt;OAuth relies on the fact that the communication channels between the interaction participants (server, clients, web application, user's browser, resource server) are somehow protected. Most often this role is played by protocols SSL/TLS. But OAuth will work and on unprotected channels. So, for example, server Keycloak, by default uses HTTP protocol and does without protection. It simplifies working out and debugging at working out. At real use of services, OAuth protection of channels should be included strictly obligatory is written down in the documentation Keycloak. Developers InterSystems IRIS adhere to a more strict approach for OAuth - use SSL/TSL is obligatory. The only simplification - you can use the self-signed certificates or take advantage of built-in IRIS service PKI (System administration &amp;gt;&amp;gt; Security &amp;gt;&amp;gt; Public key system).&lt;/p&gt;

&lt;p&gt;Verification of the user's authorization is made with the explicit indication of two parameters - the name of your application registered on the OAuth server, and in the OAuth client scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parameter OAUTH2APPNAME = "OAuthClient";
set isAuthorized = ##class(%SYS.OAuth2.AccessToken).IsAuthorized(
..#OAUTH2APPNAME,
.sessionId,
"scope1",
.accessToken,
.idtoken,
.responseProperties,
.error)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the lack of authorization, we prepare a link to the request for user identification and obtaining permission to work with our application. Here we need to specify not only the name of the application registered on the OAuth server and in the OAuth client and the requested volume (scope) but also the backlink to which point of the web application to return the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parameter OAUTH2CLIENTREDIRECTURI = "https://52773b-76230063.labs.learning.intersystems.com/oauthclient/"
set url = ##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint(
..#OAUTH2APPNAME,
"scope1",
..#OAUTH2CLIENTREDIRECTURI,
.properties,
.isAuthorized,
.sc)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use IRIS and register users on the IRIS OAuth server. For example it is enough to set to the user only a name and the password.&lt;br&gt;
At transfer of the user under the received reference, the server will carry out the procedure of identification of the user and inquiry at it of the permissions for operation by the account data in the web application, and also will keep the result in itself in global OAuth2.Server.Session in the field %SYS:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ful9ah0axxkg33fdwx1e8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ful9ah0axxkg33fdwx1e8.png" alt="sign in" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7k698qox3mryicbocqqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7k698qox3mryicbocqqh.png" alt="permissions" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Demonstrate the data of an authorized user. If the procedures are successful, we have, for example, an access token. Let's get it:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set valid = ##class(%SYS.OAuth2.Validation).ValidateJWT(
.#OAUTH2APPNAME,
accessToken,
"scope1",
.aud,
.JWTJsonObject,
.securityParameters,
.sc
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The full working code of the OAuth example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class OAuthClient.REST Extends %CSP.REST
{
Parameter OAUTH2APPNAME = "OAuthClient";
Parameter OAUTH2CLIENTREDIRECTURI = "https://52773b-76230063.labs.learning.intersystems.com/oauthclient/";
// to keep sessionId
Parameter UseSession As Integer = 1;
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
    &amp;lt;Routes&amp;gt;
        &amp;lt;Route Method="GET" Url = "/" Call = "Do" /&amp;gt;
    &amp;lt;/Routes&amp;gt;
}
ClassMethod Do() As %Status
{
    // Check for accessToken
    set isAuthorized = ##class(%SYS.OAuth2.AccessToken).IsAuthorized(
        ..#OAUTH2APPNAME,
        .sessionId,
        "scope1",
        .accessToken,
        .idtoken,
        .responseProperties,
        .error)
    // to show accessToken
    if isAuthorized {
     set valid = ##class(%SYS.OAuth2.Validation).ValidateJWT(
         ..#OAUTH2APPNAME,
         accessToken,
         "scope1",
         .aud,
         .JWTJsonObject,
         .securityParameters,
         .sc
     )
     &amp;amp;html&amp;lt; Hello!&amp;lt;br&amp;gt; &amp;gt;
         w "You access token = ", JWTJsonObject.%ToJSON()
     &amp;amp;html&amp;lt; &amp;lt;/html&amp;gt; &amp;gt;
     quit $$$OK
    }
    // perform the process of user and client identification and get accessToken
    set url = ##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint(
        ..#OAUTH2APPNAME,
        "scope1",
        ..#OAUTH2CLIENTREDIRECTURI,
        .properties,
        .isAuthorized,
        .sc)
    if $$$ISERR(sc) {
         w "error handling here"
         quit $$$OK
    }
    // url magic correction: change slashes in the query parameter to its code
    set urlBase = $PIECE(url, "?")
    set urlQuery = $PIECE(url, "?", 2)
    set urlQuery = $REPLACE(urlQuery, "/", "%2F")
    set url = urlBase _ "?" _ urlQuery
    &amp;amp;html&amp;lt;
     &amp;lt;html&amp;gt;
         &amp;lt;h1&amp;gt;Authorization in IRIS via OAuth2&amp;lt;/h1&amp;gt;
         &amp;lt;a href = "#(url)#"&amp;gt;Authorization in &amp;lt;b&amp;gt;IRIS&amp;lt;/b&amp;gt;&amp;lt;/a&amp;gt;
     &amp;lt;/html&amp;gt;
    &amp;gt;
    quit $$$OK
}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also find a working copy of the code on the InterSystems GitHub repository: &lt;a href="https://github.com/intersystems-community/iris-oauth-example" rel="noopener noreferrer"&gt;https://github.com/intersystems-community/iris-oauth-example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If necessary, enable the advanced debug message mode on the OAuth server and OAuth client, which are written to the ISCLOG global in the %SYS area:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set ^%ISCLOG = 5
set ^%ISCLOG("Category", "OAuth2") = 5
set ^%ISCLOG("Category", "OAuth2Server") = 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more details, see the &lt;a href="https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GOAUTH" rel="noopener noreferrer"&gt;IRIS Using OAuth 2.0 and OpenID Connect&lt;/a&gt; documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As you've seen, all OAuth features are easily accessible and completely ready to use. If necessary, you can replace the handler classes and user interfaces with your own. You can configure the OAuth server and the client settings from configuration files instead of using the management portal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://openexchange.intersystems.com/package/IRIS-OAuth-example" rel="noopener noreferrer"&gt;Check the related application on InterSystems Open Exchange&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>security</category>
      <category>oauth</category>
      <category>objectscript</category>
    </item>
    <item>
      <title>DataOps: Let's learn how to work with physical objects in IRIS</title>
      <dc:creator>Dmitrii Kuznetsov</dc:creator>
      <pubDate>Fri, 28 Aug 2020 15:20:47 +0000</pubDate>
      <link>https://dev.to/intersystems/dataops-let-s-learn-how-to-work-with-physical-objects-in-iris-3bhe</link>
      <guid>https://dev.to/intersystems/dataops-let-s-learn-how-to-work-with-physical-objects-in-iris-3bhe</guid>
      <description>&lt;p&gt;Liquid syntax error: Unknown tag 'endraw'&lt;/p&gt;
</description>
      <category>beginners</category>
      <category>compiler</category>
      <category>datamodel</category>
      <category>objectscript</category>
    </item>
  </channel>
</rss>
