# Consent Service: JavaScript API

The following methods may be implemented in a consent service script:

- **[consentStartOperation](/content/docs/security/consent_service_javascript.html#consentStartOperation/index.html)**: Called once at the start of each request.
- **[consentCanSeeResource](/content/docs/security/consent_service_javascript.html#consentCanSeeResource/index.html)**: Called once for each resource that may potentially be revealed to the user (i.e. potentially multiple times for a single request).
- **[consentWillSeeResource](/content/docs/security/consent_service_javascript.html#consentWillSeeResource/index.html)**: Called once for each resource that may potentially be revealed to the user (i.e. potentially multiple times for a single request).
- **[completeOperationSuccess](/content/docs/security/consent_service_javascript.html#completeOperationSuccess/index.html)**: Called once at the end of any request that completes normally.
- **[completeOperationFailure](/content/docs/security/consent_service_javascript.html#completeOperationFailure/index.html)**: Called once at the end of any request that completes unsuccessfully.

# Method: consentStartOperation

This method is called once at the start of each request. The purpose is to determine whether a request should be permitted to proceed, and whether to apply the rest of the consent service logic to the request. It may also pre-fetch any relevant data or resources that will be used to provide consent rules in subsequent method calls.

Inputs:

- `theRequestDetails` – This object contains details about the FHIR request being made. The object will be of type [RequestDetailsJson](/content/docs/javascript_execution_environment/callback_models.html#requestdetailsjson/index.html).
- `theUserSession` – This object contains details about the authenticated user and their session. This includes demographics, permissions, approved scopes, etc. The object will be of type [UserSessionDetailsJson](/content/docs/javascript_execution_environment/callback_models.html#usersessiondetails/index.html).
- `theContextServices` – This object has utility methods for interacting with the environment, and indicating a consent outcome to the rest of the framework. The object will be of type [ScriptConsentContextServices](/content/docs/javascript_execution_environment/callback_models.html#scriptconsentcontextservices/index.html).
- `theClientSession` – This object contains details about the authenticated OIDC client and their OAuth2 session. The object will be of type [OAuth2ClientSession](/content/docs/javascript_execution_environment/callback_models.html#oauth2clientsession/index.html).

Outputs:

- This method does not return an output, but must indicate a response mode by calling an appropriate method on `theContextServices`.

Example:

```javascript
function consentStartOperation(theRequestDetails, theUserSession, theContextServices, theClientSession) {

// For superusers, we will skip the rest of the consent service entirely
	if (theUserSession != null && theUserSession.hasAuthority('ROLE_SUPERUSER')) {
		theContextServices.authorized();
		return;
	}

// By default, this request should continue but still be evaluated by the service
	theContextServices.proceed();

}
```

Copy

# Method: consentCanSeeResource

This method is called once for each resource that may be returned to the user. It has the ability to authorize the release of data, or to block it, or to request that it be passed to [consentWillSeeResource](/content/docs/security/consent_service_javascript.html#consentWillSeeResource/index.html) for masking.

Note that this method will not be called if `theContextServices.authorized()` was invoked by the consent script in the `consentStartOperation(...)` method. This method can carry a significant performance impact, so it should only be used if necessary.

Inputs:

Outputs:

- This method does not return an output, but must indicate a response mode by calling an appropriate method on `theContextServices`.

Example:

```javascript
/**
 * If present, this function is called before every resource that may be returned
 * to the user.
 *
 * @param theRequestDetails  Contains details about the request (e.g. the
 *                           FHIR operation being performed, the HTTP method,
 *                           the URL, etc.
 * @param theUserSession     Contains details about the logged in user and
 *                           their session.
 * @param theContextServices Contains various utility methods for accessing
 *                           relevant information about the request, as well
 *                           as providing a response.
 * @package theResource      The resource that will be accessed.
 * @param theClientSession   Contains details about the OIDC client and
 *                           their OAuth2 session.
 */
function consentCanSeeResource(theRequestDetails, theUserSession, theContextServices, theResource, theClientSession) {
	if ( ...some condition... ) {
		theContextServices.reject();
	} else {
		theContextServices.proceed();
	}
}
```

Copy

# Method: consentWillSeeResource

This method is called once for each resource that is being returned to the user. It has the ability to mask specific elements (or even the whole resource) from being returned to the user.

Inputs:

Outputs:

- This method does not return an output, but must indicate a response mode by calling an appropriate method on `theContextServices`.

Example:

Copy

# Method: completeOperationSuccess

This function will be called exactly once for each request that completes successfully (i.e. returns an HTTP 2xx response). Note that in the case of failed requests (HTTP 4xx or 5xx), [completeOperationFailure](/content/docs/security/consent_service_javascript.html#completeOperationFailure/index.html) will be called instead.

Inputs:

Outputs:

- This method does not return an output.

Example:

```javascript
/**
 * If present, this function is called when a request has been handled
 * successfully (i.e. an HTTP 2xx response)
 *
 * @param theRequestDetails  Contains details about the request (e.g. the
 *                           FHIR operation being performed, the HTTP method,
 *                           the URL, etc.
 * @param theUserSession     Contains details about the logged in user and
 *                           their session.
 * @param theContextServices Contains various utility methods for accessing
 *                           relevant information about the request, as well
 *                           as providing a response.
 * @param theClientSession   Contains details about the OIDC client and
 *                           their OAuth2 session.
 */
function completeOperationSuccess(theRequestDetails, theUserSession, theContextServices, theClientSession) {
	// some functions...
}
```

Copy

# Method: completeOperationFailure

This function will be called exactly once for each request that completes unsuccessfully (i.e. returns an HTTP 4xx or 5xx response).

Inputs:

Outputs:

- This method does not return an output.

Example:

```javascript
/**
 * If present, this function is called when a request has been handled
 * unsuccessfully (i.e. an HTTP 4xx/5xx response)
 *
 * @param theRequestDetails  Contains details about the request (e.g. the
 *                           FHIR operation being performed, the HTTP method,
 *                           the URL, etc.
 * @param theUserSession     Contains details about the logged in user and
 *                           their session.
 * @param theContextServices Contains various utility methods for accessing
 *                           relevant information about the request, as well
 *                           as providing a response.
 * @param theClientSession   Contains details about the OIDC client and
 *                           their OAuth2 session.
 */
function completeOperationFailure(theRequestDetails, theUserSession, theContextServices, theClientSession) {
	// some functions
}
```

Copy

# Example: Tag-Based Consent Script

The following example shows a simple consent script, implementing consent rules based on user permissions and resource [security labels](https://www.hl7.org/fhir/security-labels.html).

In this example:

- Users with the `ROLE_SUPERUSER` permission do not have any consent rules applied
- Observation resources with the `R` (restricted) security label will have their `Observation.value` and `Observation.note` fields cleared before they are returned to the user.
- Any resources with the `V` (very restricted) security label will not be shown to the user at all.

```javascript
/**
 * If present, this function is called before every request. It serves two
 * primary purposes:
 *
 * 1. It can be used to proactively determine that a request does not need
 *    to have the consent service applied to it. This is good for
 *    performance, since applying the consent service has performance
 *    implications.
 * 2. It can be used to proactively load consent directives, user
 *    information, etc. that will be used in future methods.
 *
 * @param theRequestDetails  Contains details about the request (e.g. the
 *                           FHIR operation being performed, the HTTP method,
 *                           the URL, etc.
 * @param theUserSession     Contains details about the logged in user and
 *                           their session.
 * @param theContextServices Contains various utility methods for accessing
 *                           relevant information about the request, as well
 *                           as providing a response.
 * @param theClientSession   Contains details about the OIDC client and
 *                           their OAuth2 session.
 */
function consentStartOperation(theRequestDetails, theUserSession, theContextServices, theClientSession) {

// By default, this request should continue but still be evaluated by the service
	theContextServices.proceed();

}

/**
 * If present, this function is called before every resource that may be returned
 * to the user.
 *
 * @param theRequestDetails  Contains details about the request (e.g. the
 *                           FHIR operation being performed, the HTTP method,
 *                           the URL, etc.
 * @param theUserSession     Contains details about the logged in user and
 *                           their session.
 * @param theContextServices Contains various utility methods for accessing
 *                           relevant information about the request, as well
 *                           as providing a response.
 * @package theResource      The resource that will be accessed.
 * @param theClientSession   Contains details about the OIDC client and
 *                           their OAuth2 session.
 */
function consentCanSeeResource(theRequestDetails, theUserSession, theContextServices, theResource, theClientSession) {

if (theResource.meta.hasSecurity('https://www.hl7.org/fhir/v3/Confidentiality/cs.html', 'V')) {

// Any resources with a security label of "V" (very restricted) is rejected,
		// meaning that the client doesn't see them and doesn't even know that they
		// exist
		theContextServices.reject();

} else if (theResource.meta.hasSecurity('https://www.hl7.org/fhir/v3/Confidentiality/cs.html', 'R')) {

// Any resources with a security label of "R" (restricted) is allowed to
		// proceed, but will still pass through consentWillSeeResource(...) for
		// filtering
		theContextServices.proceed();

} else {

// Any other resources are authorized, meaning that the client will get
		// to see the resources, and consentWillSeeResource(...) is not called. This
		// is good for performance but means that no filtering can take place.
		theContextServices.authorized();
	}

}

/**
 * If present, this function is called before every resource that will be
 * shown to the user.
 *
 * @param theRequestDetails  Contains details about the request (e.g. the
 *                           FHIR operation being performed, the HTTP method,
 *                           the URL, etc.
 * @param theUserSession     Contains details about the logged in user and
 *                           their session.
 * @param theContextServices Contains various utility methods for accessing
 *                           relevant information about the request, as well
 *                           as providing a response.
 * @package theResource      The resource that will be accessed.
 * @param theClientSession   Contains details about the OIDC client and
 *                           their OAuth2 session.
 */
function consentWillSeeResource(theRequestDetails, theUserSession, theContextServices, theResource, theClientSession) {

// For Observation resources with a confidentiality code of "R" (restricted),
	// we will strip the value and notes from what the user will see
	if (theResource.meta.hasSecurity('https://www.hl7.org/fhir/v3/Confidentiality/cs.html', 'R')) {
		if (theResource.resourceType === 'Observation') {
			theResource.clear('value');
			theResource.clear('note');
		}
	}

// Let the user see the resource
	theContextServices.proceed();
}
```

Copy

# Example: Scope-Based Consent Script

Another approach to applying consent rules involves using rules based on OpenID Connect Scopes. In this example, a custom scope is defined in the OIDC Client Definition. Unless the application explicitly requests this scope, and the user has approved it, the application will not be able to access SARS-COV-2 Serum/Plasma test results.

The custom scope is named `observation_view_covid19`. See [Custom Scopes Example](/content/docs/smart/smart_on_fhir_approval_page.html#custom-scope-example-covid/index.html) for more information on how to define this scope and request user approval for it.

// In this example, we are applying consent rules only to Observation resources
   if (theResource.resourceType === 'Observation') {

let resourceSystem = theResource.code.coding[0].system;
      let resourceCode = theResource.code.coding[0].code;

// Any non-LOINC coded Observations will be allowed
      if (resourceSystem !== 'http://loinc.org') {
         theContextServices.authorized();
         return;
      }

// The LOINC code 94767-1 corresponds to a SARS-COV-2 Serum/Plasma test. Unless the session
      // has an appropriate scope approved, we'll filter this result.
      if (resourceCode === '94767-1') {
         let approvedScopes = theRequestDetails.approvedScopes;
         if (!approvedScopes.contains('observation_view_covid19')) {
            theContextServices.reject();
            return;
         }
      }

}

// Any other resources are authorized, meaning that the client will get
   // to see the resources, and consentWillSeeResource(...) is not called. This
   // is good for performance but means that no filtering can take place.
   theContextServices.authorized();

}
```

Copy

# Example: Using Consent Purpose and Actor

It is possible to define the actor and purpose for consent purposes, storing them in the User Session Details from the authorization callback Script. See [Authentication Callback Scripts](/content/docs/security/callback_scripts.html) for more information on how to define authentication callback scripts.

```javascript
function onAuthenticateSuccess(theOutcome, theOutcomeFactory, theContext) {

let username = theOutcome.username.toUpperCase();

// Set the consent actor to the logged-on user
    theOutcome.setConsentActor(username);

// Set the purpose of the consent to healthcare research
    theOutcome.setConsentPurpose('http://terminology.hl7.org/CodeSystem/v3-ActReason', 'HRESCH');

return theOutcome;
}
```

Copy

Having set the consent purpose and actor, the consent scripts can use them to make determinations on whether data can be seen.

if (theResource.resourceType === 'Patient') {
        var isResearchPurpose = (purpose != null && purpose.getCode() === 'HRESCH');
        if (actor === 'ORG1' && isResearchPurpose) {
            // Actor 'ORG1' with research purpose ('HRESCH') doesn't have access to Patient DOB
            theResource.clear('birthDate');
        }
    }
    theContextServices.proceed();
}
```

Copy

[Consent Service](/content/docs/security/consent_service.html)

Consent Service: JavaScript API

Security

[Authentication Protocols](/content/docs/security/authentication_protocols.html)
[Authorization and Consent](/content/docs/security/authorization_and_consent.html)
[Inbound Security Module](/content/docs/security/inbound_security_module.html)
[Local Inbound Security Module](/content/docs/security/local_inbound_security_module.html)
[LDAP Inbound Security Module](/content/docs/security/ldap_inbound_security_module.html)
[Scripted Inbound Security Module](/content/docs/security/script_inbound_security_module.html)
[SAML Inbound Security Module](/content/docs/security/saml_inbound_security_module.html)
[Trusted Client Mode](/content/docs/security/trusted_client_mode.html)
[Roles and Permissions](/content/docs/security/roles_and_permissions.html)
[Callback Scripts](/content/docs/security/callback_scripts.html)
[Anonymous Access](/content/docs/security/anonymous_access.html)
[Consent Service](/content/docs/security/consent_service.html)
[Consent Service: JavaScript API](/content/docs/security/consent_service_javascript.html)
[Consent Service: Java API](/content/docs/security/consent_service_java.html)
[Security Recipes](/content/docs/security/security_recipes.html)
[Two Factor Authentication](/content/docs/security/two_factor_auth.html)
[Password Hashing Algorithms](/content/docs/security/password_hashing_algorithms.html)
[JWT Signature Algorithms](/content/docs/security/jwt_signature_algorithms.html)
[Troubleshooting Security](/content/docs/security/troubleshooting_security.html)

[Consent Service: Java API](/content/docs/security/consent_service_java.html)
