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

OAuth 2.0 Client Variations

The instructions on using an InterSystems IRIS® web application as an OAuth 2.0 client focus on the authorization code grant type.

In the basic scenario, the client receives an access token from the authorization server and then optionally calls additional endpoints in the authorization server: the introspection endpoint, the Userinfo endpoint, or both. After that, the client calls the resource server. Notice that it is also possible for the resource server to independently call these endpoints.

This topic discusses some variations.

Disabling PKCE

By default, clients that use the authorization code grant type leverage the Proof Key for Code Exchange (PKCE) extension. In almost all cases, your client should not modify this default behavior because PKCE is an important and widely accepted security feature. However, in rare cases, you might want to disable PKCE.

To disable PKCE, modify the properties argument of GetAuthorizationCodeEndpoint() before calling the method. Your code should include the line:

Set properties("code_verifier")=""

For more information about the properties argument of GetAuthorizationCodeEndpoint(), see Method Details.

Implicit Grant Type

In this variation, the client uses the implicit grant type when requesting tokens.

Configuration requirements: See the instructions in Configuring a Client, but specify Client Type as appropriate for your use case.

Code requirements: The overall flow is similar to the one for the authorization code grant type, but do not call GetAuthorizationCodeEndpoint(). Instead call the GetImplicitEndpoint() method of the %SYS.OAuth2.AuthorizationOpens in a new tab class:

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

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: "openid profile scope3 scope4"

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

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

  • idtokenOnly enables you to obtain only an ID token. If this argument is 0, the method obtains both an access token and (if the request includes the appropriate scope) an ID token. If this argument is 1, the method does not obtain an access token.

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

  • 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.

  • isAuthorized, which is returned as output, equals 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. This parameter equals 0 otherwise.

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

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

Also see Variation: Performing the Redirect within OnPreHTTP.

Password Credentials Grant Type

In this variation, the client uses the password credentials grant type when requesting tokens. You can use this grant type when the client has the password belonging to the resource owner. The client application can simply perform an HTTP POST operation to the token endpoint, without any page redirection; InterSystems IRIS provides a method to do this.

Configuration requirements: See the instructions in Configuring a Client, but note that you do not need to specify Client Secret. (In general, you should use the client secret only when the client secret is needed and it is possible to protect the client secret.)

Code requirements: Your application should do the following:

  1. Call the IsAuthorized() method of %SYS.OAuth2.AccessTokenOpens in a new tab and check the returned value (and possible error), as described in Obtaining Tokens.

  2. If IsAuthorized() returned 0, call the GetAccessTokenPassword() method of %SYS.OAuth2.AuthorizationOpens in a new tab.

    ClassMethod GetAccessTokenPassword(applicationName As %String, 
                                       username As %String, 
                                       password As %String, 
                                       scope As %String, 
                                       ByRef properties As %String,
                                       Output error As %OAuth2.Error) As %Status
    

    The arguments are as follows:

    • applicationName is the name of the client application.

    • username is a username.

    • password is the corresponding password.

    • 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.

    • 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.

    • error, which is returned as output, is either null or is an instance of OAuth2.Error that contains error information.

    This method performs an HTTP POST operation to the token endpoint, and then receives and saves the access token (if any).

  3. Check the error argument and proceed accordingly.

  4. Continue as described in Examining the Token(s) and Adding an Access Token to an HTTP Request.

Client Credentials Grant Type

In this variation, the client uses the client credentials grant type when requesting tokens. This grant type enables the client application to communicate with the resource server independently from any user. There is no user context. The client application can simply perform an HTTP POST operation to the token endpoint, without any page redirection; InterSystems IRIS provides a method to do this.

Configuration requirements: See the instructions in Configuring a Client. Make sure to specify the Client Type as Private and specify Client Secret.

Code requirements: Your application should do the following:

  1. Call the IsAuthorized() method of %SYS.OAuth2.AccessTokenOpens in a new tab and check the returned value (and possible error), as described in Obtaining Tokens.

  2. If IsAuthorized() returned 0, call the GetAccessTokenClient() method of %SYS.OAuth2.AuthorizationOpens in a new tab.

    ClassMethod GetAccessTokenClient(applicationName As %String, 
                                     scope As %String, 
                                     ByRef properties As %String, 
                                     Output error As %OAuth2.Error) As %Status
    

    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.

    • properties, which is passed by reference, is a multidimensional array that contains any parameters to be added to the request. See the properties argument for GetAccessTokenPassword(), in the previous subsection.

    • error, which is returned as output, is either null or is an instance of OAuth2.Error that contains error information.

    This method performs an HTTP POST operation to the token endpoint, and then receives and saves the access token (if any).

  3. Check the error argument and proceed accordingly.

  4. Continue as described in Examining the Token(s) and Adding an Access Token to an HTTP Request.

Performing the Redirect within OnPreHTTP

For the authorization code and implicit grant types, the basic instructions use the following steps:

  1. Call the IsAuthorized() method of %SYS.OAuth2.AccessTokenOpens in a new tab.

  2. Call the GetAuthorizationCodeEndpoint() method (for the authorization code grant type) or call the GetImplicitEndpoint() method (for the implicit grant type).

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

An alternative is to modify the OnPreHttp() method of the page class (in your application), so that it calls either the GetAccessTokenAuthorizationCode() method (for the authorization code grant type) or call the GetAccessTokenImplicit() method (for the implicit grant type). These methods cause the browser to navigate directly (if needed) to the authentication form of the authorization server, without first displaying any content of your page.

Passing Request Objects as JWTs

InterSystems IRIS also supports passing the request object as a JWT, as specified in section 6Opens in a new tab of the OpenID Connect Core specification. You can pass the request object by value or by reference.

In both cases, you use methods of the %SYS.OAuth2.RequestOpens in a new tab class. See the class reference for additional methods not described in this section.

Passing a Request Object by Value

To use the request parameter to pass the request object as a JWT:

  1. Call the MakeRequestJWT() method of the %SYS.OAuth2.RequestOpens in a new tab class:

    ClassMethod MakeRequestJWT(applicationName As %String, 
                               ByRef properties As %String, 
                               Output sc As %Status) As %String
    

    Where:

    • applicationName is the name of the client application.

    • 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.
    • sc, which is returned as output, contains the status code set by this method.

    This method returns a string, which is the JWT. For example:

     // create jwt 
     set jwt=##class(%SYS.OAuth2.Request).MakeRequestJWT("myapp",.properties,.sc)
    
  2. Modify the properties array that you will use as the argument for GetAuthorizationCodeEndpoint() or GetImplicitEndpoint(). Set the node properties("request") equal to the JWT that you created in the previous step. For example:

     set properties("request")=jwt
  3. When you call GetAuthorizationCodeEndpoint() or GetImplicitEndpoint(), include the properties array. For example:

     set url=##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint("myapp",
           scope,redirect,.properties,.isAuthorized,.sc, responseMode)
    

Passing a Request Object by Reference

To use the request_uri parameter to pass the request object as a JWT:

  1. Call the UpdateRequestObject() method of the %SYS.OAuth2.RequestOpens in a new tab class:

    ClassMethod UpdateRequestObject(applicationName As %String, 
                                    requestName As %String, 
                                    ByRef properties As %String, 
                                    Output sc As %Status) As %SYS.OAuth2.Request
    

    Where:

    • applicationName is the name of the client application.

    • requestName is the name of the request.

    • 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.
    • sc, which is returned as output, contains the status code set by this method.

    This method creates, saves, and returns an instance of %SYS.OAuth2.RequestOpens in a new tab.

     // create requestobject 
     set requestobject=##class(%SYS.OAuth2.Request).UpdateRequestObject("myapp","myrequest",.properties,.sc)
    
  2. Get the URL of the saved request object. To do so, call the GetURL() method of the instance. Note that GetURL() returns a status code as output in the first argument; your code should check that.

     Set requesturl=requestobject.GetURL()
  3. Modify the properties array that you will use as the argument for GetAuthorizationCodeEndpoint() or GetImplicitEndpoint(). Set the node properties("request_uri") equal to the URL obtained in the previous step. For example:

    set properties("request_uri")=requesturl
    
  4. When you call GetAuthorizationCodeEndpoint() or GetImplicitEndpoint(), include the properties array. For example:

     set url=##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint("myapp",
           scope,redirect,.properties,.isAuthorized,.sc, responseMode)
    
    

Calling Other Endpoints of the Authorization Server

The methods in %SYS.OAuth2.AuthorizationOpens in a new tab enable you to call a specific set of endpoints in the authorization server. If the authorization server has other endpoints, use the following general process to call them:

  1. Create an instance of %Net.HttpRequestOpens in a new tab, set its properties as needed, and call methods as needed, in order to define the request.

    Set httpRequest=##class(%Net.HttpRequest).%New()
    Set httpRequest.ContentType="application/x-www-form-urlencoded"
    ...
    

    For details on this class, see Sending HTTP Requests.

  2. To add authentication to the request, call the AddAuthentication() method of %SYS.OAuth2.AccessTokenOpens in a new tab.

    ClassMethod AddAuthentication(applicationName As %String, httpRequest As %Net.HttpRequest) As %Status
    

    Where:

    InterSystems IRIS looks up the given client and uses its Authentication type, SSL configuration, and other information to add the appropriate authentication to the request.

  3. Optionally open the client configuration so that you can use properties contained in it. To do so, switch to the %SYS namespace and call the Open() method of OAuth2.ClientOpens in a new tab, passing the client name as the argument:

     New $NAMESPACE
     set $NAMESPACE="%SYS"
     Set client=##class(OAuth2.Client).Open(applicationName,.sc)
     If client="" Quit
  4. Call the Post(), Get(), or Put() method (as appropriate) of the HTTP request object, providing the authorization server’s token endpoint as the argument. For example:

     set sc=httpRequest.Post(client.ServerDefinition.TokenEndpoint)
  5. Perform additional processing as needed.

FeedbackOpens in a new tab