Source code for bokeh.server.auth
#-----------------------------------------------------------------------------
# Copyright (c) Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------
''' Framework-neutral authentication policy for Bokeh server frontends. '''
from __future__ import annotations
# Standard library imports
import inspect
from collections.abc import Awaitable, Callable
from typing import Any
# Bokeh imports
from ..util.asyncio import _run_in_executor
from .request import ServerRequest
__all__ = (
'AuthPolicy',
)
type Authenticator = Callable[[ServerRequest], Any | None | Awaitable[Any | None]]
type LoginURL = str | Callable[[ServerRequest], str | None]
[docs]
class AuthPolicy:
''' Authenticate Bokeh requests without depending on a web framework.
The authenticator receives a framework-neutral
:class:`~bokeh.server.request.ServerRequest` and returns an authenticated
user, or ``None`` to reject the request. Both synchronous and asynchronous
authenticators are supported.
Args:
authenticator: Function that authenticates an HTTP or websocket
request and returns its user.
login_url: Optional URL, or request-dependent URL function, used to
redirect unauthenticated HTTP requests. Without one, Bokeh returns
HTTP 401.
logout_url: Optional URL exposed as
``curdoc().session_context.logout_url``. The host application is
responsible for implementing the endpoint.
'''
def __init__(self, authenticator: Authenticator, *, login_url: LoginURL | None = None,
logout_url: str | None = None) -> None:
self._authenticator = authenticator
self._login_url = login_url
self._logout_url = logout_url
[docs]
async def authenticate(self, request: ServerRequest) -> Any | None:
''' Return the authenticated user for a request, or ``None``. '''
user = await _run_in_executor(self._authenticator, request)
if inspect.isawaitable(user):
user = await user
return user
[docs]
def get_login_url(self, request: ServerRequest) -> str | None:
''' Return the login URL for an unauthenticated HTTP request. '''
if callable(self._login_url):
return self._login_url(request)
return self._login_url
[docs]
async def get_login_url_async(self, request: ServerRequest) -> str | None:
''' Return a request-specific login URL without blocking the event loop. '''
if callable(self._login_url):
return await _run_in_executor(self._login_url, request)
return self._login_url
@property
def logout_url(self) -> str | None:
''' The logout URL exposed to authenticated Bokeh sessions. '''
return self._logout_url