Client Class

This is the main API for oauth2 client.

Its methods define and document parameters mentioned in OAUTH2 RFC 6749.

Inheritance
Client

Constructor

Client(server_configuration, client_id, on_obtaining_tokens=<function Client.<lambda>>, on_removing_rt=<function Client.<lambda>>, on_updating_rt=<function Client.<lambda>>, **kwargs)

Parameters

server_configuration
client_id
on_obtaining_tokens
default value: lambda event: None
on_removing_rt
default value: lambda token_item: None
on_updating_rt
default value: lambda token_item, new_rt: None

Methods

build_auth_request_uri

Generate an authorization uri to be visited by resource owner.

Parameters are the same as another method initiate_auth_code_flow, whose functionality is a superset of this method.

initiate_auth_code_flow

Initiate an auth code flow.

Later when the response reaches your redirect_uri, you can use obtain_token_by_auth_code_flow to complete the authentication/authorization.

This method also provides PKCE protection automatically.

initiate_device_flow

Initiate a device flow.

Returns the data defined in Device Flow specs. https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.2

You should then orchestrate the User Interaction as defined in here https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.3

And possibly here https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.3.1

obtain_token_by_assertion

This method implements Assertion Framework for OAuth2 (RFC 7521). See details at https://tools.ietf.org/html/rfc7521#section-4.1

obtain_token_by_auth_code_flow

With the auth_response being redirected back, validate it against auth_code_flow, and then obtain tokens.

Internally, it implements PKCE to mitigate the auth code interception attack.

obtain_token_by_authorization_code

Get a token via authorization code. a.k.a. Authorization Code Grant.

This is typically used by a server-side app (Confidential Client), but it can also be used by a device-side native app (Public Client). See more detail at https://tools.ietf.org/html/rfc6749#section-4.1.3

You are encouraged to use its higher level method obtain_token_by_auth_code_flow instead.

obtain_token_by_browser

A native app can use this method to obtain token via a local browser.

Internally, it implements PKCE to mitigate the auth code interception attack.

obtain_token_by_device_flow

Obtain token by a device flow object, with customizable polling effect.

obtain_token_by_refresh_token

This is an overload which will trigger token storage callbacks.

obtain_token_by_username_password

The Resource Owner Password Credentials Grant, used by legacy app.

obtain_token_for_client

Obtain token for this client (rather than for an end user), a.k.a. the Client Credentials Grant, used by Backend Applications.

We don't name it obtain_token_by_client_credentials(...) because those credentials are typically already provided in class constructor, not here. You can still explicitly provide an optional client_secret parameter, or you can provide such extra parameters as default_body during the class initialization.

parse_auth_response

Parse the authorization response being redirected back.

build_auth_request_uri

Generate an authorization uri to be visited by resource owner.

Parameters are the same as another method initiate_auth_code_flow, whose functionality is a superset of this method.

build_auth_request_uri(response_type, redirect_uri=None, scope=None, state=None, **kwargs)

Parameters

response_type
Required
redirect_uri
default value: None
scope
default value: None
state
default value: None

Returns

The auth uri as a string.

initiate_auth_code_flow

Initiate an auth code flow.

Later when the response reaches your redirect_uri, you can use obtain_token_by_auth_code_flow to complete the authentication/authorization.

This method also provides PKCE protection automatically.

initiate_auth_code_flow(scope=None, redirect_uri=None, state=None, **kwargs)

Parameters

scope
list
default value: None

It is a list of case-sensitive strings. Some ID provider can accept empty string to represent default scope.

redirect_uri
str
default value: None

Optional. If not specified, server will use the pre-registered one.

state
str
default value: None

An opaque value used by the client to maintain state between the request and callback. If absent, this library will automatically generate one internally.

kwargs
Required

Other parameters, typically defined in OpenID Connect.

Returns

The auth code flow. It is a dict in this form:


   {
       "auth_uri": "https://...",  // Guide user to visit this
       "state": "...",  // You may choose to verify it by yourself,
                        // or just let obtain_token_by_auth_code_flow()
                        // do that for you.
       "...": "...",  // Everything else are reserved and internal
   }

The caller is expected to:

  1. somehow store this content, typically inside the current session,

  2. guide the end user (i.e. resource owner) to visit that auth_uri,

  3. and then relay this dict and subsequent auth response to obtain_token_by_auth_code_flow.

initiate_device_flow

Initiate a device flow.

Returns the data defined in Device Flow specs. https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.2

You should then orchestrate the User Interaction as defined in here https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.3

And possibly here https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12#section-3.3.1

initiate_device_flow(scope: Optional[list] = None, **kwargs: dict) -> dict

Parameters

scope
default value: None

obtain_token_by_assertion

This method implements Assertion Framework for OAuth2 (RFC 7521). See details at https://tools.ietf.org/html/rfc7521#section-4.1

obtain_token_by_assertion()

Parameters

assertion
Required

The assertion bytes can be a raw SAML2 assertion, or a JWT assertion.

grant_type
Required

It is typically either the value of GRANT_TYPE_SAML2, or GRANT_TYPE_JWT, the only two profiles defined in RFC 7521.

scope
default value: None

Optional. It must be a subset of previously granted scopes.

obtain_token_by_auth_code_flow

With the auth_response being redirected back, validate it against auth_code_flow, and then obtain tokens.

Internally, it implements PKCE to mitigate the auth code interception attack.

obtain_token_by_auth_code_flow(auth_code_flow, auth_response, scope=None, **kwargs)

Parameters

auth_code_flow
dict
Required

The same dict returned by initiate_auth_code_flow.

auth_response
dict
Required

A dict based on query string received from auth server.

scope
<xref:collections.Iterable>[str]
default value: None

You don't usually need to use scope parameter here. Some Identity Provider allows you to provide a subset of what you specified during initiate_auth_code_flow.

Returns

  • A dict containing "access_token" and/or "id_token", among others, depends on what scope was used. (See https://tools.ietf.org/html/rfc6749#section-5.1)

  • A dict containing "error", optionally "error_description", "error_uri". (It is either this or that

  • Most client-side data error would result in ValueError exception. So the usage pattern could be without any protocol details:

    
       def authorize():  # A controller in a web app
           try:
               result = client.obtain_token_by_auth_code_flow(
                   session.get("flow", {}), auth_resp)
               if "error" in result:
                   return render_template("error.html", result)
               store_tokens()
           except ValueError:  # Usually caused by CSRF
               pass  # Simply ignore them
           return redirect(url_for("index"))
    

obtain_token_by_authorization_code

Get a token via authorization code. a.k.a. Authorization Code Grant.

This is typically used by a server-side app (Confidential Client), but it can also be used by a device-side native app (Public Client). See more detail at https://tools.ietf.org/html/rfc6749#section-4.1.3

You are encouraged to use its higher level method obtain_token_by_auth_code_flow instead.

obtain_token_by_authorization_code(code, redirect_uri=None, scope=None, **kwargs)

Parameters

code
Required

The authorization code received from authorization server.

redirect_uri
default value: None

Required, if the "redirect_uri" parameter was included in the authorization request, and their values MUST be identical.

scope
default value: None

It is both unnecessary and harmless to use scope here, per RFC 6749. We suggest to use the same scope already used in auth request uri, so that this library can link the obtained tokens with their scope.

obtain_token_by_browser

A native app can use this method to obtain token via a local browser.

Internally, it implements PKCE to mitigate the auth code interception attack.

obtain_token_by_browser(redirect_uri=None, auth_code_receiver=None, **kwargs)

Parameters

scope
<xref:collections.Iterable>[str]
default value: None

A list of scopes that you would like to obtain token for.

extra_scope_to_consent
default value: None

Some IdP allows you to include more scopes for end user to consent. The access token returned by this method will NOT include those scopes, but the refresh token would record those extra consent, so that your future obtain_token_by_refresh_token call would be able to obtain token for those additional scopes, silently.

redirect_uri
string
Required

The redirect_uri to be sent via auth request to Identity Provider (IdP), to indicate where an auth response would come back to. Such as http://127.0.0.1:0 (default) or http://localhost:1234.

If port 0 is specified, this method will choose a system-allocated port, then the actual redirect_uri will contain that port. To use this behavior, your IdP would need to accept such dynamic port.

Per HTTP convention, if port number is absent, it would mean port 80, although you probably want to specify port 0 in this context.

auth_params
dict
Required

These parameters will be sent to authorization_endpoint.

timeout
int
Required

In seconds. None means wait indefinitely.

browser_name
str
Required

If you did webbrowser.register("xyz", None, BackgroundBrowser("/path/to/browser")) beforehand, you can pass in the name "xyz" to use that browser. The default value None means using default browser, which is customizable by env var $BROWSER.

Returns

Same as obtain_token_by_auth_code_flow

obtain_token_by_device_flow

Obtain token by a device flow object, with customizable polling effect.

obtain_token_by_device_flow()

Parameters

flow
dict
Required

An object previously generated by initiate_device_flow(...). Its content WILL BE CHANGED by this method during each run. We share this object with you, so that you could implement your own loop, should you choose to do so.

exit_condition
<xref:Callable>
default value: lambda flow: flow.get("expires_at", 0) < time.time()

This method implements a loop to provide polling effect. The loop's exit condition is calculated by this callback.

The default callback makes the loop run until the flow expires. Therefore, one of the ways to exit the polling early, is to change the flow["expires_at"] to a small number such as 0.

In case you are doing async programming, you may want to completely turn off the loop. You can do so by using a callback as:

exit_condition = lambda flow: True

to make the loop run only once, i.e. no polling, hence non-block.

obtain_token_by_refresh_token

This is an overload which will trigger token storage callbacks.

obtain_token_by_refresh_token()

Parameters

token_item
Required

A refresh token (RT) item, in flexible format. It can be a string, or a whatever data structure containing RT string and its metadata, in such case the rt_getter callable must be able to extract the RT string out from the token item data structure.

Either way, this token_item will be passed into other callbacks as-is.

scope
default value: None

If omitted, is treated as equal to the scope originally granted by the resource owner, according to https://tools.ietf.org/html/rfc6749#section-6

rt_getter
default value: lambda token_item: token_item["refresh_token"]

A callable to translate the token_item to a raw RT string

on_removing_rt
default value: None

If absent, fall back to the one defined in initialization

on_updating_rt
default value: None

Default to None, it will fall back to the one defined in initialization. This is the most common case.

As a special case, you can pass in a False, then this function will NOT trigger on_updating_rt() for RT UPDATE, instead it will allow the RT to be added by on_obtaining_tokens(). This behavior is useful when you are migrating RTs from elsewhere into a token storage managed by this library.

obtain_token_by_username_password

The Resource Owner Password Credentials Grant, used by legacy app.

obtain_token_by_username_password(username, password, scope=None, **kwargs)

Parameters

username
Required
password
Required
scope
default value: None

obtain_token_for_client

Obtain token for this client (rather than for an end user), a.k.a. the Client Credentials Grant, used by Backend Applications.

We don't name it obtain_token_by_client_credentials(...) because those credentials are typically already provided in class constructor, not here. You can still explicitly provide an optional client_secret parameter, or you can provide such extra parameters as default_body during the class initialization.

obtain_token_for_client(scope=None, **kwargs)

Parameters

scope
default value: None

parse_auth_response

Parse the authorization response being redirected back.

static parse_auth_response(params, state=None)

Parameters

params
Required

A string or dict of the query string

state
default value: None

REQUIRED if the state parameter was present in the client authorization request. This function will compare it with response.

Attributes

DEVICE_FLOW

DEVICE_FLOW = {'DEVICE_CODE': 'device_code', 'GRANT_TYPE': 'urn:ietf:params:oauth:grant-type:device_code'}

DEVICE_FLOW_RETRIABLE_ERRORS

DEVICE_FLOW_RETRIABLE_ERRORS = ('authorization_pending', 'slow_down')

GRANT_TYPE_JWT

GRANT_TYPE_JWT = 'urn:ietf:params:oauth:grant-type:jwt-bearer'

GRANT_TYPE_SAML2

GRANT_TYPE_SAML2 = 'urn:ietf:params:oauth:grant-type:saml2-bearer'

grant_assertion_encoders

grant_assertion_encoders = {'urn:ietf:params:oauth:grant-type:saml2-bearer': <function BaseClient.encode_saml_assertion>}