# Integrate CARTO in your existing application

When you build a solution from scratch using CARTO you can choose between the three different [authentication strategies](https://docs.carto.com/carto-for-developers/key-concepts/authentication-methods) to secure your application. However, in many other cases the starting point is an existing application with its own login system where you want to add a geospatial component, such as a map visualization.

In this guide you will learn how to integrate CARTO with an existing application that has its own login system, implementing the machine-to-machine authentication in order to provide fine-grained data access to the end users.

## Overview

In this guide, the ACME company has decided to add maps to their existing application and CARTO will be the platform used for it. They have two important requirements:

* ACME wants to keep its own login system.
* The maps will show different data based on the user, in this case, based on the user's group.

With this in mind, we are going to develop a backend endpoint in order to generate a CARTO [API Access Token](https://docs.carto.com/carto-for-developers/key-concepts/authentication-methods/api-access-tokens) with only access to the data the user has permission for in our application, the frontend application will use that token to interact with the rest of the CARTO APIs.

{% hint style="info" %}
The backend is responsible for generating an API Access Token without exceding the actual permissions of the users.
{% endhint %}

<figure><img src="https://3029946802-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FybPdpmLltPkzGFvz7m8A%2Fuploads%2F2jkWC4j0GHylZ6cSB4Gf%2FM2M%20App%20Diagram.png?alt=media&#x26;token=4832a621-2561-4189-adfc-3ac2bccda4a6" alt=""><figcaption><p>Architecture diagram of a private application with custom auth mechanism</p></figcaption></figure>

The data used for this guide will be the table **retail\_stores** contains all the retails in the US, It's available at `carto-demo-data.demo_tables.retail_stores`.

<figure><img src="https://3029946802-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FybPdpmLltPkzGFvz7m8A%2Fuploads%2Fgit-blob-7544fbabfcce22af0ccedd5ef7b6db76de33d301%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

In our demo application we will have two users:

```json
{
  "username": "user.boston@acme.com",
  "password": "boston",
  "group": "BOSTON"
},
{
  "username": "user.ny@acme.com",
  "password": "ny",
  "group": "NEW YORK"
} 
```

The user in the group of `BOSTON` will only see the stores in the city of Boston, the user in group `NEW YORK` will be limited to New York.

## Scaffolding your backend

Since this guide needs a backend and a frontend application, the first thing we have to do is create the structure to store the code for these components. Let's start with the backend side and install the needed dependencies to work with [Express](https://expressjs.com/):

```bash
mkdir backend
cd backend
npm init --yes
npm install express dotenv cors jsonwebtoken
```

We are going to use [Typescript](https://www.typescriptlang.org/) on both the backend and frontend sides, so we need to install the required dependencies:

```bash
npm i -D typescript @types/express @types/node @types/cors @types/jsonwebtoken
npx tsc --init
```

Now, the next step is to uncomment the following line in the file (it specifies an output folder for all emitted files):

```json
"outDir": "./dist",
```

As an optional step, you would like to add to have extra help to develop by restarting your application automatically when there are changes in your code. To do that, install the following dependencies:

```bash
npm install -D concurrently nodemon
```

And add the following content to the file <mark style="color:blue;">package.json:</mark>

```json
{
    "scripts": {
        "build": "npx tsc",
        "start": "node dist/index.js",
        "dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/index.js\""
    }
}
```

Now, just typing `npm run dev` the server will run up and you can see the changes in the code immediately.

## Creating a M2M OAuth Client in CARTO

In order to use the CARTO APIs you need to authenticate your requests. For a backend-side application, the recommended approach is to do so by creating a **Machine to Machine OAuth Client** ([M2M OAuth Client](https://docs.carto.com/carto-user-manual/developers/managing-credentials/m2m-oauth-clients)). To create this OAuth Client, you need to go to [CARTO Workspace](https://app.carto.com) -> Developers -> Credentials -> Create New -> M2M OAuth Client

<figure><img src="https://3029946802-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FybPdpmLltPkzGFvz7m8A%2Fuploads%2Fgit-blob-dd8f21da0777c3d13ad53278324c09141e0f0832%2Fimage.png?alt=media" alt=""><figcaption><p>How to create a Machine to Machine application</p></figcaption></figure>

{% hint style="info" %}
For development purposes, you can set the URL for localhost in the <mark style="color:blue;">App URL</mark> and <mark style="color:blue;">Application Login URI.</mark> Just set the URL `https://127.0.0.1:8000` in both fields.
{% endhint %}

Once the application is created, you will have to get the <mark style="color:blue;">Client ID</mark> and the <mark style="color:blue;">Client Secret</mark>

## Coding the endpoint

Now, we have to create a couple of endpoints: a basic login endpoint to authenticate the user and an endpoint to generate the CARTO token.

For **the login endpoint**, the responsibilities will be:

* Check the login and password.
* Get the group of the user and create a JWT token.

{% hint style="info" %}
In a real production environment, you should already have a login endpoint.
{% endhint %}

While the endpoint to **get the CARTO token** will do:

* Validate the JWT in the Authentication header.
* Extract the group and create the token via [CARTO API](https://api-docs.carto.com/#6977be37-183c-40a5-8442-386d1dcb47d9).

Replace the file <mark style="color:orange;">index.ts</mark> with the following content:

<pre class="language-typescript"><code class="lang-typescript"><strong>import express, { Express, Request, Response } from 'express'
</strong>import dotenv from 'dotenv'
import cors from 'cors'
import jwt from 'jsonwebtoken'
import fetch from 'node-fetch'

dotenv.config()

const app: Express = express()
const port = process.env.PORT || 8000
const jwtSecret = process.env.JWT_SECRET as string

app.use(express.json())
app.use(cors())

interface LoginRequestBody {
  username: string
  password: string
}

interface LoginResponseBody {
  token: string
}

interface AccessApiTokenResponse {
  token: string
  error: string,
  description: string
}

// hard-coded users. Don't use this in production! This should come from an IdP or a database.
const users = [{
    username: 'user.boston@acme.com',
    password: 'boston',
    group: 'BOSTON'
  },
  {
    username: 'user.ny@acme.com',
    password: 'ny',
    group: 'NEW YORK'
  } 
]

// This endpoint simulates a login system. It checks the credentials and returns a JWT token
// with the user group as a claim.
app.post('/login', async (req: Request, res: Response) => {
  const { username, password } = req.body as LoginRequestBody
  const user = users.find((u) => u.username === username)

  if (!user || user.password !== password) {
    res.status(401).send({ 'error': 'Invalid credentials' })
    return
  }

  const loginToken = jwt.sign({ group: user.group }, jwtSecret, { expiresIn: '1h' })
  const loginResponse = { token: loginToken } as LoginResponseBody

  res.send(loginResponse)
})

// This endpoint returns a CARTO API Access Token for the user group. The token will be used
// to query the tables for the city of the user.
app.post('/carto-token', async (req: Request, res: Response) => {
  try {

    // Get the token from the Authorization header with Bearer prefix
    const authHeader = req.headers.authorization as string
    const loginToken = authHeader.replace('Bearer ', '')

    // Decode the token to get the group
    const tokenGroup = jwt.verify(loginToken, jwtSecret) as { group: string }
    const token = await getAPIAccessTokenForGroup(tokenGroup.group)
    const response = { token, city: tokenGroup.group } as LoginResponseBody
    res.send(response)
  } catch (error) {
    console.log(error)
    res.status(401).send({ 'error': 'Invalid token' })
  }
})

app.listen(port, () => {
  console.log(`⚡️[server]: Server is running at http://localhost:${port}`)
})
</code></pre>

Create a <mark style="color:blue;">.env</mark> file located in the root of the backend with the following content:

```bash
PORT=8000
# The JWT Secret to sign the JWT token
JWT_SECRET=PUT_YOUR_SECRET_HERE
# API Base URL (copy this from CARTO Workspace -> Developers)
CARTO_BASE_URL=PUT_YOUR_API_BASE_URL_HERE
# ClientID and Secret of your Machine to Machine Application
CARTO_CLIENT_ID=PUT_YOUR_CLIENT_ID_HERE
CARTO_CLIENT_SECRET=PUT_YOUR_CLIENT_ID_HERE
```

The most important function involved in the endpoint is the one called `getAPIAccessTokenForGroup` that owns the logic to interact with CARTO in order to get a valid token for the frontend side. Let's see what its implementation looks like:

{% code overflow="wrap" lineNumbers="true" %}

```typescript
async function getAPIAccessTokenForGroup(group: string): Promise<string> {
  const cartoBaseUrl = process.env.CARTO_BASE_URL
  const clientId = process.env.CARTO_CLIENT_ID
  const clientSecret = process.env.CARTO_CLIENT_SECRET

  // Step 1: Get an OAuth Access Token using the clientId and clientSecret of a Machine to Machine Application.
  const accessTokenResponse = await fetch('https://auth.carto.com/oauth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: `grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}&audience=carto-cloud-native-api`
  })

  const { access_token, error } = await accessTokenResponse.json() as { access_token: string, error: string }
  if (error) {
    console.log(error)
    throw new Error(error)
  }

  // Step 2: Generate an API Access Token for the logged user (with limited grants).
  const grants = [
    {
      'connection_name': 'carto_dw',
      'source': `SELECT * FROM \`carto-demo-data\`.demo_tables.retail_stores WHERE city = @groupcity`
    }
  ]

  // Call the tokens API using the OAuth Access Token from step 1.
  const accessApiTokenResponse = await fetch(`${cartoBaseUrl}/v3/tokens`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${access_token}`
    },
    body: JSON.stringify({
      'grants': grants,
      // Put here the referers of your frontend application in production
      'referers': [],
      'allowed_apis': [
        // 'sql', // Uncomment this line to allow SQL API calls
        'maps'
      ]
    })
  })

  const { token, error: tokenError, description: tokenDescription } = await accessApiTokenResponse.json() as AccessApiTokenResponse
  if (tokenError) {
    console.log(error)
    throw new Error(tokenError)
  }

  return token
}
```

{% endcode %}

{% hint style="info" %}
Tokens are limited based on the quota of your plan. In a production environment, you should implement a mechanism to create only the tokens that you need:

* **API Access Tokens:** avoid creating two tokens with the same grants for the same user.
* **OAuth Access Tokens:** OAuth Access Tokens are valid for 24 hours, so you should avoid creating more than one token per day per application/API instance.
  {% endhint %}

The function will take one parameter indicating the group in order to create the right token. The first thing to do is to get the environment variables to interact with the CARTO API. The next step is to obtain an[ OAuth Access Token](https://docs.carto.com/carto-for-developers/key-concepts/authentication-methods/oauth-access-tokens) to deal with the rest of the APIs. To get this first token you can see in the line 7 to 13 how to use the `Client ID` and the `Client Secret` to make the request and get this token. Once, you have a valid OAuth Access Token, the last step is to create an [API Access Token](https://docs.carto.com/carto-user-manual/developers/managing-credentials/api-access-tokens) for the specific grants. In this case, the grants include the permission to execute a specific SQL query to get all the retail for a specific city.

That means, that once the token is created, the client using this token only will have permission to execute the defined query and get only the data declared in the grants.

Finally, once the code for the backend is ready you can run the server just by typing in your terminal:

```bash
npm run dev
```

{% hint style="info" %}
If your application requires dynamic queries, you can use [query parameters](https://api-docs.carto.com/#3f1407e6-8c40-43c3-a8f8-21ae7d3618b6) in [SQL](https://docs.carto.com/key-concepts/apis#sql) and [Maps](https://docs.carto.com/key-concepts/apis#maps) API.

`SELECT * FROM carto-demo-data.demo_tables.retail_stores`

`WHERE city = 'BOSTON' AND storetype = @storetype`
{% endhint %}

## Frontend side integration

At this point, our backend is ready to generate tokens for our users. In the following code you can see an example of a frontend application that does:

* Login.
* Call the previous endpoint to get an [API Access Token](https://docs.carto.com/carto-for-developers/key-concepts/authentication-methods/api-access-tokens) with the permissions limited to the user.
* Use the token to call CARTO APIs.

To run this, first, you need to clone the project:

```bash
git clone https://github.com/CartoDB/carto-for-developers-guides.git
cd carto-for-developers-guides/integrate-existing-app/frontend
```

Edit the <mark style="color:orange;">.env</mark> file at set the VITE\_API\_BASE\_URL:

<pre><code># API Base URL (copy this from CARTO Workspace -> Developers)
<strong>VITE_CARTO_API_BASE_URL=https://gcp-us-east1.api.carto.com
</strong># Custom company backend
VITE_COMPANY_API_BASE_URL=http://localhost:8000
</code></pre>

{% hint style="info" %}
If you have a different region, you need to modify VITE\_CARTO\_API\_BASE\_URL.
{% endhint %}

Run:

```bash
npm run dev
```

<figure><img src="https://3029946802-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FybPdpmLltPkzGFvz7m8A%2Fuploads%2Fgit-blob-f45c29d14be73b9af79757ba2b60cef91d40e4f8%2Fimage.png?alt=media" alt=""><figcaption><p>Sample web application integrating a custom backend with CARTO</p></figcaption></figure>

## What's next?

All the code for this guide is available on [GitHub](https://github.com/CartoDB/carto-for-developers-guides/tree/master/guides/integrate-existing-app).

```bash
git clone https://github.com/CartoDB/carto-for-developers-guides.git
cd carto-for-developers-guides/integrate-existing-app
```

We recommend you to visit [https://github.com/CartoDB/gitbook-documentation/blob/master/carto-for-developers/key-concepts/carto-for-deck.gl](https://github.com/CartoDB/gitbook-documentation/blob/master/carto-for-developers/key-concepts/carto-for-deck.gl "mention") to learn more about the different visualizations you can create using deck.gl. There are many examples in our [gallery](https://docs.carto.com/carto-for-developers/examples) that might be useful to improve your application!
