Starting and Using the Server

The examples illustrate how to access API of the Bluesky HTTP Server using httpie command-line tool. Though it is unlikely that httpie is ever used to control the server in practical deployments, the instructions could be useful for application developers for testing the server and understanding how the API work.

Installation instructions for httpie: https://httpie.io/docs/cli/installation.

In the examples it is assumed that the server address is localhost and the server port is 60610. The address and the port are used by default by Bluesky Queue Server components and should be substituted by custom address and/or port if necessary.

Starting the Server

Single-User Mode

The server can configured to operate in single-user mode. The mode is useful for demos and testing, but it could be used in small local deployments where no true authorization is required. The single-user API key is be passed to the server by setting an environment variable QSERVER_HTTP_SERVER_SINGLE_USER_API_KEY or listed in server config files (authentication/single_user_api_key). API key listed in config files overrides the key in environment variable.

Note

Single-user mode is disabled if any providers are specified in the server config files even if single-user API key is passed to the server. Make supported that authentication/providers section is not included in the config files if single-user access is the desired mode of authorization.

Passing single-user API key by setting an environment variable

An API key is an arbitrary non-empty string that consists of alphanumeric characters. Substitute <generated-api-key> for the generated API key:

QSERVER_HTTP_SERVER_SINGLE_USER_API_KEY=<generated-api-key> uvicorn --host localhost --port 60610 bluesky_httpserver.server:app

Specifying single-user API key in configuration file

Alternatively, the single-user API key may be specified in the server config file. It is considered unsafe practice to explicitly list API keys in config files, so the purpose of this feature is mainly to customize the name of environment variable used to pass the API key if the default name is inconvenient.

For example, the following config file (e.g. config.yml) causes the server to load single-user API key from the environment variable SU_API_KEY:

authentication:
  single_user_api_key: ${SU_API_KEY}

The environment variable must be set to the generated API key:

export SU_API_KEY=<generated-api-key>

and the path to the config file passed to the server:

QSERVER_HTTP_SERVER_CONFIG=config.yml uvicorn --host localhost --port 60610 bluesky_httpserver.server:app

Passing Configuration to the Server

In practical deployments, server configuration is represented as one or more YML files. Path to the location of startup files is passed to the server using the environment variable QSERVER_HTTP_SERVER_CONFIG. The path may point to a single file or a directory with multiple files. If the variable is not set, then no configuration is loaded. The settings from in config files override settings passed as environment variables.

# 'config.yml' in the current working directory
QSERVER_HTTP_SERVER_CONFIG=config.yml uvicorn --host localhost --port 60610 bluesky_httpserver.server:app

# 'config.yml' in the directory '~/.config/qserver/http'
QSERVER_HTTP_SERVER_CONFIG=~/.qserver/http/config.yml uvicorn --host localhost --port 60610 bluesky_httpserver.server:app

# Multiple config files in the directory '~/.config/qserver/http'
QSERVER_HTTP_SERVER_CONFIG=~/.config/qserver/http uvicorn --host localhost --port 60610 bluesky_httpserver.server:app

Enabling Anonymous Public Access

Anonymous public access is disabled by default. It can be enabled by setting authentication/allow_anonymous_access in the server config file:

authentication:
  allow_anonymous_access: True

Anonymous public access rules are applied when no API key or token is passed with API requests. API calls with invalid token or API key are rejected even if public access is enabled.

Authentication API for Users

Logging into the Server (Requesting Token)

Users log into the server by calling /auth/provider/<provider-name>/token, where <provider-name> should be substituted by the name of authentication provider. A user submits username and password with the API request and gets access token and refresh token. The access token is used for authorization of other API requests and the refresh token is used to request new access token when current token expires.

The server must be configured to have at least one active authentication provider. The server is shipped with simple DictionaryAPIAccessControl authentication policy, which performs authentication based on dictionary that maps usernames and passwords and intended for use in demos and testing. The following is an example of a config file sets up DictionaryAPIAccessControl as a provider named toy:

authentication:
  providers:
    - provider: toy
      authenticator: bluesky_httpserver.authenticators:DictionaryAuthenticator
      args:
        users_to_passwords:
          bob: ${BOB_PASSWORD}
          alice: ${ALICE_PASSWORD}
          tom: ${TOM_PASSWORD}
api_access:
  policy: bluesky_httpserver.authorization:DictionaryAPIAccessControl
  args:
    users:
      bob:
        roles:
          - admin
          - expert
      alice:
        roles: user
      tom:
        roles: observer

Generally it is not a good idea to explicitly list passwords in configuration files. Using environment variables is more secure. The environment variable should be set before starting the server:

export BOB_PASSWORD=bob_password
export ALICE_PASSWORD=alice_password
export TOM_PASSWORD=tom_password

Then users bob, alice and tom can log into the server as

http --form POST http://localhost:60610/api/auth/provider/toy/token username=bob password=bob_password

If authentication is successful, then the server returns access and refresh tokens.

Generating API Keys

Users that are assigned the scope user:apikeys can generate API keys used for authorization without logging into the server. API keys are often used for long-running applications or autonomous agents. API keys carry information that allows the server to identify the user who generated the key and the scopes that define access permissions. The scopes of an API key may be a full set or a subset of user’s scopes.

The API /auth/apikey accepts three parameters:

  • expires_in (int) - time until expiration of the API key in seconds;

  • scopes (option, list of strings) - list of scopes;

  • note (optional, string) - text message;

API keys may be generated using a valid token or an API key with the scope user:apikeys. If no scopes are specified in the request, then API inherits scopes of the user (if authorized by token) or created using a copy of scopes of the original API key (if authorized by API key). The inherited scopes change as user privileges change and may be expanded if the user is given additional permissions. If the parameter scopes is used to pass a list of scopes, then the API key has a fixed set of scopes. API request may never access API outside the listed scopes even if user privileges are extended. If user privileges are reduced, some scopes may not be accessed even if they are listed.

The user generating API key must be permitted to use each scope listed in the request. If the new key is generated based on the existing API key, each scope must also be allowed for the existing API key. The request fails if any of the listed scopes is not permitted.

Request API key that inherits the scopes of the user (principal) using an access token (replace <token> with the token):

http POST http://localhost:60610/api/auth/apikey expires_in:=900 'Authorization: Bearer <token>'

Request API key with fixed set of scopes (scopes are a subset of the scopes of the principal) using an access token:

http POST http://localhost:60610/api/auth/apikey expires_in:=900 scopes:='["read:status", "user:apikeys"]' 'Authorization: Bearer <token>'

Request API key using an existing API key. The scopes for the new key are a copy of the scopes of the existing key:

http POST http://localhost:60610/api/auth/apikey expires_in:=900 'Authorization: ApiKey <apikey>'

Request API key with fixed set of scopes using an existing API key:

http POST http://localhost:60610/api/auth/apikey expires_in:=900 scopes:='["read:status"]' 'Authorization: ApiKey <apikey>'

Verifying Scopes of Access Tokens and API Keys

User can verify currently permissions for a token or API key at any time by sending /auth/scopes request. The API returns the list of assigned roles and the list of scopes applied to the token or the API key:

# Get scopes for the access token
http GET http://localhost:60610/api/auth/scopes 'Authorization: Bearer <token>'
# Get scopes for the API key
http GET http://localhost:60610/api/auth/scopes 'Authorization: ApiKey <api-key>'

Getting Information on API Key

Information on an existing API key may be obtained calling /auth/apikey (GET) API and using the API key for authentication:

http GET http://localhost:60610/api/auth/apikey 'Authorization: ApiKey <apikey>'

Deleting API Key

API key may be deleted by an authenticated user by calling /auth/apikey (DELETE). The API key used for authorization of the API request can also be deleted:

# Authorization using token
http DELETE http://localhost:60610/api/auth/apikey first_eight==<first-eight-chars-of-key> 'Authorization: Bearer <token>'
# Authorization using API key
http DELETE http://localhost:60610/api/auth/apikey first_eight==<first-eight-chars-of-key> 'Authorization: ApiKey <api-key>'

Refreshing Sessions

Refresh token returned by /auth/apikey can be used to obtain replacement access tokens by calling /auth/session/refresh API:

http POST http://localhost:60610/api/auth/session/refresh refresh_token=<refresh-token>

whoami

An access token or an API key may be used to obtain full information about the user, including principal identities and open sessions by calling /auth/whoami API:

# 'whoami' using the access token
http GET http://localhost:60610/api/auth/scopes 'Authorization: Bearer <token>'
# 'whoami' using the API key
http GET http://localhost:60610/api/auth/scopes 'Authorization: ApiKey <api-key>'

Revoking Sessions

Authenticated user may revoke any of the open sessions using session UUID. The list of sessions is returned by /auth/whoami API. Revoking the session invalidates the respective refresh token. Access tokens and API keys will continue working until expiration.

# Revoke session using access token
http DELETE http://localhost:60610/api/auth/session/revoke/<full-session-uid>  'Authorization: Bearer <token>'
# Revoke session using API key
http DELETE http://localhost:60610/api/auth/session/revoke/<full-session-uid>  'Authorization: ApiKey <api-key>'

Passing Tokens and API Keys in API Requests

Generated access tokens or API keys can be used for authorization in API requests. /status API returns the status of RE Manager:

# Get scopes for the access token
http GET http://localhost:60610/api/status 'Authorization: Bearer <token>'
# Get scopes for the API key
http GET http://localhost:60610/api/status 'Authorization: ApiKey <api-key>'

Logging Out of the Server

The API /auth/logout is not changing the state of the server and returns {} (empty dictionary). The purpose of the API is to delete any tokens or API keys stored locally by the browser. The API request does not require authentication:

http POST http://localhost:60610/api/logout

Administrative API

Some API are available only to clients with administrative permissons (scope admin:read:principals and/or admin:apikeys).

Getting Information on All Principals

Clients with admin:read:principals may get information on all active principals using /auth/principal API. The API is similar to /auth/whoami, but instead of returning a single item with information on authorized principal it returns the list of items for all principal:

# Get information on all principals using token with admin privileges
http GET http://localhost:60610/api/auth/principal 'Authorization: Bearer <token>'
# Get information on all principals using API key with admin privileges
http GET http://localhost:60610/api/auth/principal 'Authorization: ApiKey <api-key>'

Getting Information on a Selected Principal

Clients with admin:read:principals may get information on any principals using /auth/principal/<principal-UUID> API. The principals are identified by UUID. The returned data is structured identically as the data returned by /auth/whoami, but may represent any user of the server, not only the authorized user:

# Get information on a selected principal using token with admin privileges
http GET http://localhost:60610/api/auth/principal/<principal-UUID> 'Authorization: Bearer <token>'
# Get information on all principals using API key with admin privileges
http GET http://localhost:60610/api/auth/principal/<principal-UUID> 'Authorization: ApiKey <api-key>'

Generating an API Key for a Principal

Clients with admin:apikeys scope may generate API keys for any principal in the system using /auth/principal/<principal-UUID>/apikey API. The scopes for the generated API key are limited by permissions assigned to the principal (not the client sending the request). The API works similarly to /auth/apikey and accepts identical set of parameters: expires_in is a required parameter representing API key expiration time in seconds, scopes and note are optional parameters. The API call must be authorized using a token or an API key of the client with administrative privileges.

# Generate API key for a given selected principal using token with admin privileges
http POST http://localhost:60610/api/auth/principal/<principal-UUID>/apikey expires_in:=900 'Authorization: Bearer <token>'
# Generate API key for a given selected principal using API key with admin privileges
http POST http://localhost:60610/api/auth/principal/<principal-UUID>/apikey expires_in:=900 'Authorization: ApiKey <api-key>'