LogoLogo
HomeAcademyLoginTry for free
  • Welcome
  • What's new
    • Q2 2025
    • Q1 2025
    • Q4 2024
    • Q3 2024
    • Q2 2024
    • Q1 2024
    • Q4 2023
    • Q3 2023
    • Q2 2023
    • Q1 2023
    • Q4 2022
    • Q3 2022
  • FAQs
    • Accounts
    • Migration to the new platform
    • User & organization setup
    • General
    • Builder
    • Workflows
    • Data Observatory
    • Analytics Toolbox
    • Development Tools
    • Deployment Options
    • CARTO Basemaps
    • CARTO for Education
    • Support Packages
    • Security and Compliance
  • Getting started
    • What is CARTO?
    • Quickstart guides
      • Connecting to your data
      • Creating your first map
      • Creating your first workflow
      • Developing your first application
    • CARTO Academy
  • CARTO User Manual
    • Overview
      • Creating your CARTO organization
      • CARTO Cloud Regions
      • CARTO Workspace overview
    • Maps
      • Data sources
        • Simple features
        • Spatial Indexes
        • Pre-generated tilesets
        • Rasters
        • Defining source spatial data
        • Managing data freshness
        • Changing data source location
      • Layers
        • Point
          • Grid point aggregation
          • H3 point aggregation
          • Heatmap point aggregation
          • Cluster point aggregation
        • Polygon
        • Line
        • Grid
        • H3
        • Raster
        • Zoom to layer
      • Widgets
        • Formula widget
        • Category widget
        • Pie widget
        • Histogram widget
        • Range widget
        • Time Series widget
        • Table widget
      • SQL Parameters
        • Date parameter
        • Text parameter
        • Numeric parameter
        • Publishing SQL parameters
      • Interactions
      • Legend
      • Basemaps
        • Basemap selector
      • AI Agents
      • SQL analyses
      • Map view modes
      • Map description
      • Feature selection tool
      • Search locations
      • Measure distances
      • Exporting data
      • Download PDF reports
      • Managing maps
      • Publishing and sharing maps
        • Map settings for viewers
        • Map preview for editors
        • Collaborative maps
        • Embedding maps
        • URL parameters
      • Performance considerations
    • Workflows
      • Workflow canvas
      • Results panel
      • Components
        • Aggregation
        • Custom
        • Data Enrichment
        • Data Preparation
        • Generative AI
        • Input / Output
        • Joins
        • Parsers
        • Raster Operations
        • Spatial Accessors
        • Spatial Analysis
        • Spatial Constructors
        • Spatial Indexes
        • Spatial Operations
        • Statistics
        • Tileset Creation
        • BigQuery ML
        • Snowflake ML
        • Google Earth Engine
        • Google Environment APIs
        • Telco Signal Propagation Models
      • Data Sources
      • Scheduling workflows
      • Sharing workflows
      • Using variables in workflows
      • Executing workflows via API
      • Temporary data in Workflows
      • Extension Packages
      • Managing workflows
      • Workflows best practices
    • Data Explorer
      • Creating a map from your data
      • Importing data
        • Importing rasters
      • Geocoding data
      • Optimizing your data
    • Data Observatory
      • Terminology
      • Browsing the Spatial Data Catalog
      • Subscribing to public and premium datasets
      • Accessing free data samples
      • Managing your subscriptions
      • Accessing your subscriptions from your data warehouse
        • Access data in BigQuery
        • Access data in Snowflake
        • Access data in Databricks
        • Access data in Redshift
        • Access data in PostgreSQL
    • Connections
      • Google BigQuery
      • Snowflake
      • Databricks
      • Amazon Redshift
      • PostgreSQL
      • CARTO Data Warehouse
      • Sharing connections
      • Deleting a connection
      • Required permissions
      • IP whitelisting
      • Customer data responsibilities
    • Applications
    • Settings
      • Understanding your organization quotas
      • Activity Data
        • Activity Data Reference
        • Activity Data Examples
        • Activity Data Changelog
      • Users and Groups
        • Inviting users to your organization
        • Managing user roles
        • Deleting users
        • SSO
        • Groups
        • Mapping groups to user roles
      • CARTO Support Access
      • Customizations
        • Customizing appearance and branding
        • Configuring custom color palettes
        • Configuring your organization basemaps
        • Enabling AI Agents
      • Advanced Settings
        • Managing applications
        • Configuring S3 Bucket for Redshift Imports
        • Configuring OAuth connections to Snowflake
        • Configuring OAuth U2M connections to Databricks
        • Configuring S3 Bucket integration for RDS for PostgreSQL Exports in Builder
        • Configuring Workload Identity Federation for BigQuery
      • Data Observatory
      • Deleting your organization
    • Developers
      • Managing Credentials
        • API Base URL
        • API Access Tokens
        • SPA OAuth Clients
        • M2M OAuth Clients
      • Named Sources
  • Data and Analysis
    • Analytics Toolbox Overview
    • Analytics Toolbox for BigQuery
      • Getting access
        • Projects maintained by CARTO in different BigQuery regions
        • Manual installation in your own project
        • Installation in a Google Cloud VPC
        • Core module
      • Key concepts
        • Tilesets
        • Spatial indexes
      • SQL Reference
        • accessors
        • clustering
        • constructors
        • cpg
        • data
        • http_request
        • import
        • geohash
        • h3
        • lds
        • measurements
        • placekey
        • processing
        • quadbin
        • random
        • raster
        • retail
        • routing
        • s2
        • statistics
        • telco
        • tiler
        • transformations
      • Guides
        • Running queries from Builder
        • Working with Raster data
      • Release notes
      • About Analytics Toolbox regions
    • Analytics Toolbox for Snowflake
      • Getting access
        • Native App from Snowflake's Marketplace
        • Manual installation
      • Key concepts
        • Spatial indexes
        • Tilesets
      • SQL Reference
        • accessors
        • clustering
        • constructors
        • data
        • http_request
        • import
        • h3
        • lds
        • measurements
        • placekey
        • processing
        • quadbin
        • random
        • raster
        • retail
        • s2
        • statistics
        • tiler
        • transformations
      • Guides
        • Running queries from Builder
        • Working with Raster data
      • Release Notes
    • Analytics Toolbox for Databricks
      • Getting access
        • Personal (former Single User) cluster
        • Standard (former Shared) cluster
      • Reference
        • lds
        • tiler
      • Guides
      • Release Notes
    • Analytics Toolbox for Redshift
      • Getting access
        • Manual installation in your database
        • Installation in an Amazon Web Services VPC
        • Core version
      • Key concepts
        • Tilesets
        • Spatial indexes
      • SQL Reference
        • clustering
        • constructors
        • data
        • http_request
        • import
        • lds
        • placekey
        • processing
        • quadbin
        • random
        • s2
        • statistics
        • tiler
        • transformations
      • Guides
        • Running queries from Builder
      • Release Notes
    • Analytics Toolbox for PostgreSQL
      • Getting access
        • Manual installation
        • Core version
      • Key concepts
        • Tilesets
        • Spatial Indexes
      • SQL Reference
        • h3
        • quadbin
        • tiler
      • Guides
        • Creating spatial index tilesets
        • Running queries from Builder
      • Release Notes
    • CARTO + Python
      • Installation
      • Authentication Methods
      • Visualizing Data
      • Working with Data
        • How to work with your data in the CARTO Data Warehouse
        • How to access your Data Observatory subscriptions
        • How to access CARTO's Analytics Toolbox for BigQuery and create visualizations via Python notebooks
        • How to access CARTO’s Analytics Toolbox for Snowflake and create visualizations via Python notebooks
        • How to visualize data from Databricks
      • Reference
    • CARTO QGIS Plugin
  • CARTO for Developers
    • Overview
    • Key concepts
      • Architecture
      • Libraries and APIs
      • Authentication methods
        • API Access Tokens
        • OAuth Access Tokens
        • OAuth Clients
      • Connections
      • Data sources
      • Visualization with deck.gl
        • Basemaps
          • CARTO Basemap
          • Google Maps
            • Examples
              • Gallery
              • Getting Started
              • Basic Examples
                • Hello World
                • BigQuery Tileset Layer
                • Data Observatory Tileset Layer
              • Advanced Examples
                • Arc Layer
                • Extrusion
                • Trips Layer
            • What's New
          • Amazon Location
            • Examples
              • Hello World
              • CartoLayer
            • What's New
        • Rapid Map Prototyping
      • Charts and widgets
      • Filtering and interactivity
      • Summary
    • Quickstart
      • Make your first API call
      • Visualize your first dataset
      • Create your first widget
    • Guides
      • Build a public application
      • Build a private application
      • Build a private application using SSO
      • Visualize massive datasets
      • Integrate CARTO in your existing application
      • Use Boundaries in your application
      • Avoid exposing SQL queries with Named Sources
      • Managing cache in your CARTO applications
    • Reference
      • Deck (@deck.gl reference)
      • Data Sources
        • vectorTableSource
        • vectorQuerySource
        • vectorTilesetSource
        • h3TableSource
        • h3QuerySource
        • h3TilesetSource
        • quadbinTableSource
        • quadbinQuerySource
        • quadbinTilesetSource
        • rasterSource
        • boundaryTableSource
        • boundaryQuerySource
      • Layers (@deck.gl/carto)
      • Widgets
        • Data Sources
        • Server-side vs. client-side
        • Models
          • getFormula
          • getCategories
          • getHistogram
          • getRange
          • getScatter
          • getTimeSeries
          • getTable
      • Filters
        • Column filters
        • Spatial filters
      • CARTO APIs Reference
    • Release Notes
    • Examples
    • CARTO for React
      • Guides
        • Getting Started
        • Views
        • Data Sources
        • Layers
        • Widgets
        • Authentication and Authorization
        • Basemaps
        • Look and Feel
        • Query Parameters
        • Code Generator
        • Sample Applications
        • Deployment
        • Upgrade Guide
      • Examples
      • Library Reference
        • Introduction
        • API
        • Auth
        • Basemaps
        • Core
        • Redux
        • UI
        • Widgets
      • Release Notes
  • CARTO Self-Hosted
    • Overview
    • Key concepts
      • Architecture
      • Deployment requirements
    • Quickstarts
      • Single VM deployment (Kots)
      • Orchestrated container deployment (Kots)
      • Advanced Orchestrated container deployment (Helm)
    • Guides
      • Guides (Kots)
        • Configure your own buckets
        • Configure an external in-memory cache
        • Enable Google Basemaps
        • Enable the CARTO Data Warehouse
        • Configure an external proxy
        • Enable BigQuery OAuth connections
        • Configure Single Sign-On (SSO)
        • Use Workload Identity in GCP
        • High availability configuration for CARTO Self-hosted
        • Configure your custom service account
      • Guides (Helm)
        • Configure your own buckets (Helm)
        • Configure an external in-memory cache (Helm)
        • Enable Google Basemaps (Helm)
        • Enable the CARTO Data Warehouse (Helm)
        • Configure an external proxy (Helm)
        • Enable BigQuery OAuth connections (Helm)
        • Configure Single Sign-On (SSO) (Helm)
        • Use Workload Identity in GCP (Helm)
        • Use EKS Pod Identity in AWS (Helm)
        • Enable Redshift imports (Helm)
        • Migrating CARTO Self-hosted installation to an external database (Helm)
        • Advanced customizations (Helm)
        • Configure your custom service account (Helm)
    • Maintenance
      • Maintenance (Kots)
        • Updates
        • Backups
        • Uninstall
        • Rotating keys
        • Monitoring
        • Change the Admin Console password
      • Maintenance (Helm)
        • Monitoring (Helm)
        • Rotating keys (Helm)
        • Uninstall (Helm)
        • Backups (Helm)
        • Updates (Helm)
    • Support
      • Get debug information for Support (Kots)
      • Get debug information for Support (Helm)
    • CARTO Self-hosted Legacy
      • Key concepts
        • Architecture
        • Deployment requirements
      • Quickstarts
        • Single VM deployment (docker-compose)
      • Guides
        • Configure your own buckets
        • Configure an external in-memory cache
        • Enable Google Basemaps
        • Enable the CARTO Data Warehouse
        • Configure an external proxy
        • Enable BigQuery OAuth connections
        • Configure Single Sign-On (SSO)
        • Enable Redshift imports
        • Configure your custom service account
        • Advanced customizations
        • Migrating CARTO Self-Hosted installation to an external database
      • Maintenance
        • Updates
        • Backups
        • Uninstall
        • Rotating keys
        • Monitoring
      • Support
    • Release Notes
  • CARTO Native App for Snowflake Containers
    • Deploying CARTO using Snowflake Container Services
  • Get Help
    • Legal & Compliance
    • Previous libraries and components
    • Migrating your content to the new CARTO platform
Powered by GitBook
On this page
  • Scaffolding your application
  • Create a SPA OAuth Client
  • Managing the user login using Auth0 SDK
  • Visualizing a dataset
  • Executing a query against CARTO APIs
  • What's next?

Was this helpful?

Export as PDF
  1. CARTO for Developers
  2. Guides

Build a private application

How to build a basic private application with CARTO login

PreviousBuild a public applicationNextBuild a private application using SSO

Last updated 1 year ago

Was this helpful?

Here you will learn how to create an application that requires a login to access. This application will be only accessible to users inside your CARTO organization (regardless of their role), so you will need a CARTO user to access it.

If you're building an application for an Enterprise organization that requires an integration with your own login system, you'll need to first connect and enable the feature in CARTO. We'll cover that in the next guide: .

The CARTO login uses the popular Authorization Framework protocol, so in this guide you will find an easy process to implement it, including login and logout methods.

After completing this guide you will be familiar with the following concepts:

  • Scaffolding your application.

  • Creating a Single Page Application OAuth Client (SPA OAuth Client).

  • Managing the user login using Auth0 SDK.

  • Visualizing a dataset.

  • Executing a query against CARTO APIs.

Scaffolding your application

To make this guide faster, we're going to start using the basic CARTO template in Vite that already includes a Basemap and deck.gl.

git clone https://github.com/CartoDB/carto-for-developers-guides.git
cp -r carto-for-developers-guides/template private-app
cd private-app
npm install
npm run dev

Create a SPA OAuth Client

Then, go to the .env file, and uncomment VITE_CLIENT_ID with the value of the app that was just created.

Managing the user login using Auth0 SDK

We're going to implement here two things:

  • Authenticate a user following the standard OAuth 2.0 workflow.

  1. Install the Auth0 SDK:

npm install @auth0/auth0-spa-js
  1. Create a file src/auth.ts:

import { Auth0Client, createAuth0Client } from '@auth0/auth0-spa-js';

let auth0Client: Auth0Client

export async function initAuth() {
  let accessToken: string | undefined;

  const clientId = import.meta.env.VITE_CLIENT_ID;
  auth0Client = await createAuth0Client({
    domain: 'auth.carto.com',
    clientId,
    authorizationParams: {
      redirect_uri: window.location.origin,
      audience: 'carto-cloud-native-api'
    }
  })

  if (location.search.includes('state=') && 
      (location.search.includes('code=') || 
      location.search.includes('error='))) {
    await auth0Client.handleRedirectCallback();
    window.history.replaceState({}, document.title, '/');
  }

  const isAuthenticated = await auth0Client.isAuthenticated();
  const appEl = document.getElementById('app');

  if (isAuthenticated) {
    appEl?.classList.add('isAuthenticated');
    
    const userProfile = await auth0Client.getUser();
    accessToken = await auth0Client.getTokenSilently();

    if (userProfile) {
      const profileEl = document.getElementById('profile')!;
      profileEl.innerHTML = `
            <p>${userProfile.name}</p>
            <img width="50px" height="50px" src='${userProfile.picture}' />
          `;
    }
    
  } else {
    appEl?.classList.remove('isAuthenticated');
  }
  
  // Logout
  const logoutButton = document.getElementById('logout');
  logoutButton?.addEventListener('click', (e) => {
    e.preventDefault();
    auth0Client.logout();
  });

  // Login
  const loginButton = document.getElementById('login');
  loginButton?.addEventListener('click', (e) => {
    e.preventDefault();
    auth0Client.loginWithRedirect();
  });
  
  return accessToken
}
  1. Replace src/main.ts with:

import './style.css'
import { initAuth } from './auth'
import { createMap } from './map'

document.querySelector<HTMLDivElement>('#app')!.innerHTML = `
  <button id="login">Login</button>
  <div id="login-content">
    <header>
      <button id="logout">Logout</button>
      <div id="profile"></div>
    </header>
    <div id="map"></div>
    <canvas id="deck-canvas"></canvas>
  </div>
`

initAuth().then((accessToken) => {
  if (accessToken) {
    createMap()
  }
})
  1. Add this at the end of src/style.css:

header {
  z-index: 1;
  position: absolute;
  padding: 10px;
}

#login-content {
  display: none;
}

.isAuthenticated #login-content {
  display: block;
}
.isAuthenticated #login {
  display: none;
}

Your application is now ready to authenticate users by sending them to the CARTO login, which will require the user to enter their own credentials, before successfully returning to the application in a classic OAuth 2.0 workflow that returns an OAuth Access Token.

Visualizing a dataset

Once the user is logged in an OAuth Access Token will be available, and we just need to tell deck.gl to use this token.

Let's modify src/main.ts:

initAuth().then((accessToken) => {
  if (accessToken) {
    const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
    createMap({apiBaseUrl, accessToken});
  }
})

And prepare src/map.ts to receive the new parameters, including imports:

import { BASEMAP, vectorTableSource, VectorTileLayer } from '@deck.gl/carto';

interface createMapProps {
  apiBaseUrl: string,
  accessToken: string
}
export function createMap({apiBaseUrl, accessToken}:createMapProps) {
// ...

Then add the following source and layer to the Deck instance at src/map.ts:

const connectionName = 'carto_dw';
const cartoConfig = {apiBaseUrl, accessToken, connectionName};

const demoTableSource = vectorTableSource({
  ...cartoConfig,
  tableName: 'carto-demo-data.demo_tables.populated_places'
});

const deck = new Deck({
  canvas: 'deck-canvas',
  initialViewState: INITIAL_VIEW_STATE,
  controller: true,
  layers: [
    new VectorTileLayer({
      id: 'places',
      data: demoTableSource,
      pointRadiusMinPixels: 3,
      getFillColor: [200, 0, 80],
    })
  ]
})

Remember that OAuth Access Tokens impersonate the user, so it will inherit all the permissions of the user.

Executing a query against CARTO APIs

Create a file src/api.ts:

interface ExecuteQueryProps {
  apiBaseUrl: string
  connection: string
  query: string
  accessToken: string
}
async function executeQuery ({apiBaseUrl, connection, query, accessToken}: ExecuteQueryProps) {
  const url = `${apiBaseUrl}/v3/sql/${connection}/query?q=${encodeURI(query)}`
  const options = {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${accessToken}`
    }
  };
  const response = await fetch(url, options);
  return await response.json();
}

interface GetAirportsProps {
  apiBaseUrl: string,
  accessToken: string
}
export function getAirports ({apiBaseUrl, accessToken}: GetAirportsProps) {
  const query = `select * from carto-demo-data.demo_tables.world_airports`
  const connection = 'carto_dw'
  return executeQuery({apiBaseUrl, connection, query, accessToken})
}

Modify src/main.ts to call the getAirports function:

initAuth().then((accessToken) => {
  if (accessToken) {
    const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
    setDefaultCredentials({ apiBaseUrl, accessToken})
    createMap()
    getAirports({apiBaseUrl, accessToken}).then((airports) => {
      console.log(airports)
    })
  }
})

Congratulations! You now have successfully built a private application that will require the user to log in. And after a successful login, you're able to show the user a map layer, and you're able to query an airports dataset right from your application.

What's next?

git clone https://github.com/CartoDB/carto-for-developers-guides.git
cd carto-for-developers-guides/private-app

During this guide, we're using the . The process explained here is also compatible with other Warehouses like BigQuery, Snowflake, Redshift, or Postgres. Instead of using connection=carto_dw, you need to use connection=<your_connection>.

As explained , we recommend to manage the tooling of your app.

After that, you should have a project up and running at

As explained in we need to create a SPA OAuth Client to obtain a client_id + client_secret that we will use to then obtain an OAuth token after the user successfully authenticates (with user and password or other methods)

Go to -> Developers -> Credentials -> Create New -> SPA OAuth Client. And complete the form as follows:

CARTO platform uses under the hood to manage the authentication and authorization. When you created a SPA application in the previous step, CARTO created a SPA application in Auth0.

Auth0 provides to manage the OAuth 2.0 workflow for Angular, Vue, React, and Vanilla Javascript. In this guide, we're going to use the Vanilla Javascript SDKs to manage the login with CARTO.

Use the authenticated user to obtain an to call .

At this point, we're all clear to execute a query against the using the OAuth Access Token we've previously obtained.

The full code of this guide is available on .

We recommend you to visit Visualization with deck.gl to learn more about the visualizations you can create in deck.gl. There are many examples in our that might be useful to improve your application!

CARTO Data Warehouse
https://127.0.0.1:5173/
Workspace
Auth0
SDKs
OAuth Access Token
CARTO APIs
GitHub
gallery
Vite
here
Single Sign-On (SSO)
Build a private application using SSO
OAuth 2.0
CARTO SQL API
Architecture diagram of a private application with Login
Key Concepts section