Authorisation

Web API authorisation.

Credentials

Client for retrieving access tokens.

Token

Expiring access token.

RefreshingCredentials

Synchronous client for self-refreshing tokens.

RefreshingToken

Automatically refreshing access token.

AccessToken

Access token base class.

scope

User access token privileges.

Scope

Set of scopes for a token.

request_client_token

Request for client credentials.

prompt_for_user_token

Prompt for manual authorisation.

refresh_user_token

Request a refreshed user token.

prompt_for_pkce_token

Prompt for manual authorisation with PKCE.

refresh_pkce_token

Request a refreshed PKCE user token.

UserAuth

Implement user authorisation flow.

gen_state

Generate state to use in user authorisation.

parse_code_from_url

Parse an URL for parameter 'code'.

parse_state_from_url

Parse an URL for parameter 'state'.

See also: Authorisation guide.

Expiring credentials

class tekore.Credentials(client_id, client_secret=None, redirect_uri=None, sender=None, asynchronous=None)

Bases: Client

Client for retrieving access tokens.

Parameters:
  • client_id (str) – client id

  • client_secret (str) – client secret, not required for PKCE user authorisation

  • redirect_uri (str) – whitelisted redirect URI, required for user authorisation

  • sender (Sender) – request sender

  • asynchronous (bool) – synchronicity requirement

pkce_user_authorisation(scope=None, state=None, verifier_bytes=32)

Construct authorisation URL and verifier.

Step 1/2 in authorisation code flow with proof key for code exchange. The user should be redirected to the resulting URL for authorisation. The verifier is passed to request_pkce_token() in step 2.

Parameters:
  • scope – token privileges, accepts a Scope, a single scope, a list of scopes and strings for Scope, or a space-separated list of scopes as a string

  • state (str) – additional state

  • verifier_bytes (int) – number of bytes to generate PKCE verifier with, 32 <= bytes <= 96. The specified range of bytes generates the appropriate number of characters (43 - 128) after base-64 encoding, as required in RFC 7636.

Returns:

authorisation URL and PKCE code verifier

Return type:

Tuple[str, str]

refresh(token)

Refresh an access token.

Both client and user tokens are accepted and refreshed. The correct refreshing method is applied regardless if PKCE was used or not. For client tokens, a new token is returned. For user tokens, a refreshed token is returned.

Parameters:

token (Token) – token to be refreshed

Returns:

refreshed access token

Return type:

Token

refresh_pkce_token(refresh_token)

Request a refreshed PKCE user token.

Parameters:

refresh_token (str) – refresh token

Returns:

refreshed user access token

Return type:

Token

refresh_user_token(refresh_token)

Request a refreshed user token.

Parameters:

refresh_token (str) – refresh token

Returns:

refreshed user access token

Return type:

Token

request_client_token()

Request a client token.

Returns:

client access token

Return type:

Token

request_pkce_token(code, verifier)

Request a new PKCE user token.

Step 2/2 in authorisation code flow with proof key for code exchange. Code is provided as a URL parameter in the redirect URI after login in step 1: pkce_user_authorisation().

Parameters:
  • code (str) – code from redirect parameters

  • verifier (str) – PKCE code verifier generated for authorisation URL

Returns:

user access token

Return type:

Token

request_user_token(code)

Request a new user token.

Step 2/2 in authorisation code flow. Code is provided as a URL parameter in the redirect URI after login in step 1: user_authorisation_url().

Parameters:

code (str) – code from redirect parameters

Returns:

user access token

Return type:

Token

user_authorisation_url(scope=None, state=None, show_dialog=False)

Construct an authorisation URL.

Step 1/2 in authorisation code flow. User should be redirected to the resulting URL for authorisation. Step 2/2: request_user_token().

Parameters:
  • scope – token privileges, accepts a Scope, a single scope, a list of scopes and strings for Scope, or a space-separated list of scopes as a string

  • state (str) – additional state

  • show_dialog (bool) – force login dialog even if previously authorised

Returns:

login URL

Return type:

str

class tekore.Token(token_info, uses_pkce)

Bases: AccessToken

Expiring access token.

Represents both client and user tokens. The refresh token of a client token is None.

Parameters:
  • token_info (dict) –

  • uses_pkce (bool) –

property access_token: str

Bearer token value.

property expires_at: int

When the token expires.

property expires_in: int

Seconds until token expiration.

property is_expiring: bool

Determine whether token is about to expire.

property refresh_token: str | None

Refresh token for generating new access tokens.

None if the token is an application token.

property scope: Scope

Privileges granted to the token.

Empty Scope if the token is an application token or a user token without any scopes.

property token_type: str

How the token may be used, always ‘Bearer’.

property uses_pkce: bool

Proof key for code exchange used in authorisation.

class tekore.AccessToken

Bases: ABC

Access token base class.

abstract property access_token: str

Bearer token value.

Used as the string representation of the instance.

Refreshing credentials

class tekore.RefreshingCredentials(client_id, client_secret=None, redirect_uri=None, sender=None)

Synchronous client for self-refreshing tokens.

Delegates to an underlying Credentials manager and parses tokens it returns into RefreshingToken.

Parameters:
  • client_id (str) – client id

  • client_secret (str) – client secret, not required for PKCE user authorisation

  • redirect_uri (str) – whitelisted redirect URI, required for user authorisation

  • sender (Sender) – synchronous request sender

credentials

underlying credentials manager for token refreshing

pkce_user_authorisation(scope=None, state=None, verifier_bytes=32)

Construct authorisation URL and verifier.

Step 1/2 in authorisation code flow with proof key for code exchange. The user should be redirected to the resulting URL for authorisation. The verifier is passed to request_pkce_token() in step 2.

Parameters:
  • scope – token privileges, accepts a Scope, a single scope, a list of scopes and strings for Scope, or a space-separated list of scopes as a string

  • state (str) – additional state

  • verifier_bytes (int) – number of bytes to generate PKCE verifier with, 32 <= bytes <= 96. The specified range of bytes generates the appropriate number of characters (43 - 128) after base-64 encoding, as required in RFC 7636.

Returns:

authorisation URL and PKCE code verifier

Return type:

Tuple[str, str]

refresh_pkce_token(refresh_token)

Request a refreshed PKCE user token.

Parameters:

refresh_token (str) – refresh token

Returns:

refreshed user access token

Return type:

RefreshingToken

refresh_user_token(refresh_token)

Request an automatically refreshing user token with a refresh token.

Parameters:

refresh_token (str) – refresh token

Returns:

automatically refreshing user token

Return type:

RefreshingToken

request_client_token()

Request a refreshing client token.

Returns:

automatically refreshing client token

Return type:

RefreshingToken

request_pkce_token(code, verifier)

Request a new PKCE user token.

Step 2/2 in authorisation code flow with proof key for code exchange. Code is provided as a URL parameter in the redirect URI after login in step 1: pkce_user_authorisation().

Parameters:
  • code (str) – code from redirect parameters

  • verifier (str) – PKCE code verifier generated for authorisation URL

Returns:

user access token

Return type:

RefreshingToken

request_user_token(code)

Request a new refreshing user token.

Step 2/2 in authorisation code flow. Code is provided as a URL parameter in the redirect URI after login in step 1: user_authorisation_url().

Parameters:

code (str) – code from redirect parameters

Returns:

automatically refreshing user token

Return type:

RefreshingToken

user_authorisation_url(scope=None, state=None, show_dialog=False)

Construct an authorisation URL.

Step 1/2 in authorisation code flow. User should be redirected to the resulting URL for authorisation. Step 2/2: request_user_token().

Parameters:
  • scope – token privileges, accepts a Scope, a single scope, a list of scopes and strings for Scope, or a space-separated list of scopes as a string

  • state (str) – additional state

  • show_dialog (bool) – force login dialog even if previously authorised

Returns:

login URL

Return type:

str

class tekore.RefreshingToken(token, credentials)

Bases: AccessToken

Automatically refreshing access token.

Returned from utility functions and RefreshingCredentials. It shouldn’t have to be instantiated outside of the functions, unless you are sure that you want to.

Uses an instance of Credentials to automatically request a new access token when the old one is about to expire. This occurs when the access_token property is read.

Both expires_in and expires_at are always None, and is_expiring is always False.

Parameters:
  • token (Token) – access token object

  • credentials (Credentials) – credentials manager for token refreshing

credentials

credentials manager for token refreshing

property access_token: str

Bearer token value.

property expires_at: None

When the token expires, always None.

property expires_in: None

Seconds until token expiration, always None.

property is_expiring: bool

Determine whether token is about to expire, always False.

property refresh_token: str | None

Refresh token for generating new access tokens.

None if the token is an application token.

property scope: Scope

Privileges granted to the token.

Empty Scope if the token is an application token or a user token without any scopes.

property token_type: str

How the token may be used, always ‘Bearer’.

property uses_pkce: bool

Proof key for code exchange used in authorisation.

Scopes

Scopes are used in user authorisation to retrieve tokens with additional privileges. scope is an enumeration of every possible such privilege.

import tekore as tk

cred = (client_id, client_secret, redirect_uri)
scope = tk.scope.user_read_email + tk.scope.user_read_private
token = tk.prompt_for_user_token(*cred, scope)

See Spotify’s Authorization scopes guide for scope descriptions. Scopes that are required or optional are listed in each endpoint’s documentation, see Client. They can also be determined programmatically.

class tekore.scope(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

User access token privileges.

The string representation of a member is its enum value.

s = tk.scope.user_read_email
print(s)  # -> 'user-read-email'

Also provides three scopes that are a combination of others.

tk.scope.read: Scope = ...            # All read scopes
tk.scope.write: Scope = ...           # All write scopes
tk.scope.every: Scope = read + write  # All available scopes

Note

app_remote_control and streaming are only used outside of the Web API, and are not included in the premade scope combinations.

Addition and subtraction from both sides is supported but delegated to Scope and always returns a Scope.

__add__(other)

Combine to a set of scopes.

Return type:

Scope

__radd__(other)

Combine to a set of scopes.

Return type:

Scope

__rsub__(other)

Remove scope from another.

Return type:

Scope

__sub__(other)

Remove scope from another.

Return type:

Scope

app_remote_control = 'app-remote-control'
every = frozenset({'playlist-modify-private', 'playlist-modify-public', 'playlist-read-collaborative', 'playlist-read-private', 'ugc-image-upload', 'user-follow-modify', 'user-follow-read', 'user-library-modify', 'user-library-read', 'user-modify-playback-state', 'user-read-currently-playing', 'user-read-email', 'user-read-playback-position', 'user-read-playback-state', 'user-read-private', 'user-read-recently-played', 'user-top-read'})
playlist_modify_private = 'playlist-modify-private'
playlist_modify_public = 'playlist-modify-public'
playlist_read_collaborative = 'playlist-read-collaborative'
playlist_read_private = 'playlist-read-private'
read = frozenset({'playlist-read-collaborative', 'playlist-read-private', 'user-follow-read', 'user-library-read', 'user-read-currently-playing', 'user-read-email', 'user-read-playback-position', 'user-read-playback-state', 'user-read-private', 'user-read-recently-played', 'user-top-read'})
streaming = 'streaming'
ugc_image_upload = 'ugc-image-upload'
user_follow_modify = 'user-follow-modify'
user_follow_read = 'user-follow-read'
user_library_modify = 'user-library-modify'
user_library_read = 'user-library-read'
user_modify_playback_state = 'user-modify-playback-state'
user_read_currently_playing = 'user-read-currently-playing'
user_read_email = 'user-read-email'
user_read_playback_position = 'user-read-playback-position'
user_read_playback_state = 'user-read-playback-state'
user_read_private = 'user-read-private'
user_read_recently_played = 'user-read-recently-played'
user_top_read = 'user-top-read'
write = frozenset({'playlist-modify-private', 'playlist-modify-public', 'ugc-image-upload', 'user-follow-modify', 'user-library-modify', 'user-modify-playback-state'})
class tekore.Scope(*members)

Bases: frozenset

Set of scopes for a token.

Instantiated with an unpacked list of strings or scopes.

Also supports flexible addition and subtraction from both sides with strings, scopes and other Scope objects. Addition is a set-like union, subtraction is a set-like relative complement. If any operation is unsuccessful, NotImplementedError is raised.

waldo = tk.scopes.user_follow_read + sally + elise - 'user-read-email'

The string representation of a Scope is a sorted, space-separated concatenation of its members.

s = tk.Scope('b', 'c', 'a')
print(s)  # -> 'a b c'

Construct a new set of scopes.

Parameters:

members – unpacked list of members of the new scope

__add__(other)

Combine two sets of scopes.

Return type:

Scope

static __new__(cls, *members)

Construct a new set of scopes.

Parameters:

members – unpacked list of members of the new scope

__radd__(other)

Combine two sets of scopes.

Return type:

Scope

__repr__()

Readable representation.

__rsub__(other)

Remove scopes from a set.

Return type:

Scope

__str__()

Join members with spaces.

__sub__(other)

Remove scopes from a set.

Return type:

Scope

Utilities

Authorisation utilities.

Note

These utilities are meant to get users up and running quickly. Consider implementing authorisation procedures that suit your needs specifically. See Authenticating server for more details.

request_client_token

Request for client credentials.

prompt_for_user_token

Prompt for manual authorisation.

refresh_user_token

Request a refreshed user token.

prompt_for_pkce_token

Prompt for manual authorisation with PKCE.

refresh_pkce_token

Request a refreshed PKCE user token.

UserAuth

Implement user authorisation flow.

gen_state

Generate state to use in user authorisation.

parse_code_from_url

Parse an URL for parameter 'code'.

parse_state_from_url

Parse an URL for parameter 'state'.

tekore.request_client_token(client_id, client_secret)

Request for client credentials.

Parameters:
  • client_id (str) – client ID

  • client_secret (str) – client secret

Returns:

automatically refreshing client token

Return type:

RefreshingToken

tekore.prompt_for_user_token(client_id, client_secret, redirect_uri, scope=None, open_browser=True)

Prompt for manual authorisation.

Open a web browser for the user to log in with Spotify. Prompt to paste the URL after logging in to complete authorisation.

Parameters:
  • client_id (str) – client ID

  • client_secret (str) – client secret

  • redirect_uri (str) – whitelisted redirect URI

  • scope – token privileges, accepts a Scope, a single scope, a list of scopes and strings for Scope, or a space-separated list of scopes as a string

  • open_browser (bool) – open a web browser with auth url, or just print it

Returns:

automatically refreshing user token

Return type:

RefreshingToken

Raises:

AssertionError – if state is inconsistent

tekore.refresh_user_token(client_id, client_secret, refresh_token)

Request a refreshed user token.

Parameters:
  • client_id (str) – client ID

  • client_secret (str) – client secret

  • refresh_token (str) – refresh token

Returns:

automatically refreshing user token

Return type:

RefreshingToken

tekore.prompt_for_pkce_token(client_id, redirect_uri, scope=None, open_browser=True)

Prompt for manual authorisation with PKCE.

Open a web browser for the user to log in with Spotify. Prompt to paste the URL after logging in to complete authorisation.

Parameters:
  • client_id (str) – client ID

  • redirect_uri (str) – whitelisted redirect URI

  • scope – token privileges, accepts a Scope, a single scope, a list of scopes and strings for Scope, or a space-separated list of scopes as a string

  • open_browser (bool) – open a web browser with auth url, or just print it

Returns:

automatically refreshing PKCE user token

Return type:

RefreshingToken

Raises:

AssertionError – if state is inconsistent

tekore.refresh_pkce_token(client_id, refresh_token)

Request a refreshed PKCE user token.

Parameters:
  • client_id (str) – client ID

  • refresh_token (str) – refresh token

Returns:

automatically refreshing user token

Return type:

RefreshingToken

class tekore.UserAuth(cred, scope=None, pkce=False)

Bases: object

Implement user authorisation flow.

Implements all steps and security checks for user authorisation. The responsibility of the caller is to redirect a user to the given URL and provide the resulting redirect URI or its parameters. Can be used with an asynchronous credentials client.

Parameters:
url

address to redirect a user to for authorisation

Type:

str

state

generated additional state

Type:

str

verifier

PKCE code verifier, None if PKCE is not used

Type:

str

Examples

auth = tk.UserAuth(cred, scope)

# Redirect user to auth.url and parse parameters
code, state = ...
token = auth.request_token(code, state)

# Or leave parsing to UserAuth
redirected = ...
token = auth.request_token(url=redirected)

# With an asynchronous client
token = await auth.request_token(url=redirected)
request_token(code=None, state=None, url=None)

Verify state consistency and request token.

Parameters:
  • code (str) – code from redirect parameters, required if url was not specified

  • state (str) – state from redirect parameters, required if url was not specified

  • url (str) – if specified, code and state are parsed from this URL instead

Returns:

access token

Return type:

Union[Token, RefreshingToken]

Raises:

AssertionError – if state is inconsistent

tekore.gen_state(n_bytes=32)

Generate state to use in user authorisation.

The generated state is random and URL-safe. It is generated using secrets.token_urlsafe().

Parameters:

n_bytes (int) –

Return type:

str

tekore.parse_code_from_url(url)

Parse an URL for parameter ‘code’.

Returns:

value of ‘code’

Return type:

str

Raises:

KeyError – if ‘code’ is not available or has multiple values

Parameters:

url (str) –

tekore.parse_state_from_url(url)

Parse an URL for parameter ‘state’.

Returns:

value of ‘state’

Return type:

str

Raises:

KeyError – if ‘state’ is not available or has multiple values

Parameters:

url (str) –