# Accessing remote services

Most applications will have to communicate with another service other than a Deskpro instance. The SDK does not enforce a particular way of how to implement the communication, leaving this choice to the developer.

The SDK comes with a http client which aims to solve only advanced use cases for accessing remote services:

* making requests to a non-CORS enabled API. Here's what MDN web docs has to say about CORS: <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>

The browsers security model prevents a page from making requests to another page in a different domain. CORS is a mechanism that allows this which requires the page in the different domain to whitelist the domain of the page making the request. Not all API's are CORS enabled and to get around this issue a server-side proxy ships with Deskpro as part of the Apps SDK. This means you do not have to run your own server-side proxy implementation if you do not have a really compelling reason for it

* making secure requests

Many of the requests made by apps will involve some sort of authorization, like an OAuth token or API Key. These credentials should be stored securely, meaning your application will not have direct access to them. Instead, by using [request placeholders](/apps-developer-guide-old/sdk/accessing-remote-services.md#using-request-placeholders), the server-side proxy will inject those credentials into the outbound request.

Some type of secure requests will require a signature to be computed based on some secure storage data, such is the case for OAuth1 requests. Make sure to read the chapter [Signing Requests](/apps-developer-guide-old/sdk/accessing-remote-services.md#signing-requests) to learn more.

## Whitelisting remote services

If you use the server-side proxy, your application manifest must declare which external URLs can be accessed. This is a security measure to stop abusing this feature.

You specify which URL can be accessed by supplying a list of regex patterns in your application manifest:

```javascript
{
  "deskpro" : {
      "domainWhitelist": [
        "/^https?://([^.]+\\.)*myjetbrains.com/?.*$/",
        "/^https?://([^.]+\\.)*atlassian.net/?.*$/"
    ]
  }
}
```

The patterns above allow the server-side proxy to access any url on the `myjetbrains.com` and `atlassian.net` domains via `http` or `https`.

## Using request placeholders

Request placeholders is a technique that allows the server-side proxy to inject settings or other secure storage data into a request sent from an application.

The syntax for a placeholder is:

```
    {{name}}
```

where name is the name of the setting or a secure storage data. Placeholders can be used in the URL of the request or in a Header

For example, let's assume that your application is an integration between Deskpro and ServiceX and that an API Key is required to make authorized requests to ServiceX.

Your application manifest will probably contain these entries which secure the API Key:

```javascript
{
  "deskpro": {
    "settings" : [
      {
        "name": "apiKey",
        "defaultValue": "",
        "title": "Mailchimp API Key",
        "required": true,
        "type": "text"
      }
    ],
    "storage": [
      {
        "name": "apiKey",
        "isBackendOnly": true,
        "permRead": "EVERYBODY",
        "permWrite": "OWNER"
      }
    ]
  }
}
```

When the application is installed, the administrator will configure it and input an API key and then it will be stored under the `apiKey` storage key.

To make a request using the API key you would invoke the server-side proxy like this:

```javascript
  /**
   * @param {string} email the subscriber email
   * @returns {Promise.<DeskproAPIResponse, Error>}
   */
  getData()
  {
    // reference to the deskpro api client, @see https://deskpro.github.io/apps-sdk-core/reference/DeskproAPIClient.html
    const { restApi } = this.props.dpapp;

    return restApi.fetchCORS(
      `https://{serviceX-resource-url}>`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json' ,
          'Accept': 'application/json' ,
          'Authorization': 'api_key {{apiKey}}' 
        }
      })
    ;
  }
```

As you can see, invoking the server-side proxy is done through the [DeskproAPIClient.fetchCors](https://deskpro.github.io/apps-sdk-core/reference/DeskproAPIClient.html) method. Notice the `Authorization` header and how we are using the request placeholder syntax `{{apiKey}}` to securely inject the ServiceX API key which is stored server-side under the `apiKey` key.

## Signing requests

In some cases you will need to compute a signature based on secure settings or other secure data. Because your application does not have direct access to those values, you must delegate this task to the server-side proxy.

To instruct the proxy to sign your request you must add a `X-Proxy-SignWith` header to your request configuration. The value of this header tells the proxy how the request should be signed. The proxy will compute the signature, discard the `X-Proxy-SignWith` header such that it is not added to the final request and in most cases an `Authorization` header will be added in the final request.

Read the following chapters for an overview of the existing signature types.

### Basic Auth signature

This type of signature adds a `Authorization: Basic <VALUE>` header to the final request. The syntax for this header is:

```
  HEADER = X-Proxy-SignWith: auth_basic VALUE:VALUE
  VALUE = name | {{name}}
```

which allows injection of secure data via the request placeholder syntax

To enable this, let's elaborate on the previous example:

```javascript
  /**
   * @param {string} email the subscriber email
   * @returns {Promise.<DeskproAPIResponse, Error>}
   */
  getData()
  {
    // reference to the deskpro api client, @see https://deskpro.github.io/apps-sdk-core/reference/DeskproAPIClient.html
    const { restApi } = this.props.dpapp;

    return restApi.fetchCORS(
      `https://{serviceX-resource-url}>`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json' ,
          'Accept': 'application/json' ,
          'X-Proxy-SignWith': 'auth_basic anystring:{{apiKey}}' 
        }
      })
    ;
  }
```

As you can see the signature is enabled by adding this entry `'X-Proxy-SignWith': 'auth_basic anystring:{{apiKey}}'` to the list of headers.

### Oauth1 Signature

This type of signature adds an OAuth1 authorization header to the final request:

```
Authorization: OAuth
               oauth_consumer_key=<KEY>
               oauth_token=<TOKEN>
               oauth_signature_method="HMAC-SHA1"
               oauth_timestamp=<TIMESTAMP>,
               oauth_nonce="nonce",
               oauth_signature=<VALUE>
```

The syntax for this header is:

```
  HEADER = X-Proxy-SignWith: oauth1 CONNECTION_KEY TOKENS_KEY
  CONNECTION_KEY = name
  TOKENS_KEY = name
```

For example, if your application would use OAuth1 to connect to JIRA your manifest would contain among others the following keys:

```javascript
{
  "deskpro": {
    "storage": [
     {
        "name": "oauth:jira",
        "isBackendOnly": true,
        "permRead": "EVERYBODY",
        "permWrite": "OWNER"
      },
      {
        "name": "oauth:jira:tokens",
        "isBackendOnly": true,
        "permRead": "OWNER",
        "permWrite": "OWNER"
      }
    ]
  }
}
```

You would recall that if your application requires OAuth you must declare a storage item name `oauth:<PROVIDER NAME>` where the information used to create a connection to `PROVIDER NAME` is stored. The other key,`oauth:jira:tokens`, is only used to store individual tokens and it can have any name you deem fit, but we recommend the `oauth:<PROVIDER NAME>:tokens` convention. The most important thing about the tokens key is that it must be readable only be its owner.

Building on the previous example, this is how we would make an OAuth1 request:

To enable this, let's elaborate on the previous example:

```javascript
  /**
   * @param {string} email the subscriber email
   * @returns {Promise.<DeskproAPIResponse, Error>}
   */
  getData()
  {
    // reference to the deskpro api client, @see https://deskpro.github.io/apps-sdk-core/reference/DeskproAPIClient.html
    const { restApi } = this.props.dpapp;

    return restApi.fetchCORS(
      `https://{serviceX-resource-url}>`,
      {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json' ,
          'Accept': 'application/json' ,
          'X-Proxy-SignWith': 'oauth1 oauth:jira oauth:jira:tokens' 
        }
      })
    ;
  }
```

As you can see the signature is enabled by adding this entry `'X-Proxy-SignWith': 'oauth1 oauth:jira oauth:jira:tokens'` to the list of headers.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://deskpro.gitbook.io/apps-developer-guide-old/sdk/accessing-remote-services.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
