TokenStorage#

The TokenStorage component provides a way of storing and loading the tokens received from authentication and token refreshes.

Usage#

TokenStorage is available under the name globus_sdk.tokenstorage.

Storage adapters are the main objects of this subpackage. Primarily, usage should revolve around creating a storage adapter, potentially loading data from it, and using it as the on_refresh handler for an authorizer.

For example:

import os
import globus_sdk
from globus_sdk.tokenstorage import SimpleJSONFileAdapter

my_file_adapter = SimpleJSONFileAdapter(os.path.expanduser("~/mytokens.json"))

if not my_file_adapter.file_exists():
    # ... do a login flow, getting back initial tokens
    # elided for simplicity here
    token_response = ...
    # now store the tokens, and pull out the tokens for the
    # resource server we want
    my_file_adapter.store(token_response)
    by_rs = token_response.by_resource_server
    tokens = by_rs["transfer.api.globus.org"]
else:
    # otherwise, we already did this whole song-and-dance, so just
    # load the tokens from that file
    tokens = my_file_adapter.get_token_data("transfer.api.globus.org")


# RereshTokenAuthorizer and ClientCredentialsAuthorizer both use
# `on_refresh` callbacks
# this feature is therefore only relevant for those auth types
#
# auth_client is the internal auth client used for refreshes,
# and which was used in the login flow
# note that this is all normal authorizer usage wherein
# my_file_adapter is providing the on_refresh callback
auth_client = ...
authorizer = globus_sdk.RefreshTokenAuthorizer(
    tokens["refresh_token"],
    auth_client,
    access_token=tokens["access_token"],
    expires_at=tokens["expires_at_seconds"],
    on_refresh=my_file_adapter.on_refresh,
)

# or, for client credentials
authorizer = globus_sdk.ClientCredentialsAuthorizer(
    auth_client,
    ["urn:globus:auth:transfer.api.globus.org:all"],
    access_token=tokens["access_token"],
    expires_at=tokens["expires_at_seconds"],
    on_refresh=my_file_adapter.on_refresh,
)

# and then use the authorizer on a client!
tc = globus_sdk.TransferClient(authorizer=authorizer)

Complete Example Usage#

The Group Listing With Token Storage Script provides complete and runnable example which leverages tokenstorage.

Adapter Types#

globus_sdk.tokenstorage provides base classes for building your own storage adapters, and several complete adapters.

The SimpleJSONFileAdapter is good for the “simplest possible” persistent storage, using a JSON file to store token data.

MemoryAdapter is even simpler still, and is great for writing and testing code which uses the StorageAdapter interface backed by an in-memory structure.

The SQLiteAdapter is more complex, for applications like the globus-cli which need to store various tokens and additional configuration. In addition to basic token storage, the SQLiteAdapter provides for namespacing of the token data, and for additional configuration storage.

Reference#

class globus_sdk.tokenstorage.StorageAdapter[source]#

Bases: object

abstract store(token_response)[source]#

Store an OAuthTokenResponse in the underlying storage for this adapter.

Parameters:

token_response (OAuthTokenResponse) – The token response to store

abstract get_token_data(resource_server)[source]#

Lookup token data for a resource server

Either returns a dict with the access token, refresh token (optional), and expiration time, or returns None, indicating that there was no data for that resource server.

Parameters:

resource_server (str) – The resource_server string which uniquely identifies the token data to retriever from storage

Return type:

dict[str, Any] | None

on_refresh(token_response)[source]#

By default, the on_refresh handler for a token storage adapter simply stores the token response.

Parameters:

token_response (OAuthTokenResponse) – The token response received from the refresh

class globus_sdk.tokenstorage.MemoryAdapter[source]#

Bases: StorageAdapter

A token storage adapter which stores tokens in process memory.

Tokens are lost when the process exits.

store(token_response)[source]#

Store an OAuthTokenResponse in the underlying storage for this adapter.

Parameters:

token_response (OAuthTokenResponse) – The token response to store

get_token_data(resource_server)[source]#

Lookup token data for a resource server

Either returns a dict with the access token, refresh token (optional), and expiration time, or returns None, indicating that there was no data for that resource server.

Parameters:

resource_server (str) – The resource_server string which uniquely identifies the token data to retriever from storage

Return type:

dict[str, Any] | None

class globus_sdk.tokenstorage.FileAdapter[source]#

Bases: StorageAdapter

File adapters are for single-user cases, where we can assume that there’s a simple file-per-user and users are only ever attempting to read their own files.

file_exists()[source]#

Check if the file used by this file storage adapter exists.

Return type:

bool

user_only_umask()[source]#

A context manager to deny rwx to Group and World, x to User

This does not create a file, but ensures that if a file is created while in the context manager, its permissions will be correct on unix systems.

Note

On Windows, this has no effect. To control the permissions on files used for token storage, use %LOCALAPPDATA% or %APPDATA%. These directories should only be accessible to the current user.

Return type:

Iterator[None]

class globus_sdk.tokenstorage.SimpleJSONFileAdapter(filename)[source]#

Bases: FileAdapter

Parameters:

filename (str) – the name of the file to write to and read from

A storage adapter for storing tokens in JSON files.

store(token_response)[source]#

By default, self.on_refresh is just an alias for this function.

Given a token response, extract all the token data and write it to self.filename as JSON data. Additionally will write the version of globus_sdk.tokenstorage which was in use.

Under the assumption that this may be running on a system with multiple local users, this sets the umask such that only the owner of the resulting file can read or write it.

Parameters:

token_response (OAuthTokenResponse) – The token data received from the refresh

get_by_resource_server()[source]#

Read only the by_resource_server formatted data from the file, discarding any other keys.

This returns a dict in the same format as OAuthTokenResponse.by_resource_server

Return type:

dict[str, Any]

get_token_data(resource_server)[source]#

Lookup token data for a resource server

Either returns a dict with the access token, refresh token (optional), and expiration time, or returns None, indicating that there was no data for that resource server.

Parameters:

resource_server (str) – The resource_server string which uniquely identifies the token data to retriever from storage

Return type:

dict[str, Any] | None

class globus_sdk.tokenstorage.SQLiteAdapter(dbname, *, namespace='DEFAULT', connect_params=None)[source]#

Bases: FileAdapter

Parameters:
  • dbname (pathlib.Path | str) – The name of the DB file to write to and read from. If the string “:memory:” is used, an in-memory database will be used instead.

  • namespace (str) – A “namespace” to use within the database. All operations will be performed indexed under this string, so that multiple distinct sets of tokens may be stored in the database. You might use usernames as the namespace to implement a multi-user system, or profile names to allow multiple Globus accounts to be used by a single user.

  • connect_params (dict[str, t.Any] | None) – A pass-through dictionary for fine-tuning the SQLite connection.

A storage adapter for storing tokens in sqlite databases.

SQLite adapters are for more complex cases, where there may be multiple users or “profiles” in play, and additionally a dynamic set of resource servers which need to be stored in an extensible way.

The namespace is a user-supplied way of partitioning data, and any token responses passed to the storage adapter are broken apart and stored indexed by resource_server. If you have a more complex use-case in which this scheme will be insufficient, you should encode that in your choice of namespace values.

The connect_params is an optional dictionary whose elements are passed directly to the underlying sqlite3.connect() method, enabling developers to fine-tune the connection to the SQLite database. Refer to the sqlite3.connect() documentation for SQLite-specific parameters.

close()[source]#

Close the underlying database connection.

store_config(config_name, config_dict)[source]#
Parameters:
  • config_name (str) – A string name for the configuration value

  • config_dict (Mapping[str, Any]) – A dict of config which will be stored serialized as JSON

Store a config dict under the current namespace in the config table. Allows arbitrary configuration data to be namespaced under the namespace, so that application config may be associated with the stored tokens.

Uses sqlite “REPLACE” to perform the operation.

read_config(config_name)[source]#
Parameters:

config_name (str) – A string name for the configuration value

Return type:

dict[str, Any] | None

Load a config dict under the current namespace in the config table. If no value is found, returns None

remove_config(config_name)[source]#
Parameters:

config_name (str) – A string name for the configuration value

Return type:

bool

Delete a previously stored configuration value.

Returns True if data was deleted, False if none was found to delete.

store(token_response)[source]#
Parameters:

token_response (OAuthTokenResponse) – a globus_sdk.OAuthTokenResponse object containing token data to store

By default, self.on_refresh is just an alias for this function.

Given a token response, extract the token data for the resource servers and write it to self.dbname, stored under the adapter’s namespace

get_token_data(resource_server)[source]#

Load the token data JSON for a specific resource server.

In the event that the server cannot be found in the DB, return None.

Parameters:

resource_server (str) – The name of a resource server to lookup in the DB, as one would use as a key in OAuthTokenResponse.by_resource_server

Return type:

dict[str, Any] | None

get_by_resource_server()[source]#

Load the token data JSON and return the resulting dict objects, indexed by resource server.

This should look identical to an OAuthTokenResponse.by_resource_server in format and content. (But it is not attached to a token response object.)

Return type:

dict[str, Any]

remove_tokens_for_resource_server(resource_server)[source]#

Given a resource server to target, delete tokens for that resource server from the database (limited to the current namespace). You can use this as part of a logout command implementation, loading token data as a dict, and then deleting the data for each resource server.

Returns True if token data was deleted, False if none was found to delete.

Parameters:

resource_server (str) – The name of the resource server to remove from the DB, as one would use as a key in OAuthTokenResponse.by_resource_server

Return type:

bool

iter_namespaces(*, include_config_namespaces=False)[source]#

Iterate over the namespaces which are in use in this storage adapter’s database. The presence of tokens for a namespace does not indicate that those tokens are valid, only that they have been stored and have not been removed.

Parameters:

include_config_namespaces (bool) – Include namespaces which appear only in the configuration storage section of the sqlite database. By default, only namespaces which were used for token storage will be returned

Return type:

Iterator[str]