Authentication
Goal: add Authentication forwarding to the /wmts endpoints
requirements: titiler.stacapi
"""TiTiler+stacapi FastAPI application."""
from dataclasses import dataclass, field
from fastapi import Depends, FastAPI
from fastapi.security import APIKeyHeader
from starlette.middleware.cors import CORSMiddleware
from starlette.requests import Request
from typing_extensions import Annotated
import morecantile
from titiler.core.dependencies import DefaultDependency
from titiler.core.errors import DEFAULT_STATUS_CODES, add_exception_handlers
from titiler.core.middleware import CacheControlMiddleware
from titiler.mosaic.errors import MOSAIC_STATUS_CODES
from titiler.stacapi import __version__ as titiler_stacapi_version
from titiler.stacapi.dependencies import APIParams
from titiler.stacapi.factory import OGCWMTSFactory
from titiler.stacapi.settings import ApiSettings, STACAPISettings
settings = ApiSettings()
stacapi_config = STACAPISettings()
header_scheme = APIKeyHeader(name="Authorization", description="STAC API Authorization")
@dataclass(init=False)
class BackendParams(DefaultDependency):
"""backend parameters."""
api_params: APIParams = field(init=False)
def __init__(self, request: Request, token: Annotated[str, Depends(header_scheme)]):
"""Initialize BackendParams
Note: Because we don't want `api_params` to appear in the documentation we use a dataclass with a custom `__init__` method.
FastAPI will use the `__init__` method but will exclude Request in the documentation making `api_params` an invisible dependency.
"""
self.api_params = APIParams(
url=request.app.state.stac_url,
headers={"Authorization": token},
)
app = FastAPI(
title=settings.name,
openapi_url="/api",
docs_url="/api.html",
description="""Connect titiler to STAC APIs.""",
version=titiler_stacapi_version,
root_path=settings.root_path,
)
# We store the STAC API url in the application state
app.state.stac_url = stacapi_config.stac_api_url
add_exception_handlers(app, DEFAULT_STATUS_CODES)
add_exception_handlers(app, MOSAIC_STATUS_CODES)
# Set all CORS enabled origins
if settings.cors_origins:
app.add_middleware(
CORSMiddleware,
allow_origins=settings.cors_origins,
allow_credentials=True,
allow_methods=["GET"],
allow_headers=["*"],
)
app.add_middleware(CacheControlMiddleware, cachecontrol=settings.cachecontrol)
webmerc = morecantile.tms.get("WebMercatorQuad").model_dump()
webmerc["id"] = "EPSG3857"
supported_tms = morecantile.TileMatrixSets({"EPSG3857": morecantile.TileMatrixSet.model_validate(webmerc)})
###############################################################################
# OGC WMTS Endpoints
wmts = OGCWMTSFactory(
backend_dependency=BackendParams,
supported_tms=supported_tms,
)
app.include_router(wmts.router, tags=["Web Map Tile Service"])