Skip to main content

This documentation is for an older version of this product. See the latest version of this content.Opens in a new tab

Using an InterSystems IRIS Web Application as an OAuth 2.0 Client

This page describes how to use an InterSystems IRIS® web application as a client application that uses the OAuth 2.0 framework. The focus is the scenario in which an InterSystems IRIS web application is the client of a web server/client application and uses the authorization code grant type. Also see OAuth 2.0 Client Variations.

Note:

When your OAuth 2.0 client is communicating with an Active Directory Federation Service (ADFS) authorization server, your client code must append a special key-value pair to the authorization endpoint. For more details, see the description of GetAuthorizationCodeEndpoint() in Method Details.

Prerequisites for the InterSystems IRIS Client

Before starting the tasks described in this page, make sure the following items are available:

  • An OAuth 2 authorization server. Later you will need to know specific details about this server. Some of the details apply when you configure the client within InterSystems IRIS:

    • Location of the authorization server (issuer endpoint)

    • Location of the authorization endpoint

    • Location of the token endpoint

    • Location of the Userinfo endpoint (if supported; see OpenID Connect CoreOpens in a new tab)

    • Location of the token introspection endpoint (if supported; see RFC 7662Opens in a new tab)

    • Location of the token revocation endpoint (if supported; see RFC 7009Opens in a new tab)

    • Whether the authorization server supports dynamic registration

    Other details apply when you write the client code:

    • Grant types supported by this server

    • Scopes supported by this server. For example, the server may or may not support openid and profile, which are special scopes defined by OpenID Connect CoreOpens in a new tab.

    • Other requirements for requests made to this server

  • If the authorization server does not support dynamic client registration, the InterSystems IRIS application must be registered as a client of the OAuth 2.0 authorization server, and you must have the client ID and client secret for this client. The details depend upon the implementation of the authorization server. (If the server does support dynamic registration, you can register the client while configuring it as described in this page.)

Configuration Requirements

To use an InterSystems IRIS web application as an OAuth 2.0 client, perform the following configuration tasks:

  • For the web server that is serving InterSystems IRIS, configure that web server to use SSL. It is beyond the scope of this documentation to describe how to configure a web server to use SSL.

  • Create an InterSystems IRIS SSL configuration for use by the client.

    This should be a client SSL configuration; no certificate is needed. The configuration is used to connect to a web server. Via this connection, the client communicates with the authorization server to obtain access tokens, call the Userinfo endpoint, call the introspection endpoint, and so on.

    For details on creating SSL configurations, see InterSystems TLS Guide.

    Each SSL configuration has a unique name. For reference, the documentation refers to this one as sslconfig, but you can use any unique name.

  • Create the OAuth 2.0 configuration items for the client. To do so, first create the server description and then create the client configuration, as described in the subsections.

    For both items, to find the needed options in the Management Portal, select System Administration > Security > OAuth 2.0 > Client Configuration. This page provides the options needed when you create an OAuth 2.0 configuration on a client machine (that is, on any machine other than one being used as an authorization server).

    On a client machine, do not use the menu System Administration > Security > OAuth 2.0 > Server Configuration.

Creating a Server Description (Using Discovery)

  1. In the Management Portal, select System Administration > Security > OAuth 2.0 > Client Configuration.

    This displays a page that lists any server descriptions that are available on this instance. In any given row, the Issuer endpoint column indicates the issuer endpoint for the server description. The Client Count column indicates the number of client configurations associated with the given server description. In the last column, the Client Configurations link enables you to create, view, edit, and delete the associated client configurations.

  2. Select Create Server Configuration.

    The Management Portal then displays a new page where you can enter details for the server description.

  3. Specify the following details:

    • Issuer endpoint (required) — Enter the endpoint URL to be used to identify the authorization server.

    • SSL/TLS configuration (required) — Select the SSL/TLS configuration to use when making the dynamic client registration request.

    • Registration access token — Optionally enter the initial registration access token to use as a bearer token to authorize the dynamic client registration request.

  4. Select Discover and Save.

    InterSystems IRIS then communicates with the given authorization server, retrieves information needed in the server description, and then saves that information.

    The Management Portal then redisplays the list of server descriptions.

Manually Creating a Server Description (No Discovery)

To manually create a server description (rather than using discovery), first display the server description page (steps 1 and 2 above) and then select Manual. Then the page displays a larger set of options, as follows:

  • Issuer endpoint (required) — Enter the endpoint URL to be used to identify the authorization server.

  • Authorization endpoint (required) — Enter the endpoint URL to be used when requesting an authorization code from the authorization server.

  • Token endpoint (required) — Enter the endpoint URL to be used when requesting an access token from the authorization server.

  • Userinfo endpoint — Enter the endpoint URL to be used when making a Userinfo request using an access token from the authorization server for authorization.

  • Token introspection endpoint — Enter the endpoint URL to be used when making a token introspection request using the client_id and client_secret for authorization. See RFC 7662Opens in a new tab.

  • Token revocation endpoint— Enter the endpoint URL to be used when making a token revocation request using the client_id and client_secret for authorization. See RFC 7009Opens in a new tab.

  • JSON Web Token (JWT) Settings — Specifies the source of the public keys that the client should use for signature verification and decryption of JWTs from the authorization server.

    By default, the authorization server generates a pair of JWKSs (JSON web key sets). One JWKS is private and contains all the needed private keys (per algorithm) as well as the client secret for use as a symmetric key; this JWKS is never shared. The other JWKS contains the corresponding public keys and is publicly available. The process of creating the server description also copies the public JWKS from the authorization server to the client for its use in signature verification and encryption of JWTs.

    To access any of these options, first select Source other than dynamic registration.

Specify these values and then select Save.

Configuring and Dynamically Registering a Client

This section describes how to create a client configuration and dynamically register the client.

  1. In the Management Portal, select System Administration > Security > OAuth 2.0 > Client Configuration.

    The Management Portal displays the list of server descriptions.

  2. Click the Client Configurations link in the row for the server description with which this client configuration should be associated.

    The Management Portal then displays the list of client configurations associated with the server description. This list is initially empty.

  3. Click Create Client Configuration.

    The Management Portal then displays a new page where you can enter details.

  4. On the General tab, specify the following details:

    • Application name — Specify a short name for the application.

    • Client name — Specify the client name to display to the end user.

    • Description — Specify an optional description of the application.

    • Enabled — Optionally clear this check box if you want to prevent this application from being used.

    • Client Type — Select one of the following:

      • Confidential — Specifies that the client is a confidential client, per RFC 6749Opens in a new tab.

        This page primarily discusses the scenario in which the client uses the authorization code grant type. For this scenario, specify Client Type as Confidential. For other grant types, see Variations.

      • Public — Specifies that the client is a public client, per RFC 6749Opens in a new tab.

      • Resource server — Specifies that the client is a resource server which is not also a client.

    • SSL/TLS configuration — Select the SSL configuration you created for use by the client (for example, sslconfig).

    • The client URL to be specified to the authorization server to receive responses — Specify the URL of the internal destination required for an InterSystems IRIS OAuth 2.0 client. At this destination, the access token is saved and then the browser is further redirected back to the client application.

      To specify this URL, enter values for the following options:

      • Host name — Specify the host name or IP address of the authorization server.

      • Port — Specify this if needed to accommodate any changes in the Web Gateway configuration.

      • Prefix — Specify this if needed to accommodate any changes in the Web Gateway configuration.

      The URL has the following form, using the <baseURL> for your instance:

      https://<baseURL>/csp/sys/oauth2/OAuth2.Response.cls
      
    • Use TLS/SSL — Select this option, unless there is a good reason not to use TLS/SSL when opening the redirect page.

    • Front Channel Logout URL — Optionally specify the HTTP-based front channel logout URL. The server registers this URL and uses it log users out on the client. To create a client that does not support front channel logout, leave the URL empty. The box above this field displays the specified URL and appends 'IRISLogout=end' to it.

      Note:

      For an InterSystems IRIS client to support front channel logout, the Session Cookie Scope of the client application to None. For details on configuring application settings, see Create and Edit Applications.

    • Required grant types — Specify the OAuth 2.0 grant types that the client will restrict itself to using.

    • Authentication type — Select the type of authentication (as specified in RFC 6749Opens in a new tab or OpenID Connect Core section 9Opens in a new tab) to be used for HTTP requests to the authorization server. Select one of the following: none, basic, form encoded body, client secret JWT, or private key JWT.

    • Require iss and sid query parameters when auth server calls logout URL — Select this option to require the iss (issuer) and sid (session ID) query parameters when the authorization server calls the front channel logout URL.

    • Authentication signing algorithm — Select the algorithm that must be used for signing the JWTs used to authenticate this client at the token endpoint (if the authentication type is client secret JWT or private key JWT). If you do not select an option, any algorithm supported by the OpenID provider and the relying party may be used.

  5. On the Client Information tab, specify the following details:

    • Logo URL — URL of the logo for the client application.

    • Client home page URL — URL of the home page for the client application.

    • Policy URL — URL of the policy document for the client application.

    • Terms of service URL — URL of the terms of service document for the client application.

    • Default scope — Specify the default scope, as a blank separated list, for access token requests. This default should be consistent with the scopes permitted by the authorization server.

    • Contact emails — Comma-separated list of email addresses suitable for use in contacting those responsible for the client application.

    • Default max age — Specify the default maximum authentication age, in seconds. If you specify this option, the end user must be actively re-authenticated when the maximum authentication age is reached. The max_age request parameter overrides this default value. If you omit this option, there is no default maximum authentication age.

  6. On the JWT Settings tab, specify the following details:

    • Create JWT Settings from X509 credentials — Select this option if, for signing and encryption, you want to use the private key associated with a certificate; in this case, also see Using Certificates for an OAuth 2.0 Client, in Certificates and JWTs (JSON Web Tokens).

      Note:

      InterSystems expects that the option Create JWT Settings from X509 credentials will rarely be used, and that instead customers use the default behavior described next.

      If you leave this option clear, the system generates a pair of JWKSs (JSON web key sets). One JWKS is private and contains all the needed private keys (per algorithm) as well as the client secret for use as a symmetric key; this JWKS is never shared. The other JWKS contains the corresponding public keys and is publicly available. The dynamic registration process also copies the public JWKS to the authorization server, so that the authorization server can encrypt and verify signatures of JWTs from this client.

    • Signing algorithm — Select the signing algorithm used to create signed JWTs. Or leave this blank if JWTs are not to be signed.

    • Encryption algorithm — Select the encryption algorithm used to create encrypted JWTs. Or leave this blank if JWTs are not to be encrypted. If you select a value, you must also specify Key algorithm.

    • Key algorithm — Select the key management algorithm used to create encrypted JWTs. Or leave this blank if JWTs are not to be encrypted.

  7. If the authorization server supports dynamic registration, double-check all the data you have entered and then press Dynamic Registration and Save. InterSystems IRIS then contacts the authorization server, registers the client, and obtains the client ID and client secret.

    If the authorization server does not support dynamic registration, see the following subsection.

You can update a dynamically registered client configuration by pressing Save and Update Registration on that client’s configuration page.

Configuring a Client (No Dynamic Registration)

If the authorization server does not support dynamic registration, then do the following instead of the last step above:

  1. Select the Client Credentials tab and specify the following details:

    • Client ID — Enter the client ID as provided by the authorization server.

    • Client secret — Enter the client secret as provided by the authorization server. This value is required if the Client Type is Confidential.

      This page primarily discusses the scenario in which the client uses the authorization code grant type. For this scenario, specify a value for Client secret. For other grant types, see Variations.

    Do not enter values for Client ID Issued At, Client Secret Expires At, and Registration Client Uri.

  2. Select Save.

Outline of Code Requirements

Note:

This section describes the code needed when the client uses the authorization code grant type when requesting tokens. For other grant types, see Variations.

In order for an InterSystems IRIS web application to act as OAuth 2.0 client, this web application must use logic like the following:

  1. Obtain an access token (and if needed, an ID token). See Obtaining Tokens.

  2. Examine the access token and (optionally, an ID token) to determine whether the user has the necessary permissions to use the requested resource. See Examining the Tokens.

  3. If appropriate, call the resource server as described in Adding an Access Token to an HTTP Request.

The following sections provide information on these steps.

Obtaining Tokens

Note:

This section provides information on the code needed when the client uses the authorization code grant type when requesting tokens. By default, this authorization code grant type includes the Proof Key for Code Exchange (PKCE) extension. For other grant types and authorization code without PKCE, see Variations.

To obtain tokens, use steps like the following to obtain tokens. The subsection provides details on the methods discussed here.

  1. Call the IsAuthorized() method of the %SYS.OAuth2.AccessTokenOpens in a new tab class. For this, you will need to first determine the desired scope or scopes for the access token.

    For example:

     set myscopes="openid profile scope1 scope2"
     set isAuth=##class(%SYS.OAuth2.AccessToken).IsAuthorized("myclient",,myscopes,
                     .accessToken,.idtoken,.responseProperties,.error)
    

    This method checks to see whether an access token has already been saved locally.

  2. Check to see if the error argument has returned an error and then handle that error appropriately. Note that if this argument contains an error, the function $ISOBJECT() will return 1; otherwise $ISOBJECT() will return 0.

        if $isobject(error) {
       //error handling here
     }
  3. If IsAuthorized() returns 1, skip to Examining the Tokens.

  4. Otherwise, call the GetAuthorizationCodeEndpoint() method of the %SYS.OAuth2.AuthorizationOpens in a new tab class. For this, you will need the following information:

    • Complete URL that the authorization server should redirect to, after it returns an access token. This is the client’s redirect page (which can be the same as the original page, or can be different).

    • The scope or scopes of the request.

    • Any parameters to be included with the request. For example, you may need to pass the claims parameter.

    For example:

     set scope="openid profile scope1 scope2"
     set redirect="https://localhost/csp/openid/SampleClientResult.csp"
    
     set url=##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint("myclient",
           scope,redirect,.properties,.isAuthorized,.sc)
     if $$$ISERR(sc) {
       //error handling here
     }

    This method returns the full URL, including query parameters, of the internal destination required for an InterSystems IRIS OAuth 2.0 client.

    To modify the default Proof Key for Code Exchange (PKCE) behavior for this method, see details about the properties argument in Method Details.

  5. Provide an option (such as a button) that opens the URL returned by GetAuthorizationCodeEndpoint(), thus enabling the user to authorize the request.

    At this internal URL, which is never visible to users, InterSystems IRIS obtains an authorization code, exchanges that for an access token, and then redirects the browser to the client’s redirect page.

Method Details

This subsection provides the details on the methods described in the previous subsection.

IsAuthorized()

Location: This method is in the class %SYS.OAuth2.AccessTokenOpens in a new tab.

ClassMethod IsAuthorized(applicationName As %String, 
                         sessionId As %String, 
                         scope As %String = "", 
                         Output accessToken As %String, 
                         Output IDToken As %String, 
                         Output responseProperties, 
                         Output error As %OAuth2.Error) As %Boolean

This method returns 1 if there is a locally stored access token for this client and this session, and if that access token authorizes all the scopes given by the scope argument. (Note that this method looks for the access token in the IRISSYS database, and that tokens are removed automatically after they have expired.)

Otherwise the method returns 0.

The arguments are as follows:

  • applicationName is the name of the client application.

  • sessionId specifies the session ID. Specify this only if you want to override the default session (%session.SessionId).

  • scope is a space-delimited list of scopes, for example: "openid profile scope1 scope2"

    Note that openid and profile are special scopes defined by OpenID Connect CoreOpens in a new tab.

  • accessToken, which is returned as output, is the access token, if any.

  • IDToken, which is returned as output, is the ID token, if any. (This applies only if you are using OpenId ConnectOpens in a new tab, specifically if the request used the scope openid.) Note that an ID token is a JWT.

  • responseProperties, which is returned as output, is a multidimensional array that contains any parameters of the response. This array has the following structure:

    Array node Array value
    responseProperties(parametername) where parametername is the name of a parameter (such as token_type or expires_in) Value of the given parameter.
  • error, which is returned as output, is either (when there is no error) an empty string or (in the case of error) an instance of %OAuth2.ErrorOpens in a new tab containing error information.

    %OAuth2.ErrorOpens in a new tab has three string properties: Error, ErrorDescription, and ErrorUri.

GetAuthorizationCodeEndpoint()

Location: This method is in the class %SYS.OAuth2.AuthorizationOpens in a new tab.

ClassMethod GetAuthorizationCodeEndpoint(applicationName As %String, 
                                         scope As %String, 
                                         redirectURL As %String, 
                                         ByRef properties As %String, 
                                         Output isAuthorized As %Boolean, 
                                         Output sc As %Status, 
                                         responseMode As %String
                                         sessionId As %String = "") As %String

This method returns the URL, with all needed query parameters, of the local, internal page that InterSystems IRIS uses to request the authorization code. (Note that this page is never visible to users.)

The arguments are as follows:

  • applicationName is the name of the client application.

  • scope is a space-delimited list of scopes for which access is requested, for example: "scope1 scope2 scope3"

    The default is determined by the client configuration for the given applicationName.

  • redirectURL is the full URL of the client’s redirect page, the page to which the authorization server should redirect the browser after returning the access token to the client.

  • properties, which is passed by reference, is a multidimensional array that contains any parameters to be added to the request. This array must have the following structure:

    Array node Array value
    properties(parametername) where parametername is the name of a parameter Value of the given parameter. The value can be a scalar value, an instance of a dynamic object, or the UTF-8 encoded serialized form of a dynamic object.

    Use a dynamic object if you want the request to include a parameter whose value is a JSON object; a scenario is the claims parameter that is defined by OpenID Connect. For details on dynamic objects, see Using JSON.

    To use the request or request_uri parameter, see the section Passing Request Objects as JWTs.

    You can use the code_verifier parameter to modify the secret PKCE value sent to the authorization server. By default, the PKCE secret is generated from a random 43 character string using a SHA-256 hash. To generate the secret from a custom string (for example, if you want to use 128 characters), set the custom value to the code_verifier parameter.

  • isAuthorized, which is returned as output, equals 1 if there is a locally stored access token for this client and this session (scope is not checked). This parameter equals 0 otherwise. There is no need to check this output argument, because we have just called the IsAuthorized() method.

  • sc, which is returned as output, contains the status code set by this method.

  • responseMode specifies the mode of the response from the authorization server. This can be "query" (the default), "fragment" or "form_post". The default is almost always appropriate.

  • sessionId specifies the session ID. Specify this only if you want to override the default session (%session.SessionId).

Note:

An Active Directory Federation Services (AFDS) server expects the authorization endpoint URL to include the key-value pair resource=urn:microsoft:userinfo. You can use the properties argument of GetAuthorizationCodeEndpoint to append this key-value pair to the end of the URL that is defined in the server description. You should avoid using the Management Portal to modify the authorization endpoint to include this information. Rather, use the following code to modify the properties argument before calling the GetAuthorizationCodeEndpoint method:

set properties("resource") = "urn:microsoft:userinfo"
set url = ##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint(appName, scopes, clientRedirectURI, .properties, .isAuthorized,.sc) 

Also see Variation: Performing the Redirect within OnPreHTTP.

Examining the Token(s)

After the client receives an access token (and, optionally, an ID token), the client should perform additional checks to determine whether the user has the necessary permissions to use the requested resource. To perform this examination, the client can use the methods described here to obtain additional information.

ValidateIDToken()

Location: This method is in the class %SYS.OAuth2.ValidationOpens in a new tab.

ClassMethod ValidateIDToken(applicationName As %String, 
                            IDToken As %String, 
                            accessToken As %String, 
                            scope As %String, 
                            aud As %String, 
                            Output jsonObject As %RegisteredObject, 
                            Output securityParameters As %String, 
                            Output sc As %Status) As %Boolean

This method validates the signed OpenID Connect ID token (IDToken) and creates an object (jsonObject) to contain the properties of the ID token. To validate the ID token, the method checks the audience (if aud is specified), endpoint (must match that specified in server description), and scope (if scope is specified), and signature. The method also makes sure the ID token has not expired.

This method also validates the access token (accessToken) based on the at_hash property of the ID token.

This method returns 1 if the ID token is valid or returns 0 otherwise. It also returns several arguments as output.

The arguments are as follows:

  • applicationName is the name of the client application.

  • IDToken is the ID token.

  • accessToken is the access token.

  • scope is a space-delimited list of scopes, for example: "scope1 scope2 scope3"

  • aud specifies the audience that is using the token. If the token has an associated aud property (usually because the audience was specified when requesting the token), then aud is matched to the token audience. If aud is not specified, then no audience checking takes place.

  • jsonObject, which is returned as output, is a dynamic object that contains the properties of the IDToken. Note that an ID token is a JWT. For details on dynamic objects, see Using JSON.

  • securityParameters, which is returned as output, is a multidimensional array that contains security information taken from the header, for optional additional use in verifying signatures, decrypting, or both. See the securityParameters argument for ValidateJWT().

  • sc, which is returned as output, contains the status code set by this method.

If this method returns success (1), examine jsonObject, and use the contained claims as needed to determine whether to allow access to the requested resource. Use securityParameters if needed.

GetUserinfo()

Location: This method is in the class %SYS.OAuth2.AccessTokenOpens in a new tab.

ClassMethod GetUserinfo(applicationName As %String, 
                        accessToken As %String, 
                        IDTokenObject As %RegisteredObject, 
                        Output jsonObject As %RegisteredObject, 
                        Output securityParameters As %String) As %Status

This method sends the access token to the Userinfo endpoint, receives a response that contains claims, and creates an object (jsonObject) that contains the claims returned by that endpoint. If the response returns a JWT, then the response is decrypted and the signature is checked before jsonObject is created. If the argument IDTokenObject is specified, the method also verifies that the sub claim from the User info endpoint matches the sub claim in IDTokenObject.

The request is authorized using the specified access token.

The arguments are as follows:

  • applicationName is the name of the client application.

  • accessToken is the access token.

  • IDTokenObject (optional), is a dynamic object containing an ID token. For details on dynamic objects, see Using JSON.

  • jsonObject, which is returned as output, is a dynamic object that contains the claims returned by Userinfo endpoint.

  • securityParameters, which is returned as output, is a multidimensional array that contains security information taken from the header, for optional additional use in verifying signatures, decrypting, or both. See the securityParameters argument for ValidateJWT().

If this method returns success (1), examine jsonObject, and use the contained claims as needed to determine whether to allow access to the requested resource. Use securityParameters if needed.

Adding an Access Token to an HTTP Request

After the client application has received and examined an access token, the application can make HTTP requests to the resource server. Depending on the application, those HTTP requests may need the access token.

To add an access token to an HTTP request (as a bearer token HTTP authorization header), do the following:

  1. Create an instance of %Net.HttpRequestOpens in a new tab and set properties as needed.

    For details on this class, see Sending HTTP Requests.

  2. Call the AddAccessToken() method of %SYS.OAuth2.AccessTokenOpens in a new tab, which adds the access token to the HTTP request. This method is as follows:

    ClassMethod AddAccessToken(httpRequest As %Net.HttpRequest, 
                               type As %String = "header", 
                               sslConfiguration As %String,  
                               applicationName As %String,  
                               sessionId As %String) As %Status
    

    This method adds the bearer access token associated with the given application and session to the resource server request as defined by RFC 6750Opens in a new tab. The arguments are as follows:

    • httpRequest is the instance of %Net.HttpRequestOpens in a new tab that you want to modify.

    • type specifies how to include the access token in the HTTP request:

      • "header" — Use the bearer token HTTP header.

      • "body" — Use form-encoded body. In this case, the request must be a POST with a form-encoded body.

      • "query" — Use a query parameter.

    • sslConfiguration is the InterSystems IRIS SSL configuration to use for this HTTP request. If you omit this, InterSystems IRIS uses the SSL configuration associated with the client configuration.

    • applicationName is the name of the client application.

    • sessionId specifies the session ID. Specify this only if you want to override the default session (%session.SessionId).

    This method returns a status code, which your code should check.

  3. Send the HTTP request (as described in Sending HTTP Requests. To do so, you call a method such as Get() or Put().

  4. Check the status returned by the previous step.

  5. Optionally examine the HTTP response, which is available as the HttpResponse property of the HTTP request.

    See Sending HTTP Requests.

For example:

 set httpRequest=##class(%Net.HttpRequest).%New()
 // AddAccessToken adds the current access token to the request.
 set sc=##class(%SYS.OAuth2.AccessToken).AddAccessToken(httpRequest,,"sslunittest",applicationName)
 if $$$ISOK(sc) {
    set sc=httpRequest.Get("https://myresourceserver/csp/openid/openid.SampleResource.cls")
 }

Optionally Defining Delegated Authentication for the Web Client

You can optionally define delegated authentication for an InterSystems IRIS web client that is used as an OAuth 2.0 client. InterSystems IRIS provides two ways that you can do this:

  • By creating and using a ZAUTHENTICATE routine, starting from a sample that is provided for use with OAuth 2.0. Your client code must also call %session.Login().

  • By creating and using a custom login page. It is also necessary to create and use a ZAUTHENTICATE routine (starting from the same sample that is provided for use with OAuth 2.0), but your client code does not need to call %session.Login().

The following subsections give the details. A final subsection discusses the ZAUTHENTICATE sample.

Also see REST Applications and OAuth 2.0 in Securing REST Services.

Important:

If using authentication with HealthShare®, you must use the ZAUTHENTICATE routine provided by InterSystemsOpens in a new tab and cannot write your own.

Creating and Using a ZAUTHENTICATE Routine for an OAuth 2.0 Client

To create and use a ZAUTHENTICATE routine for an InterSystems IRIS web client that is used as an OAuth 2.0 client, do all of the following:

Creating and Using a Custom Login Page for an OAuth 2.0 Client

To create and use a custom login page for an InterSystems IRIS web client that is used as an OAuth 2.0 client, do all of the following:

  • Create a subclass of %OAuth2.LoginOpens in a new tab. In your subclass:

    • Specify the application name, scope list, and (optionally) response mode. You can specify these items in either or both of the following ways:

      • By specifying parameters of your subclass of %OAuth2.LoginOpens in a new tab.

      • By overriding the DefineParameters() class method. In contrast to specifying parameters, this technique enables you to set these values at runtime.

      The parameters are as follows:

      • APPLICATION — This must be the application name for the application being logged in to.

      • SCOPE — This specifies the scope list to be used for the access token request. This must be a blank-separated list of strings.

      • RESPONSEMODE — This specifies the mode of the response. The allowed values are "query" (the default), "fragment" or "form_post".

      The DefineParameters() class method has the following signature:

      ClassMethod DefineParameters(Output application As %String, Output scope As %String, Output responseMode As %String)
      

      This method returns the application name, scope list, and response mode as output arguments. The default implementation of this method returns the values of the APPLICATION, SCOPE, and RESPONSEMODE class parameters.

    • In your subclass of %OAuth2.LoginOpens in a new tab, also specify the properties list for the GetAccessTokenAuthorizationCode() call. To do so, override the DefineProperties() class method. This method has the following signature:

      ClassMethod DefineProperties(Output properties As %String)
      

      This method returns (as output) the properties array, which is a local array specifying additional properties to be included in a token request. The properties array has the following form:

      Node Value
      properties(name), where name is the name of a parameter. Value of the given parameter.

      To add a request parameter that is a JSON object, create a properties element which is an instance of %DynamicObjectOpens in a new tab. Or create a string that is the UTF-8 encoded serialized object.

      To add the request or request_uri request parameters, use the %SYS.OAuth2.RequestOpens in a new tab class to create the JWT. Then, as appropriate, set properties("request") equal to the JWT or set properties("request_uri") equal to the URL of the JWT.

  • Configure the relevant web application to use the custom login page.

  • Create and use a ZAUTHENTICATE routine as described in the previous section, except for the first bullet item. (In this scenario, there is no need for the client code to call %session.Login().)

Notes about the OAUTH2.ZAUTHENTICATE.mac Sample

The OAUTH2.ZAUTHENTICATE.mac sample (from https://github.com/intersystems/Samples-SecurityOpens in a new tab) supports both scenarios described in the previous subsections. In this sample, the GetCredentials() subroutine looks like this:

GetCredentials(ServiceName,Namespace,Username,Password,Credentials) Public {
    If ServiceName="%Service_WebGateway" {
        // Supply user name and password for authentication via a subclass of %OAuth2.Login
        Set Username="OAuth2"
        Set Password=$c(1,2,3)
    }
    Quit $$$OK
}

This subroutine is called if no username and password are provided (which is the case when the custom login page is being used). For the service %Service_WebGateway, this sample sets the username and password to specific values that are also used in the ZAUTHENTICATE() subroutine (which is called in later processing).

The ZAUTHENTICATE() subroutine includes the following:

If Username="OAuth2",Password=$c(1,2,3) {
    // Authentication is via a subclass of %OAuth2.Login that sets the query parameter CSPOAUTH2
    // with a hash value that allows GetCurrentApplication to determine the application -- 
    // username/password is supplied by GetCredentials.
    Set sc=##class(OAuth2.Response).GetCurrentApplication(.applicationName)
    Set sessionId=%session.SessionId
} Else {
    // If authentication is based on %session.Login, then application and session id are passed in.
    Set applicationName=Username
    Set sessionId=Password
}

A later step calls the isAuthorized() method like this:

Set isAuthorized=##class(%SYS.OAuth2.AccessToken).IsAuthorized(applicationName,sessionId,,.accessToken,,,.error)

If isAuthorized() returns 1, then later code calls the introspection endpoint and uses the information obtained there to define a user:

Set sc=##class(%SYS.OAuth2.AccessToken).GetIntrospection(applicationName,accessToken,.jsonObject)
...
Set Username="OAuth2"_jsonObject.sub
Set Properties("FullName")="OAuth account "_Username
Set Properties("Username")=Username
Set Properties("Password")=""    // we don't really care about oauth2 account password
// Set the roles and other Properties as appropriate.
Set Properties("Roles")=roles

Your code could use different logic to obtain the information needed to define the user. You could instead obtain this information in the following ways:

  • From IDToken if you are using OpenID Connect. In this case, call the ValidateIDToken() of %SYS.OAuth2.Validate.

  • From Userinfo endpoint if you are OpenID Connect. In this case, call the GetUserinfo() of %SYS.OAuth2.AccessTokenOpens in a new tab.

In any case, it is necessary to define a user whose username does not match a normal InterSystems IRIS username.

Your routine would also need to set roles and other parts of the Properties array as needed for your application. See Create Delegated (User-Defined) Authentication Codeand Delegated Authentication.

Revoking Access Tokens

If the authorization server supports token revocation, you can revoke access tokens via the Management Portal or programmatically.

Revoking a User’s Access Tokens

To revoke all the access tokens for a given user, do the following:

  1. Select System Administration > Security > OAuth 2.0 > Administration.

  2. Type the user ID into the field Revoke tokens for user.

  3. Select Revoke.

To perform this task, you must be logged in as a user who has USE permission on the %Admin_Secure resource.

Revoking Access Tokens Programmatically

If it is necessary for the client to revoke an access token, use the RevokeToken() method of %SYS.OAuth2.AccessTokenOpens in a new tab. Note that when the session holding a given token is deleted, the system automatically calls this method (if a revocation endpoint is specified).

ClassMethod RevokeToken(applicationName As %String, accessToken As %String) As %Status

The arguments are as follows:

  • applicationName is the name of the client application.

  • accessToken is the access token.

The request is authorized using the basic authorization HTTP header with the client_id and client_secret associated with applicationName.

For example:

set sc=##class(%SYS.OAuth2.AccessToken).RevokeToken("myclient",accessToken)
if $$$ISERR(sc) {
    //error handling here
}

Note that you cannot use this method if the server does not specify a revocation endpoint or if Client secret is not specified.

%SYS.OAuth2.AccessTokenOpens in a new tab also provides the method RemoveAccessToken(), which removes the access token from the client but does not remove the token from the server.

Rotating Keys Used for JWTs

In most cases, you can cause the client to generate new public/private key pairs; this applies only to the RSA keys used for the asymmetric RS256, RS384, and RS512 algorithms. (The exception is if you specify Source other than dynamic registration as X509 certificate. In this case, it is not possible to generate new keys.)

Generating new public/private key pairs is known as key rotation; this process adds new private RSA keys and associated public RSA keys to the private and public JWKSs.

When you perform key rotation on the client, the client uses the new private RSA keys to sign JWTs to be sent to the authorization server. Similarly, the client uses the new public RSA keys to encrypt JWTs to be sent to the authorization server. To decrypt JWTs received from the authorization server, the client uses the new RSA keys, and if that fails, uses the old RSA keys; thus the client can decrypt a JWT that was created using its old public RSA keys. Last, if the client cannot verify a signed JWT received from the authorization server, then if the client has the URL for the authorization server public JWKS, the client obtains a new public JWKS and tries again to verify the signature. (Note that the client has a URL for the authorization server public JWKS if the client was registered dynamically or if the configuration specified the JWKS from URL option; otherwise, the client does not have this URL.)

To rotate keys for a given client configuration:

  1. In the Management Portal, select System Administration > Security > OAuth 2.0 > Client Configuration.

  2. Select the server description with which the client configuration is associated.

    The system then displays all client configurations associated with that server description.

  3. Select the configuration of the client whose keys you want to rotate.

  4. Select the Rotate Keys button.

Note:

The symmetric HS256, HS384, and HS512 algorithms always use the client secret as the symmetric key.

API for Key Rotation on the Client

To rotate keys programmatically on the client, call the RotateKeys() method of OAuth2.ClientOpens in a new tab.

To obtain a new authorization server public JWKS, call the UpdateJWKS() method of OAuth2.ServerDefinitionOpens in a new tab.

For details on these methods, see the class reference.

Getting a New Public JWKS from the Authorization Server

In most cases, the authorization server generates a public/private pair of JWKSs. There are different ways in which the client can receive the public JWKS. One way is for the authorization server to provide the public JWKS at a URL; see the JWKS from URL option in Manually Creating a Server Description (No Discovery).

If the authorization server was defined with JWKS from URL and if the authorization server generates a new pair of JWKSs, you can cause the client to obtain the new public JWKS from the same URL. To do so:

  1. In the Management Portal, select System Administration > Security > OAuth 2.0 > Client Configuration.

  2. Select the server description with which the client configuration is associated.

    The system then displays all client configurations associated with that server description.

  3. Select the configuration of the client.

  4. Select the Update JWKS button.

If the authorization server was not defined with JWKS from URL and if the authorization server generates a new pair of JWKSs, it is necessary to obtain the public JWKS, send it to the client, and load it from a file.

FeedbackOpens in a new tab