Secure Map Services API

Last Updated: August 2026

Secure map services are map services (e.g.: OGC WMS endpoints) that require credentials to access. The Secure Map Services API allows a developer to register the endpoint and credentials of such a service once, and then allows apps to consume that service without ever storing or handling the credentials themselves.

In addition, requests can optionally be routed through a proxy endpoint provided by Tethys Portal so that credentials are never sent to the browser. See Proxying Requests for more details.

Tip

For a step-by-step tutorial on using secure map services in your app, see the Secure Map Services Tutorial.

Two authentication methods are supported:

  • API Key: a key is stored (encrypted) with the service and added to each request as a query parameter.

  • OAuth2: an OAuth2 access token is retrieved from the requesting user's linked social auth account and added to each request as a Bearer token.

Important

API keys assigned to a SecureMapService are encrypted before they are stored in the database. This requires a SALT_KEY to be set in your portal_config.yml. If you have not already done so, generate one as follows:

tethys gen portal_config
tethys settings --generate-salt-key

Secure Map Service Settings

Using secure map services in your app is accomplished by adding the secure_map_service_settings() method to your app class, which is located in your app configuration file (app.py). This method should return a list or tuple of SecureMapServiceSetting objects. For example:

from tethys_sdk.app_settings import SecureMapServiceSetting

class App(TethysAppBase):
    """
    Tethys App Class for My First App.
    """
    ...
    def secure_map_service_settings(self):
        """
        Example secure_map_service_settings method.
        """
        secure_map_service_settings = (
            SecureMapServiceSetting(
                name='primary_secure_map_service',
                description='Secure map service for app to use.',
                required=True,
            ),
        )

        return secure_map_service_settings

Caution

The ellipsis in the code block above indicates code that is not shown for brevity. DO NOT COPY VERBATIM.

Unlike other Tethys Service settings, a SecureMapServiceSetting does not specify an engine. The type of service and how it is authenticated are properties of the SecureMapService that is assigned to the setting, not of the setting itself.

Register a Secure Map Service

Before a SecureMapService can be assigned to a setting, it must be registered in the Admin Interface of Tethys Portal:

  1. Access the Admin interface of Tethys Portal by clicking on the drop down menu next to your user name and selecting the "Site Admin" option.

  2. Scroll down to the Tethys Services section of the Admin Interface and select the link titled Secure Map Services.

  3. Click on the Add Secure Map Service button.

  4. Fill in the connection information for the service (see the table below).

  5. Press the Save button to save the new SecureMapService.

The following fields are available on a SecureMapService:

Field

Description

Name

Unique name used to identify the service.

Endpoint

The URL of the map service.

Legend Title

The title to use for the legend when the service is added to a map as a layer.

Authentication Method

One of API Key or OAuth2. The fields that apply to the other method are hidden in the admin form.

API Key

The API key to use when the authentication method is API Key. The value is encrypted before it is stored in the database.

OAuth2 Provider

The social auth backend to retrieve the access token from when the authentication method is OAuth2. The options are populated from the authentication backends that are enabled for the portal (see Single Sign On (Optional)).

Service Type

The type of service: WMS (ImageWMS), GML, GeoJSON, or REST/JSON API (REST). For the map service types, the stored value is used as the source of the MVLayer that is created when the service is retrieved with as_layer=True. For GML and GeoJSON services, the map loads the features from the endpoint. Use REST/JSON API for services that are consumed with as_response=True or with as_endpoint=True rather than rendered as a map layer.

Use Proxy for Requests

When checked, requests are routed through a Tethys Portal proxy endpoint so that credentials are never exposed to the browser. See Proxying Requests.

Parameters

A JSON object of additional query parameters to include with each request to the service. See Service Parameters.

Tip

You do not need to create a new SecureMapService for each SecureMapServiceSetting or each app. Apps and SecureMapServiceSettings can share SecureMapServices.

Assign Secure Map Service

The SecureMapServiceSetting can be thought of as a socket for a connection to a SecureMapService. Before we can do anything with the SecureMapServiceSetting we need to "plug in" or assign a SecureMapService to the setting. Assigning a SecureMapService is done through the Admin Interface of Tethys Portal as follows:

  1. Navigate to App Settings Page

    1. Return to the Home page of the Admin Interface using the Home link in the breadcrumbs.

    2. Scroll to the Tethys Apps section of the Admin Interface and select the Installed Apps link.

    3. Select the link for your app from the list of installed apps.

  2. Assign SecureMapService to the appropriate SecureMapServiceSetting

    1. Scroll to the Secure Map Service Settings section and locate the SecureMapServiceSetting.

    Note

    If you don't see the SecureMapServiceSetting in the list, uninstall the app and reinstall it again.

    1. Assign the appropriate SecureMapService to your SecureMapServiceSetting using the drop down menu in the Secure Map Service column.

    2. Press the Save button at the bottom of the page to save your changes.

Note

During development you will assign the SecureMapService setting yourself. However, when the app is installed in production, this step is performed by the portal administrator upon installing your app, which may or may not be yourself.

Working with Secure Map Services

After a secure map service has been assigned to a setting, use the get_secure_map_service() method of the app class to retrieve it. The value that is returned depends on which of the as_ arguments is provided.

Get the Service

Called with only a name, get_secure_map_service() returns the SecureMapService object that is assigned to the setting:

from .app import App

service = App.get_secure_map_service('primary_secure_map_service')

Get an Endpoint

Pass as_endpoint=True to get the URL of the service with all of its parameters (and the API key, if applicable) applied:

from .app import App

endpoint = App.get_secure_map_service('primary_secure_map_service', as_endpoint=True)

Note

A lazy string is returned when as_endpoint is True. This ensures the endpoint reflects the current state of the service's settings every time it is used, and allows the endpoint to be referenced at import time (e.g.: as a MapLayout basemap) before the app URLs have been registered.

Get a Map Layer

Pass as_layer=True to get an MVLayer for the service that can be added to a MapView or MapLayout. The source of the layer is the Service Type of the service and the legend_title is the Legend Title of the service:

from .app import App

layer = App.get_secure_map_service('primary_secure_map_service', as_layer=True)

If the service uses OAuth2 authentication and is not proxied, the access token must be retrieved from the user making the request, so the request_user argument is required:

layer = App.get_secure_map_service(
    'primary_secure_map_service',
    as_layer=True,
    request_user=request.user,
)

Specifying the Source Projection

GML layers and Vector layers that are loaded with a token are transformed from the coordinate reference system of the source data to the projection of the map when they are rendered. That CRS is determined in the following order:

  1. The data_projection option of the layer, if one is set.

  2. The CRS declared by the data itself (srsName in GML/WFS responses, crs in GeoJSON).

  3. EPSG:4326, which is assumed when the data declares no CRS.

Most services declare their CRS, so no additional configuration is needed. If a service returns data in a projection other than EPSG:4326 without declaring it, set the data_projection option on the layer that is returned:

layer = App.get_secure_map_service(
    'primary_secure_map_service',
    as_layer=True,
    request_user=request.user,
)
layer.options['data_projection'] = 'EPSG:26912'

Note

param_overrides cannot be used to set data_projection, because those values are added to the query string of the request to the service. Set it on the options of the returned MVLayer as shown above.

Get a Response

Pass as_response=True to perform the request server-side and get the resulting requests.Response object. This is useful for services that return data to be processed by the app rather than rendered as a map layer:

from .app import App

response = App.get_secure_map_service(
    'primary_secure_map_service',
    as_response=True,
    request_user=request.user,
)
data = response.json()

Note

As with as_layer, request_user is required when the service uses OAuth2 authentication. An exception is raised if the request is not successful.

Service Parameters

The Parameters field of a SecureMapService is a JSON object of query parameters that are added to every request made to the service. For example, the following parameters could be used for a WMS service:

{
    "service": "WMS",
    "request": "GetMap",
    "layers": "my:layer",
    "format": "image/png",
    "transparent": true
}

String values may contain placeholders that reference fields of the SecureMapService, using Python's string.Template syntax. This is most commonly used to place the API key in a parameter with a name other than api_key:

{
    "connectId": "${api_key}"
}

Note

If the API key is not referenced by any parameter, it is added automatically as a parameter named api_key.

Overriding Parameters Per Request

Pass a param_overrides dictionary to get_secure_map_service() to add to or replace the parameters of the service for a single request. This does not modify the SecureMapService:

from .app import App

response = App.get_secure_map_service(
    'primary_secure_map_service',
    as_response=True,
    param_overrides={'layers': 'my:other_layer'},
    request_user=request.user,
)

Updating Parameters Permanently

Use the update_secure_map_service_params() method of the app class to permanently update the parameters of the SecureMapService that is assigned to a setting. The given parameters are merged with the existing parameters and saved:

from .app import App

App.update_secure_map_service_params(
    'primary_secure_map_service',
    {'layers': 'my:other_layer'},
)

Caution

SecureMapServices can be shared by multiple settings and apps, so updating the parameters of a service affects every app that uses it.

Proxying Requests

When the Use Proxy for Requests option is enabled on a SecureMapService, the endpoint that is returned by get_secure_map_service() is not the endpoint of the map service, but rather a URL to a proxy view provided by Tethys Portal (secure-map-proxy/<id>/). The browser makes its requests against the proxy, which then adds the credentials and parameters of the service server-side and streams the response back. As a result, the API key or access token is never sent to the browser.

The proxy view requires the user to be logged in, and for OAuth2 services it uses the access token of the logged in user making the request.

Tip

Enable Use Proxy for Requests for any service whose credentials should not be visible to end users. Without it, the API key is included in the URL of the tile requests that the browser makes, where it can be read from the browser's developer tools.

Requiring an OAuth2 Provider

Services that use OAuth2 authentication require the user to have linked the corresponding social auth account to their Tethys Portal account. To require users to link an account before they can access an app, add the app package and provider name to the OAUTH2_REQUIREMENTS portal setting:

tethys settings --set OAUTH2_REQUIREMENTS.my_first_app my_provider

Users who access the app without having linked an account for the given provider are redirected to their user settings page with a message prompting them to link it.

Note

The provider must also be configured as an authentication backend for the portal. See Single Sign On (Optional) for more details.

API Documentation

TethysAppBase.secure_map_service_settings()

Override this method to define secure map service connections for use in your app.

Returns:

A list or tuple of SecureMapServiceSetting objects.

Return type:

iterable

Example:

from tethys_sdk.app_settings import SecureMapServiceSetting

class MyFirstApp(TethysAppBase):

    def secure_map_service_settings(self):
        """
        Example secure_map_service_settings method.
        """
        secure_map_services = (
            SecureMapServiceSetting(
                name='primary_secure_map_service',
                description='Secure Map Service for app to use',
                required=True,
            ),
        )

        return secure_map_services
classmethod TethysAppBase.get_secure_map_service(name, as_endpoint=False, as_layer=False, as_response=False, as_token=False, param_overrides=None, request_user=None, source_options=None, layer_options=None)

Retrieves secure map service assigned to named SecureMapServiceSetting for the app.

Parameters:
  • name (str) -- name of the SecureMapServiceSetting as defined in the app.py.

  • as_endpoint (bool) -- Returns endpoint url string if True, Defaults to False.

  • as_layer (bool) -- Returns an MVLayer object if True, Defaults to False.

  • as_response (bool) -- Returns requests.Response object if True, Defaults to False.

  • as_token (bool) -- Returns an OAuth2 token string if True, Defaults to False.

  • param_overrides (dict) -- Dictionary of parameters to override for the map service request. Defaults to None.

  • request_user (User) -- Django User object to use for the request. Defaults to None.

  • source_options (dict) -- Used with as_layer. Merged into the options of the returned MVLayer (OpenLayers ol.source options, e.g. data_projection). url and token are set by the service and cannot be overridden. Defaults to None.

  • layer_options (dict) -- Used with as_layer. Merged over {"visible": True} into the layer_options of the returned MVLayer (OpenLayers ol.layer options, e.g. style). Defaults to None.

Returns:

SecureMapService assigned to setting.

Return type:

SecureMapService

NOTE: When as_endpoint is True a lazy string is returned. This ensures the endpoint reflects the current state of the map service's settings every time it is used.

classmethod TethysAppBase.update_secure_map_service_params(name, params)

Update the params for a given SecureMapServiceSetting's assigned SecureMapService.

NOTE: This method will not update the params for the SecureMapServiceSetting itself. It will only update the params for the assigned SecureMapService.

Parameters:
  • name (str) -- name of the SecureMapServiceSetting as defined in the app.py.

  • params (dict) -- dictionary of params to update for the service.