Using OAuth 2.0 and OpenID Connect with Caché
Using a Caché Web Application as an OAuth 2.0 Client
|
|
This chapter describes how to use a Caché web application as a client application that uses the OAuth 2.0 framework. It discusses the following:
This chapter primarily discusses the scenario in which a Caché web application is the client of a web server/client application and uses the authorization code grant type. See the
last section for details on other grant types and other variations.
Before starting the tasks described in this chapter, 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 Caché:
-
Location of the authorization server (issuer endpoint)
-
Location of the authorization endpoint
-
Location of the token endpoint
-
-
Location of the token introspection endpoint (if supported; see
RFC 7662)
-
Location of the token revocation endpoint (if supported; see
RFC 7009)
-
Whether the authorization server supports dynamic registration
Other details apply when you write the client code:
-
Grant types supported by this server
-
-
Other requirements for requests made to this server
-
If the authorization server does not support dynamic client registration, the Caché 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 chapter.)
To use a Caché web application as an OAuth 2.0 client, perform the following configuration tasks:
-
For the web server that is serving Caché, 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 a Caché 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 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.
Each SSL configuration has a unique name. For reference, the documentation refers to this one as
sslconfig, but you can use any unique name.
-
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).
-
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.
-
The Management Portal then displays a new page where you can enter details for the server description.
-
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.
-
Caché 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.
-
-
-
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 definition also copies the public JWKS from the authorization server to the client for its use in signature verification and encryption of JWTs.
-
JWKS from URL Specify a URL that points to a public JWKS and then load the JWKS into Caché.
-
JWKS from file Select a file that contains a public JWKS and then load that file into Caché.
-
Specify these values and then select
Save.
This section describes how to create a client configuration and dynamically register the client.
-
The Management Portal displays the list of server descriptions.
-
The Management Portal then displays the list of client configurations associated with the server description. This list is initially empty.
-
The Management Portal then displays a new page where you can enter details.
-
On the
General tab, specify the following details:
-
-
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.
-
-
-
-
Resource Server Specifies that the client is a resource server which is not also a client.
-
-
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
CSP Gateway configuration.
-
Prefix Specify this if needed to accommodate any changes in the
CSP Gateway configuration.
The resulting URL has the following form:
https://hostname:port/prefix/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.
-
Required grant types Specify the OAuth 2.0 grant types that the client will restrict itself to using.
-
-
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.
-
-
Logo URL URL of the logo for the client application.
-
-
Policy URL URL of the policy 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.
-
-
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.
-
If the authorization server supports dynamic registration, double-check all the data you have entered and then press
Dynamic Registration and Save. Caché 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.
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:
-
-
Client ID Enter the client ID as provided by the authorization server.
-
This chapter 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, later in this chapter.
-
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, later in this chapter.
In order for a Caché web application to act as OAuth 2.0 client, this web application must use logic like the following:
-
-
-
The following sections provide information on these steps.
Note that the pages of this web application must ultimately be based on
%CSP.Page; you can create them with CSP, Zen, or Zen Mojo. It is useful to remember that all these kinds of pages can execute code on the client or on the server. The Caché OAuth 2.0 client API is a set of methods that run on the server.
Note:
This section provides information on the code needed when the client uses the authorization code grant type when requesting tokens. For other grant types, see
Variations, later in this chapter.
To obtain tokens, use steps like the following to obtain tokens. The
subsection provides details on the methods discussed here.
-
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.
-
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
}
-
-
-
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.
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 a Caché OAuth 2.0 client.
-
At this internal URL, which is never visible to users, Caché obtains an authorization code, exchanges that for an access token, and then redirects the browser to the client’s redirect page.
This subsection provides the details on the methods described in the previous subsection.
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
CACHESYS database, and that tokens are removed automatically after they have expired.)
Otherwise the method returns 0.
The arguments are as follows:
-
-
-
-
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 Connect, 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:
-
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.Error containing error information.
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 Caché uses to request the authorization code. (Note that this page is never visible to users.)
The arguments are as follows:
-
-
-
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:
-
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.
-
-
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.
Then examine the dynamic objects returned by reference from these methods. For example,
GetIntrospection() returns a dynamic object that contains the claims made by the introspection endpoint. Use these claims as needed to determine whether to proceed.
ClassMethod ValidateJWT(applicationName 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
Use this method only if the access token is a JWT (rather than an opaque token).
This method decrypts the JWT if necessary, validates the JWT, and creates an object (
jsonObject) to contain the JWT properties. To validate the JWT, the method checks the audience (if
aud is specified), issuer endpoint (must match that specified in server definition), and scope (if
scope is specified). The method also makes sure the access token has not expired. If the JWT is signed, the method checks the signature.
This method returns 1 if the JWT is valid or returns 0 otherwise. It also returns several arguments as output.
The arguments are as follows:
-
-
-
If
scope is specified, the JWT must contain a scope claim that includes this scope.
-
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.
-
-
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.
This array contains the following nodes:
The
keyalg and
encalg nodes are either both specified or both null.
-
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.
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 definition), 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:
-
-
-
-
-
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.
-
-
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.
ClassMethod GetIntrospection(applicationName As %String,
accessToken As %String,
Output jsonObject As %RegisteredObject) As %Status
This method sends the access token to the introspection endpoint, receives a response that contains claims, and creates an object (
jsonObject) that contains the claims returned by that endpoint.
The arguments are as follows:
Note that you cannot use this method if the server does not specify an introspection endpoint or if
Client secret is not specified.
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.
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:
-
-
-
-
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.
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:
-
-
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 6750. The arguments are as follows:
-
-
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.
-
-
-
-
This method returns a status code, which your code should check.
-
-
Check the status returned by the previous step.
-
Optionally examine the HTTP response, which is available as the
HttpResponse property of the HTTP request.
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")
}
You can optionally define delegated authentication for a Caché web client that is used as an OAuth 2.0 client. Caché 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, starting from a superclass provided by Caché. 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().
To create and use a
ZAUTHENTICATE routine for a Caché web client that is used as an OAuth 2.0 client, do all of the following:
-
-
Create the
ZAUTHENTICATE routine. This routine must perform basic setup for a user account, such as specifying roles and other user properties.
-
-
To create and use a custom login page for a Caché web client that is used as an OAuth 2.0 client, do all of the following:
-
-
Specify the application name, scope list, and (optionally) response mode. You can specify these items in either or both of the following ways:
-
-
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 into.
-
SCOPE This specifies the scope list to be used for the access token request. This must be a blank-separated list of strings.
-
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.
-
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:
To add a request parameter that is a JSON object, create a properties element which is an instance of
%DynamicObject. Or create a string that is the UTF-8 encoded serialized object.
-
-
GetCredentials(ServiceName,Namespace,Username,Password,Credentials) Public {
If ServiceName="%Service_CSP" {
// 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_CSP, this sample sets the username and password to specific values that are also used in the
ZAUTHENTICATE() subroutine (which is called in later processing).
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
}
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:
In any case, it is necessary to define a user whose username does not match a normal Caché username.
This chapter primarily discusses the scenario in which a Caché web application uses the authorization code grant type. This section discusses some variations:
In the basic scenario described
earlier in this chapter, 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.
In this variation, the client uses the implicit grant type when requesting tokens.
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:
-
-
-
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.
-
-
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:
-
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.
-
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; Caché provides a method to do this.
-
-
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:
-
-
-
-
-
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:
-
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).
-
Check the
error argument and proceed accordingly.
-
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; Caché provides a method to do this.
-
-
ClassMethod GetAccessTokenClient(applicationName As %String,
scope As %String,
ByRef properties As %String,
Output error As %OAuth2.Error) As %Status
The arguments are as follows:
-
-
-
-
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).
-
Check the
error argument and proceed accordingly.
-
For the authorization code and implicit grant types, the previous instructions use the following steps:
-
-
-
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.
Caché also supports passing the request object as a JWT, as specified in
section 6 of the OpenID Connect Core specification. You can pass the request object
by value or
by reference.
Passing a Request Object by Value
To use the
request parameter to pass the request object as a JWT:
-
ClassMethod MakeRequestJWT(applicationName As %String,
ByRef properties As %String,
Output sc As %Status) As %String
-
-
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:
-
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)
-
set properties("request")=jwt
-
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:
-
ClassMethod UpdateRequestObject(applicationName As %String,
requestName As %String,
ByRef properties As %String,
Output sc As %Status) As %SYS.OAuth2.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:
-
sc, which is returned as output, contains the status code set by this method.
// create requestobject
set requestobject=##class(%SYS.OAuth2.Request).UpdateRequestObject("myapp","myrequest",.properties,.sc)
-
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()
-
set properties("request_uri")=requesturl
-
set url=##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint("myapp",
scope,redirect,.properties,.isAuthorized,.sc, responseMode)
-
Set httpRequest=##class(%Net.HttpRequest).%New()
Set httpRequest.ContentType="application/x-www-form-urlencoded"
...
-
ClassMethod AddAuthentication(applicationName As %String, httpRequest As %Net.HttpRequest) As %Status
-
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.Client, passing the client name as the argument:
New $NAMESPACE
set $NAMESPACE="%SYS"
Set client=##class(OAuth2.Client).Open(applicationName,.sc)
If client="" Quit
-
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)
-
Perform additional processing as needed.
If the authorization server supports token revocation, you can revoke access tokens via the Management Portal or programmatically.
To revoke all the access tokens for a given user, do the following:
-
-
-
To perform this task, you must be logged in as a user who has USE permission on the %Admin_Secure resource.
ClassMethod RevokeToken(applicationName As %String, accessToken As %String) As %Status
The arguments are as follows:
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.
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:
-
-
Select the server description with which the client configuration is associated.
The system then displays all client configurations associated with that server description.
-
Select the configuration of the client whose keys you want to rotate.
-
Note:
The symmetric HS256, HS384, and HS512 algorithms always use the client secret as the symmetric key.
For details on these methods, see the class reference.
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:
-
-
Select the server description with which the client configuration is associated.
The system then displays all client configurations associated with that server description.
-
Select the configuration of the client.
-
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.