WSGI and ASGI applications#

Two integrations with no dependency, for a WSGI or an ASGI server. Their hooks take a ScimRequest, and return a ScimResponse.

class scim2_server.applications.base.BaseApplication(provider: ScimProvider, service: ScimService | None = None)[source]#

The parts of the WSGI and ASGI applications that do no input or output.

Parameters:
  • provider – The description of the service.

  • service – The service serving the requests, built upon provider. Pass a subclass of ScimService to change one of its steps, such as the URL of the resources. A ScimService of provider by default.

static split_path(path: str) → str[source]#

Return the path of a request, relative to the root URL of the SCIM endpoints.

The /v2 prefix is optional, and the .scim suffix is removed (RFC 7644 §3.8).

get_subject(request: ScimRequest) → Any[source]#

Return the authenticated subject of a request.

It returns None by default. Override it to pass the subject that check_auth() authenticated to the service, for authorize() and /Me.

check_auth(request: ScimRequest) → None[source]#

Authenticate the client of a request.

It accepts every request. Override it, and raise UnauthorizedException to refuse a request whose credentials are missing or invalid. Check the rights of the client in authorize(), which sees each operation of a bulk request. It is not called for /ServiceProviderConfig (RFC 7643 §5).

handle_exception(request: ScimRequest, exception: Exception) → ScimResponse[source]#

Return the SCIM error response of an exception raised while serving a request.

An error of the client is logged at the INFO level, without traceback. Any other exception is a bug: it is logged at the ERROR level, with its traceback. Override this method to observe the errors of the requests. The errors of the operations of a bulk request are not passed to it.

finalize_response(request: ScimRequest, response: ScimResponse) → ScimResponse[source]#

Add the headers every response carries, and return the response.

Override this method to change or observe the response sent to the client.

class scim2_server.applications.wsgi.WSGIApplication(storage: ScimStorage, provider: ScimProvider, service: ScimService | None = None)[source]#

A WSGI application serving the SCIM protocol over a storage.

It reads the WSGI requests, serves them with a ScimHandler, and writes the responses.

Parameters:
  • storage – The storage of the resources.

  • provider – The description of the service.

  • service – The service serving the requests, built upon provider.

static get_base_url(environ: WSGIEnvironment) → str[source]#

Return the root URL of the SCIM endpoints, as the client sees it.

read_request(environ: WSGIEnvironment) → ScimRequest[source]#

Return the SCIM request of a WSGI request.

The body is read up to one byte more than the service accepts, so that the service answers 413 to a larger body.

read_body(environ: WSGIEnvironment, request: ScimRequest) → bytes[source]#

Read the body of a request, up to one byte more than the service accepts.

A body without Content-Length is read up to its end, when the server marks its input as terminated.

dispatch_request(request: ScimRequest) → ScimResponse[source]#

Authenticate a request and serve it.

Override this method to act before or after a request is served.

serve(request: ScimRequest) → ScimResponse[source]#

Serve a request and return the response sent to the client.

class scim2_server.applications.asgi.ASGIApplication(storage: AsyncScimStorage, provider: ScimProvider, service: ScimService | None = None)[source]#

An ASGI application serving the SCIM protocol over an asynchronous storage.

It reads the ASGI requests, serves them with an AsyncScimHandler, and writes the responses. It answers the lifespan messages of the server.

Parameters:
  • storage – The storage of the resources.

  • provider – The description of the service.

  • service – The service serving the requests, built upon provider.

static get_base_url(scope: dict[str, Any]) → str[source]#

Return the root URL of the SCIM endpoints, as the client sees it.

async read_request(scope: dict[str, Any], receive: Callable[[], Awaitable[dict[str, Any]]]) → ScimRequest[source]#

Return the SCIM request of an ASGI request.

The body is read up to one byte more than the service accepts, so that the service answers 413 to a larger body.

async dispatch_request(request: ScimRequest) → ScimResponse[source]#

Authenticate a request and serve it.

Override this method to act before or after a request is served.

async serve(request: ScimRequest) → ScimResponse[source]#

Serve a request and return the response sent to the client.

class scim2_server.applications.wsgi.TenantDispatcher(factory: Callable[[str], WSGICallable | None])[source]#

A WSGI application serving each tenant with its own SCIM application.

The tenant is the first segment of the request path, as in the URL prefix method of RFC 7644 §6.1: a request to /<tenant>/v2/Users is served by the application of <tenant>, mounted under /<tenant>.

The application of a tenant is built on its first request, then kept for the following ones.

Parameters:

factory – Build the application of a tenant from its name, or return None when the tenant does not exist.

static is_valid_tenant(tenant: str) → bool[source]#

Tell whether a name can identify a tenant.

The version segment is refused, so that a request without a tenant is not served by a tenant named v2.

select_tenant(environ: WSGIEnvironment) → str | None[source]#

Return the tenant of a request, and move it from the path to the mount prefix.

Override this method to read the tenant from somewhere else, such as a header or a sub-domain (RFC 7644 §6.1).

get_application(tenant: str) → WSGICallable | None[source]#

Return the application of a tenant, building it on its first request.

class scim2_server.applications.wsgi.ForwardedHeaders(application: WSGICallable)[source]#

A WSGI middleware that trusts the X-Forwarded-* headers of a reverse proxy.

The application then builds its URLs from the URL the client used. Only use it behind a proxy that sets these headers.