From 2ae0ec8c524bffc321a30dacd5dafd7f2b8f4f61 Mon Sep 17 00:00:00 2001 From: Samuel Gulliksson Date: Fri, 18 Oct 2019 14:55:03 +0200 Subject: [PATCH] Update documentation (#61) * Setup Sphinx (for ReadTheDocs). * Restructure documentation (move from README to separate files). --- .gitignore | 3 + .readthedocs.yml | 9 + README.md | 198 +-------------------- docs/Makefile | 20 +++ docs/api.rst | 27 +++ docs/conf.py | 58 ++++++ docs/configuration.md | 101 +++++++++++ docs/index.rst | 18 ++ docs/make.bat | 35 ++++ docs/quickstart.md | 92 ++++++++++ src/flask_pyoidc/flask_pyoidc.py | 27 ++- src/flask_pyoidc/provider_configuration.py | 2 +- 12 files changed, 380 insertions(+), 210 deletions(-) create mode 100644 .readthedocs.yml create mode 100644 docs/Makefile create mode 100644 docs/api.rst create mode 100644 docs/conf.py create mode 100644 docs/configuration.md create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 docs/quickstart.md diff --git a/.gitignore b/.gitignore index 4cc1ff1..d990912 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ dist/ coverage.xml .pytest_cache .venv/ +docs/_build +docs/_static +docs/_templates diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..5a0c369 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,9 @@ +version: 2 + +sphinx: + configuration: docs/conf.py + +python: + install: + - method: pip + path: . diff --git a/README.md b/README.md index 3dec357..944f156 100644 --- a/README.md +++ b/README.md @@ -10,198 +10,6 @@ This Flask extension provides simple OpenID Connect authentication, backed by [p ["Implicit Flow"](https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth) and ["Hybrid Flow"](https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth), is supported. -## Example - -Have a look at the [example Flask app](example/app.py) for a full example of how to use this extension. - -## Configuration - -### Provider and client configuration - -Both static and dynamic provider configuration discovery, as well as static -and dynamic client registration, is supported. The different modes of provider configuration can be combined with any -of the client registration modes. - -#### Dynamic provider configuration - -To use a provider which supports dynamic discovery it suffices to specify the issuer URL: -```python -from flask_pyoidc.provider_configuration import ProviderConfiguration - -config = ProviderConfiguration(issuer='https://op.example.com', [client configuration]) -``` - -#### Static provider configuration - -To use a provider not supporting dynamic discovery, the static provider metadata can be specified: -```python -from flask_pyoidc.provider_configuration import ProviderConfiguration, ProviderMetadata - -provider_metadata = ProviderMetadata(issuer='https://op.example.com', - authorization_endpoint='https://op.example.com/auth', - jwks_uri='https://op.example.com/jwks') -config = ProviderConfiguration(provider_metadata=provider_metadata, [client configuration]) -``` - -See the OpenID Connect specification for more information about the -[provider metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). - -#### Customizing authentication request parameters -To customize the [authentication request parameters](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest), -use `auth_request_params` in `ProviderConfiguration`: -```python -auth_params = {'scope': ['openid', 'profile']} # specify the scope to request -config = ProviderConfiguration([provider/client config], auth_request_params=auth_params) -``` - -#### Static client registration - -If you have already registered a client with the provider, specify the client credentials directly: -```python -from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientMetadata - -client_metadata = ClientMetadata(client_id='cl41ekfb9j', client_secret='m1C659wLipXfUUR50jlZ') -config = ProviderConfiguration([provider configuration], client_metadata=client_metadata) -``` - -**Note: The redirect URIs registered with the provider MUST include `/redirect_uri`, -where `` is the URL of the Flask application.** -To configure this extension to use a different endpoint, set the -[`OIDC_REDIRECT_ENDPOINT` configuration parameter](#flask-configuration). - -#### Dynamic client registration - -To dynamically register a new client for your application, the required client registration info can be specified: - -```python -from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientRegistrationInfo - -client_registration_info = ClientRegistrationInfo(client_name='Test App', contacts=['dev@rp.example.com']) -config = ProviderConfiguration([provider configuration], client_registration_info=client_registration_info) -``` - -### Flask configuration - -The application using this extension **MUST** set the following -[builtin configuration values of Flask](http://flask.pocoo.org/docs/config/#builtin-configuration-values): - -* `SERVER_NAME`: **MUST** be the same as `` if using static client registration. -* `SECRET_KEY`: This extension relies on [Flask sessions](http://flask.pocoo.org/docs/quickstart/#sessions), which - requires `SECRET_KEY`. - -You may also configure the way the user sessions created by this extension are handled: - -* `OIDC_SESSION_PERMANENT`: If set to `True` (which is the default) the user session will be kept until the configured - session lifetime (see below). If set to `False` the session will be deleted when the user closes the browser. -* `OIDC_REDIRECT_ENDPOINT`: Set the endpoint used as redirect_uri to receive authentication responses. Defaults to - `redirect_uri`, meaning the URL `/redirect_uri` needs to be registered with the provider(s). -* `PERMANENT_SESSION_LIFETIME`: Control how long a user session is valid, see - [Flask documentation](http://flask.pocoo.org/docs/1.0/config/#PERMANENT_SESSION_LIFETIME) for more information. - -### Session refresh - -If your provider supports the `prompt=none` authentication request parameter, this extension can automatically refresh -user sessions. This ensures that the user attributes (OIDC claims, user being active, etc.) are kept up-to-date without -having to log the user out and back in. To enable and configure the feature, specify the interval (in seconds) between -refreshes: -```python -from flask_pyoidc.provider_configuration import ProviderConfiguration - -config = ProviderConfiguration(session_refresh_interval_seconds=1800, [provider/client config] -``` - -**Note: The user will still be logged out when the session expires (as described above).** - -## Protect an endpoint by authentication - -To add authentication to one of your endpoints use the `oidc_auth` decorator: -```python -import flask -from flask import Flask, jsonify - -from flask_pyoidc import OIDCAuthentication -from flask_pyoidc.provider_configuration import ProviderConfiguration -from flask_pyoidc.user_session import UserSession - -app = Flask(__name__) -config = ProviderConfiguration(...) -auth = OIDCAuthentication({'default': config}, app) - -@app.route('/login') -@auth.oidc_auth('default') -def index(): - user_session = UserSession(flask.session) - return jsonify(access_token=user_session.access_token, - id_token=user_session.id_token, - userinfo=user_session.userinfo) -``` - -After a successful login, this extension will place three things in the user session (if they are received from the -provider): -* [ID Token](http://openid.net/specs/openid-connect-core-1_0.html#IDToken) -* [Access Token](http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse) -* [Userinfo Response](http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse) - -### Using multiple providers - -To allow users to login with multiple different providers, configure all of them in the `OIDCAuthentication` -constructor and specify which one to use by name for each endpoint: -```python -from flask_pyoidc import OIDCAuthentication -from flask_pyoidc.provider_configuration import ProviderConfiguration - -app = Flask(__name__) -auth = OIDCAuthentication({'provider1': ProviderConfiguration(...), 'provider2': ProviderConfiguration(...)}, app) - -@app.route('/login1') -@auth.oidc_auth('provider1') -def login1(): - pass - -@app.route('/login2') -@auth.oidc_auth('provider2') -def login2(): - pass -``` - - -## User logout - -To support user logout, use the `oidc_logout` decorator: -```python -@app.route('/logout') -@auth.oidc_logout -def logout(): - return 'You\'ve been successfully logged out!' -``` - -If the logout view is mounted under a custom endpoint (other than the default, which is -[the name of the view function](http://flask.pocoo.org/docs/1.0/api/#flask.Flask.route)), or if using Blueprints, you -must specify the full URL in the Flask-pyoidc configuration using `post_logout_redirect_uris`: -```python -ClientMetadata(..., post_logout_redirect_uris=['https://example.com/post_logout']) # if using static client registration -ClientRegistrationInfo(..., post_logout_redirect_uris=['https://example.com/post_logout']) # if using dynamic client registration -``` - -This extension also supports [RP-Initiated Logout](http://openid.net/specs/openid-connect-session-1_0.html#RPLogout), -if the provider allows it. Make sure the `end_session_endpoint` is defined in the provider metadata to enable notifying -the provider when the user logs out. - -## Specify the error view - -If an OAuth error response is received, either in the authentication or token response, it will be passed to the -"error view", specified using the `error_view` decorator: - -```python -from flask import jsonify - -@auth.error_view -def error(error=None, error_description=None): - return jsonify({'error': error, 'message': error_description}) -``` - -The function specified as the error view MUST accept two parameters, `error` and `error_description`, which corresponds -to the [OIDC error parameters](http://openid.net/specs/openid-connect-core-1_0.html#AuthError), and return the content -that should be displayed to the user. - -If no error view is specified, a generic error message will be displayed to the user. +## Getting started +Read [the documentation](https://flask-pyoidc.readthedocs.io/) or have a look at the +[example Flask app](example/app.py) for a full example of how to use this extension. diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..bca9f6a --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,27 @@ +.. _api: + +API +=== + +Flask-pyoidc extension +---------------------- +.. autoclass:: flask_pyoidc.OIDCAuthentication + :members: + +Configuration +------------- +.. automodule:: flask_pyoidc.provider_configuration + :members: + +User session handling +--------------------- +.. automodule:: flask_pyoidc.user_session + :members: + +Internals +--------- +.. automodule:: flask_pyoidc.auth_response_handler + :members: + +.. automodule:: flask_pyoidc.pyoidc_facade + :members: diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..0b54d03 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,58 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +import os +import sys +sys.path.insert(0, os.path.abspath('..')) + + +# -- Project information ----------------------------------------------------- + +project = 'flask-pyoidc' +copyright = '2019, Samuel Gulliksson' +author = 'Samuel Gulliksson' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'recommonmark' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +autoclass_content = 'both' +master_doc = 'index' + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'default' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..966193f --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,101 @@ +# Configuration + +## Provider and client configuration + +Both static and dynamic provider configuration discovery, as well as static +and dynamic client registration, is supported. The different modes of provider configuration can be combined with any +of the client registration modes. + +### Provider configuration + +#### Dynamic provider configuration + +To use a provider which supports dynamic discovery it suffices to specify the issuer URL: +```python +from flask_pyoidc.provider_configuration import ProviderConfiguration + +config = ProviderConfiguration(issuer='https://op.example.com', [client configuration]) +``` + +#### Static provider configuration + +To use a provider not supporting dynamic discovery, the static provider metadata can be specified: +```python +from flask_pyoidc.provider_configuration import ProviderConfiguration, ProviderMetadata + +provider_metadata = ProviderMetadata(issuer='https://op.example.com', + authorization_endpoint='https://op.example.com/auth', + jwks_uri='https://op.example.com/jwks') +config = ProviderConfiguration(provider_metadata=provider_metadata, [client configuration]) +``` + +See the OpenID Connect specification for more information about the +[provider metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata). + +#### Customizing authentication request parameters +To customize the [authentication request parameters](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest), +use `auth_request_params` in `ProviderConfiguration`: +```python +auth_params = {'scope': ['openid', 'profile']} # specify the scope to request +config = ProviderConfiguration([provider/client config], auth_request_params=auth_params) +``` + +#### Session refresh + +If your provider supports the `prompt=none` authentication request parameter, this extension can automatically refresh +user sessions. This ensures that the user attributes (OIDC claims, user being active, etc.) are kept up-to-date without +having to log the user out and back in. To enable and configure the feature, specify the interval (in seconds) between +refreshes: +```python +from flask_pyoidc.provider_configuration import ProviderConfiguration + +config = ProviderConfiguration(session_refresh_interval_seconds=1800, [provider/client config]) +``` + +**Note: The user will still be logged out when the session expires (as set in the Flask session configuration).** + +### Client configuration + +#### Static client registration + +If you have already registered a client with the provider, specify the client credentials directly: +```python +from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientMetadata + +client_metadata = ClientMetadata(client_id='cl41ekfb9j', client_secret='m1C659wLipXfUUR50jlZ') +config = ProviderConfiguration([provider configuration], client_metadata=client_metadata) +``` + +**Note: The redirect URIs registered with the provider MUST include `/redirect_uri`, +where `` is the URL of the Flask application.** +To configure this extension to use a different endpoint, set the +[`OIDC_REDIRECT_ENDPOINT` configuration parameter](#flask-configuration). + +#### Dynamic client registration + +To dynamically register a new client for your application, the required client registration info can be specified: + +```python +from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientRegistrationInfo + +client_registration_info = ClientRegistrationInfo(client_name='Test App', contacts=['dev@rp.example.com']) +config = ProviderConfiguration([provider configuration], client_registration_info=client_registration_info) +``` + +## Flask configuration + +The application using this extension **MUST** set the following +[builtin configuration values of Flask](http://flask.pocoo.org/docs/config/#builtin-configuration-values): + +* `SERVER_NAME`: **MUST** be the same as `` if using static client registration. +* `SECRET_KEY`: This extension relies on [Flask sessions](http://flask.pocoo.org/docs/quickstart/#sessions), which + requires `SECRET_KEY`. + +You may also configure the way the user sessions created by this extension are handled: + +* `OIDC_SESSION_PERMANENT`: If set to `True` (which is the default) the user session will be kept until the configured + session lifetime (see below). If set to `False` the session will be deleted when the user closes the browser. +* `OIDC_REDIRECT_ENDPOINT`: Set the endpoint used as redirect_uri to receive authentication responses. Defaults to + `redirect_uri`, meaning the URL `/redirect_uri` needs to be registered with the provider(s). +* `PERMANENT_SESSION_LIFETIME`: Control how long a user session is valid, see + [Flask documentation](http://flask.pocoo.org/docs/1.0/config/#PERMANENT_SESSION_LIFETIME) for more information. diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..ca3c7be --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,18 @@ +Welcome to flask-pyoidc's documentation! +======================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + quickstart + configuration + api + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..2119f51 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..f339b0d --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,92 @@ +# Quickstart + +To add authentication to one of your endpoints use the `oidc_auth` decorator: +```python +import flask +from flask import Flask, jsonify + +from flask_pyoidc import OIDCAuthentication +from flask_pyoidc.provider_configuration import ProviderConfiguration +from flask_pyoidc.user_session import UserSession + +app = Flask(__name__) +config = ProviderConfiguration(...) +auth = OIDCAuthentication({'default': config}, app) + +@app.route('/login') +@auth.oidc_auth('default') +def index(): + user_session = UserSession(flask.session) + return jsonify(access_token=user_session.access_token, + id_token=user_session.id_token, + userinfo=user_session.userinfo) +``` + +After a successful login, this extension will place three things in the user session (if they are received from the +provider): +* [ID Token](http://openid.net/specs/openid-connect-core-1_0.html#IDToken) +* [Access Token](http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse) +* [Userinfo Response](http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse) + +## Using multiple providers + +To allow users to login with multiple different providers, configure all of them in the `OIDCAuthentication` +constructor and specify which one to use by name for each endpoint: +```python +from flask_pyoidc import OIDCAuthentication +from flask_pyoidc.provider_configuration import ProviderConfiguration + +app = Flask(__name__) +auth = OIDCAuthentication({'provider1': ProviderConfiguration(...), 'provider2': ProviderConfiguration(...)}, app) + +@app.route('/login1') +@auth.oidc_auth('provider1') +def login1(): + pass + +@app.route('/login2') +@auth.oidc_auth('provider2') +def login2(): + pass +``` + +## User logout + +To support user logout, use the `oidc_logout` decorator: +```python +@app.route('/logout') +@auth.oidc_logout +def logout(): + return 'You\'ve been successfully logged out!' +``` + +If the logout view is mounted under a custom endpoint (other than the default, which is +[the name of the view function](http://flask.pocoo.org/docs/1.0/api/#flask.Flask.route)), or if using Blueprints, you +must specify the full URL in the Flask-pyoidc configuration using `post_logout_redirect_uris`: +```python +ClientMetadata(..., post_logout_redirect_uris=['https://example.com/post_logout']) # if using static client registration +ClientRegistrationInfo(..., post_logout_redirect_uris=['https://example.com/post_logout']) # if using dynamic client registration +``` + +This extension also supports [RP-Initiated Logout](http://openid.net/specs/openid-connect-session-1_0.html#RPLogout), +if the provider allows it. Make sure the `end_session_endpoint` is defined in the provider metadata to enable notifying +the provider when the user logs out. + +## Specify the error view + +If an OAuth error response is received, either in the authentication or token response, it will be passed to the +"error view", specified using the `error_view` decorator: + +```python +from flask import jsonify + +@auth.error_view +def error(error=None, error_description=None): + return jsonify({'error': error, 'message': error_description}) +``` + +The function specified as the error view MUST accept two parameters, `error` and `error_description`, which corresponds +to the [OIDC error parameters](http://openid.net/specs/openid-connect-core-1_0.html#AuthError), and return the content +that should be displayed to the user. + +If no error view is specified, a generic error message will be displayed to the user. diff --git a/src/flask_pyoidc/flask_pyoidc.py b/src/flask_pyoidc/flask_pyoidc.py index 94f55bf..54aaa9b 100644 --- a/src/flask_pyoidc/flask_pyoidc.py +++ b/src/flask_pyoidc/flask_pyoidc.py @@ -1,18 +1,17 @@ -""" - Copyright 2018 Samuel Gulliksson +# Copyright 2018 Samuel Gulliksson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -""" import functools import json @@ -42,7 +41,7 @@ class OIDCAuthentication: def __init__(self, provider_configurations, app=None): """ Args: - provider_configurations (Mapping[str, flask_pyoidc.provider_configuration.ProviderConfiguration]): + provider_configurations (Mapping[str, ProviderConfiguration]): provider configurations by name app (flask.app.Flask): optional Flask app """ diff --git a/src/flask_pyoidc/provider_configuration.py b/src/flask_pyoidc/provider_configuration.py index 0598098..d1a39a8 100644 --- a/src/flask_pyoidc/provider_configuration.py +++ b/src/flask_pyoidc/provider_configuration.py @@ -72,7 +72,7 @@ def __init__(self, client_id=None, client_secret=None, **kwargs): class ProviderConfiguration: """ - Metadata for communicating with a OpenID Connect Provider (OP). + Metadata for communicating with an OpenID Connect Provider (OP). Attributes: auth_request_params (dict): Extra parameters, as key-value pairs, to include in the query parameters