From b41b30934d01ef605c6261e4f26f56de94b060d7 Mon Sep 17 00:00:00 2001 From: frankie567 Date: Thu, 1 Feb 2024 08:18:37 +0000 Subject: [PATCH] Automated deployment: Thu Feb 1 08:18:37 UTC 2024 07f2e8a490962543ff295992fc10f2305a02fc16 --- index.html | 3 ++- search/search_index.json | 2 +- sitemap.xml.gz | Bin 127 -> 127 bytes 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 94521c8..1e2b74c 100644 --- a/index.html +++ b/index.html @@ -612,7 +612,7 @@

HTTPX OAuthcodecov PyPI version

-

All Contributors

+

All Contributors

@@ -648,6 +648,7 @@

Contributors ✨Joona Yoon
Joona Yoon

💻 LindezaGrey
LindezaGrey

💻 R. Singh
R. Singh

🐛 + Lukas Lösche
Lukas Lösche

🐛 💻 diff --git a/search/search_index.json b/search/search_index.json index 3c292d0..4d2a556 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"HTTPX OAuth","text":"

Async OAuth client using HTTPX

Documentation: https://frankie567.github.io/httpx-oauth/

Source Code: https://github.com/frankie567/httpx-oauth

"},{"location":"#installation","title":"Installation","text":"
pip install httpx-oauth\n
"},{"location":"#contributors","title":"Contributors \u2728","text":"

Thanks goes to these wonderful people (emoji key):

Fran\u00e7ois Voron\ud83d\udea7 Xavi Torell\u00f3\ud83d\udcbb dbf\ud83d\udcbb Kenton Parton\ud83d\udcbb stepan-chatalyan\ud83d\udcbb Foster Snowhill\ud83d\udcbb William Hatcher\ud83d\udcbb Matt Chan\ud83d\udce6 Goran Meki\u0107\ud83d\udce6 Joona Yoon\ud83d\udcbb LindezaGrey\ud83d\udcbb R. Singh\ud83d\udc1b

This project follows the all-contributors specification. Contributions of any kind welcome!

"},{"location":"#development","title":"Development","text":""},{"location":"#setup-environment","title":"Setup environment","text":"

We use Hatch to manage the development environment and production build. Ensure it's installed on your system.

"},{"location":"#run-unit-tests","title":"Run unit tests","text":"

You can run all the tests with:

hatch run test\n
"},{"location":"#format-the-code","title":"Format the code","text":"

Execute the following command to apply isort and black formatting:

hatch run lint\n
"},{"location":"#serve-the-documentation","title":"Serve the documentation","text":"

You can serve the documentation locally with the following command:

hatch run docs\n

The documentation will be available on http://localhost:8000.

"},{"location":"#license","title":"License","text":"

This project is licensed under the terms of the MIT license.

"},{"location":"fastapi/","title":"FastAPI","text":"

Utilities are provided to ease the integration of an OAuth2 process in FastAPI.

"},{"location":"fastapi/#oauth2authorizecallback","title":"OAuth2AuthorizeCallback","text":"

Dependency callable to handle the authorization callback. It reads the query parameters and returns the access token and the state.

Parameters

Tip

You should either set route_name, which will automatically reverse the URL, or redirect_url, which is an arbitrary URL you set.

from httpx_oauth.integrations.fastapi import OAuth2AuthorizeCallback\nfrom httpx_oauth.oauth2 import OAuth2\n\nclient = OAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", \"AUTHORIZE_ENDPOINT\", \"ACCESS_TOKEN_ENDPOINT\")\noauth2_authorize_callback = OAuth2AuthorizeCallback(client, \"oauth-callback\")\napp = FastAPI()\n\n@app.get(\"/oauth-callback\", name=\"oauth-callback\")\nasync def oauth_callback(access_token_state=Depends(oauth2_authorize_callback)):\n    token, state = access_token_state\n    # Do something useful\n
"},{"location":"oauth2/","title":"OAuth2","text":""},{"location":"oauth2/#generic-client","title":"Generic client","text":"

A generic OAuth2 class is provided to adapt to any OAuth2-compliant service. You can instantiate it like this:

from httpx_oauth.oauth2 import OAuth2\n\nclient = OAuth2(\n    \"CLIENT_ID\",\n    \"CLIENT_SECRET\",\n    \"AUTHORIZE_ENDPOINT\",\n    \"ACCESS_TOKEN_ENDPOINT\",\n    refresh_token_endpoint=\"REFRESH_TOKEN_ENDPOINT\",\n    revoke_token_endpoint=\"REVOKE_TOKEN_ENDPOINT\",\n)\n

Note that refresh_token_endpoint and revoke_token_endpoint are optional since not every services propose to refresh and revoke tokens.

"},{"location":"oauth2/#available-methods","title":"Available methods","text":""},{"location":"oauth2/#get_authorization_url","title":"get_authorization_url","text":"

Returns the authorization URL where you should redirect the user to ask for their approval.

Parameters

Example

authorization_url = await client.get_authorization_url(\n    \"https://www.tintagel.bt/oauth-callback\", scope=[\"SCOPE1\", \"SCOPE2\", \"SCOPE3\"],\n)\n
"},{"location":"oauth2/#get_access_token","title":"get_access_token","text":"

Returns an OAuth2Token object for the service given the authorization code passed in the redirection callback.

Raises a GetAccessTokenError if an error occurs.

Parameters

Example

access_token = await client.get_access_token(\"CODE\", \"https://www.tintagel.bt/oauth-callback\")\n
"},{"location":"oauth2/#refresh_token","title":"refresh_token","text":"

Returns a fresh OAuth2Token object for the service given a refresh token.

Raises a RefreshTokenNotSupportedError if no refresh_token_endpoint was provided.

Parameters

Example

access_token = await client.refresh_token(\"REFRESH_TOKEN\")\n
"},{"location":"oauth2/#revoke_token","title":"revoke_token","text":"

Revokes a token.

Raises a RevokeTokenNotSupportedError if no revoke_token_endpoint was provided.

Parameters

Example

await client.revoke_token(\"TOKEN\")\n
"},{"location":"oauth2/#get_id_email","title":"get_id_email","text":"

Returns the id and the email (if available) of the authenticated user from the API provider. It assumes you have asked for the required scopes.

Raises a GetIdEmailError if an error occurs.

Parameters

Example

user_id, user_email = await client.get_id_email(\"TOKEN\")\n
"},{"location":"oauth2/#oauth2token-class","title":"OAuth2Token class","text":"

This class is a wrapper around a standard Dict[str, Any] that bears the response of get_access_token. Properties can vary greatly from a service to another but, usually, you can get access token like this:

access_token = token[\"access_token\"]\n
"},{"location":"oauth2/#is_expired","title":"is_expired","text":"

A utility method is provided to quickly determine if the token is still valid or needs to be refreshed.

Example

if token.is_expired():\n    token = await client.refresh_token(token[\"refresh_token\"])\n    # Save token to DB\n\naccess_token = token[\"access_token\"]\n# Do something useful with this access token\n
"},{"location":"oauth2/#provided-clients","title":"Provided clients","text":"

We provide several ready-to-use clients for widely used services with configured endpoints and specificites took into account.

"},{"location":"oauth2/#openid","title":"OpenID","text":"

Generic client for providers following the OpenID Connect protocol. Besides the Client ID and the Client Secret, you'll have to provide the OpenID configuration endpoint, allowing the client to discover the required endpoints automatically. By convention, it's usually served under the path .well-known/openid-configuration.

from httpx_oauth.clients.openid import OpenID\n\nclient = OpenID(\"CLIENT_ID\", \"CLIENT_SECRET\", \"https://example.fief.dev/.well-known/openid-configuration\")\n
"},{"location":"oauth2/#discord","title":"Discord","text":"
from httpx_oauth.clients.discord import DiscordOAuth2\n\nclient = DiscordOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Warning about get_id_email

Email is optional for Discord accounts, so the email might be None.

"},{"location":"oauth2/#facebook","title":"Facebook","text":"
from httpx_oauth.clients.facebook import FacebookOAuth2\n\nclient = FacebookOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#get_long_lived_access_token","title":"get_long_lived_access_token","text":"

Returns an OAuth2Token object with a long-lived access token given a short-lived access token.

Raises a GetLongLivedAccessTokenError if an error occurs.

Parameters

Example

long_lived_access_token = await client.get_long_lived_access_token(\"TOKEN\")\n
"},{"location":"oauth2/#github","title":"GitHub","text":"
from httpx_oauth.clients.github import GitHubOAuth2\n\nclient = GitHubOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Tip

You should enable Email addresses permission in the Permissions & events section of your GitHub app parameters. You can find it at https://github.com/settings/apps/{YOUR_APP}/permissions.

"},{"location":"oauth2/#google","title":"Google","text":"
from httpx_oauth.clients.google import GoogleOAuth2\n\nclient = GoogleOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#kakao","title":"Kakao","text":"
from httpx_oauth.clients.kakao import KakaoOAuth2\n\nclient = KakaoOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#linkedin","title":"LinkedIn","text":"
from httpx_oauth.clients.linkedin import LinkedInOAuth2\n\nclient = LinkedInOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#naver","title":"NAVER","text":"
from httpx_oauth.clients.naver import NaverOAuth2\n\nclient = NaverOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#okta","title":"Okta","text":"

Based on the OpenID client. You need to provide the domain of your Okta domain for automatically discovering the required endpoints.

from httpx_oauth.clients.okta import OktaOAuth2\n\nclient = OktaOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", \"example.okta.com\")\n
"},{"location":"oauth2/#reddit","title":"Reddit","text":"
from httpx_oauth.clients.reddit import RedditOAuth2\n\nclient = RedditOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Warning about get_id_email

Reddit API never return email addresses. Thus, e-mail will always be None.

"},{"location":"oauth2/#franceconnect","title":"FranceConnect","text":"
from httpx_oauth.clients.franceconnect import FranceConnectOAuth2\n\nclient = FranceConnectOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Integration server

Since you need to go through a heavy validation process before getting your client ID and secret, you can use during development the integration server with demo credentials. You can enable this mode by setting the integration flag to True.

from httpx_oauth.clients.franceconnect import FranceConnectOAuth2\n\nclient = FranceConnectOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", integration=True)\n
"},{"location":"oauth2/#shopify","title":"Shopify","text":"

The OAuth2 client for Shopify allows you to authenticate shop owners so your app can make calls to the Shopify Admin API. Besides the Client ID and Secret, you'll need the shop subdomain of the shop you need to access.

from httpx_oauth.clients.shopify import ShopifyOAuth2\n\nclient = ShopifyOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", \"my-shop\")\n

get_id_email is based on the Shop resource

The implementation of get_id_email calls the Get Shop endpoint of the Shopify Admin API. It means that it'll return you the ID of the shop and the email of the shop owner.

"},{"location":"oauth2/#customize-httpx-client","title":"Customize HTTPX client","text":"

By default, requests are made using httpx.AsyncClient with default parameters. If you wish to customize settings, like setting timeout or proxies, you can do this by overloading the get_httpx_client method.

from typing import AsyncContextManager\n\nimport httpx\nfrom httpx_oauth.oauth2 import OAuth2\n\n\nclass OAuth2CustomTimeout(OAuth2):\n    def get_httpx_client(self) -> AsyncContextManager[httpx.AsyncClient]:\n        return httpx.AsyncClient(timeout=10.0)  # Use a default 10s timeout everywhere.\n\n\nclient = OAuth2CustomTimeout(\n    \"CLIENT_ID\",\n    \"CLIENT_SECRET\",\n    \"AUTHORIZE_ENDPOINT\",\n    \"ACCESS_TOKEN_ENDPOINT\",\n    refresh_token_endpoint=\"REFRESH_TOKEN_ENDPOINT\",\n    revoke_token_endpoint=\"REVOKE_TOKEN_ENDPOINT\",\n)\n
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"HTTPX OAuth","text":"

Async OAuth client using HTTPX

Documentation: https://frankie567.github.io/httpx-oauth/

Source Code: https://github.com/frankie567/httpx-oauth

"},{"location":"#installation","title":"Installation","text":"
pip install httpx-oauth\n
"},{"location":"#contributors","title":"Contributors \u2728","text":"

Thanks goes to these wonderful people (emoji key):

Fran\u00e7ois Voron\ud83d\udea7 Xavi Torell\u00f3\ud83d\udcbb dbf\ud83d\udcbb Kenton Parton\ud83d\udcbb stepan-chatalyan\ud83d\udcbb Foster Snowhill\ud83d\udcbb William Hatcher\ud83d\udcbb Matt Chan\ud83d\udce6 Goran Meki\u0107\ud83d\udce6 Joona Yoon\ud83d\udcbb LindezaGrey\ud83d\udcbb R. Singh\ud83d\udc1b Lukas L\u00f6sche\ud83d\udc1b \ud83d\udcbb

This project follows the all-contributors specification. Contributions of any kind welcome!

"},{"location":"#development","title":"Development","text":""},{"location":"#setup-environment","title":"Setup environment","text":"

We use Hatch to manage the development environment and production build. Ensure it's installed on your system.

"},{"location":"#run-unit-tests","title":"Run unit tests","text":"

You can run all the tests with:

hatch run test\n
"},{"location":"#format-the-code","title":"Format the code","text":"

Execute the following command to apply isort and black formatting:

hatch run lint\n
"},{"location":"#serve-the-documentation","title":"Serve the documentation","text":"

You can serve the documentation locally with the following command:

hatch run docs\n

The documentation will be available on http://localhost:8000.

"},{"location":"#license","title":"License","text":"

This project is licensed under the terms of the MIT license.

"},{"location":"fastapi/","title":"FastAPI","text":"

Utilities are provided to ease the integration of an OAuth2 process in FastAPI.

"},{"location":"fastapi/#oauth2authorizecallback","title":"OAuth2AuthorizeCallback","text":"

Dependency callable to handle the authorization callback. It reads the query parameters and returns the access token and the state.

Parameters

Tip

You should either set route_name, which will automatically reverse the URL, or redirect_url, which is an arbitrary URL you set.

from httpx_oauth.integrations.fastapi import OAuth2AuthorizeCallback\nfrom httpx_oauth.oauth2 import OAuth2\n\nclient = OAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", \"AUTHORIZE_ENDPOINT\", \"ACCESS_TOKEN_ENDPOINT\")\noauth2_authorize_callback = OAuth2AuthorizeCallback(client, \"oauth-callback\")\napp = FastAPI()\n\n@app.get(\"/oauth-callback\", name=\"oauth-callback\")\nasync def oauth_callback(access_token_state=Depends(oauth2_authorize_callback)):\n    token, state = access_token_state\n    # Do something useful\n
"},{"location":"oauth2/","title":"OAuth2","text":""},{"location":"oauth2/#generic-client","title":"Generic client","text":"

A generic OAuth2 class is provided to adapt to any OAuth2-compliant service. You can instantiate it like this:

from httpx_oauth.oauth2 import OAuth2\n\nclient = OAuth2(\n    \"CLIENT_ID\",\n    \"CLIENT_SECRET\",\n    \"AUTHORIZE_ENDPOINT\",\n    \"ACCESS_TOKEN_ENDPOINT\",\n    refresh_token_endpoint=\"REFRESH_TOKEN_ENDPOINT\",\n    revoke_token_endpoint=\"REVOKE_TOKEN_ENDPOINT\",\n)\n

Note that refresh_token_endpoint and revoke_token_endpoint are optional since not every services propose to refresh and revoke tokens.

"},{"location":"oauth2/#available-methods","title":"Available methods","text":""},{"location":"oauth2/#get_authorization_url","title":"get_authorization_url","text":"

Returns the authorization URL where you should redirect the user to ask for their approval.

Parameters

Example

authorization_url = await client.get_authorization_url(\n    \"https://www.tintagel.bt/oauth-callback\", scope=[\"SCOPE1\", \"SCOPE2\", \"SCOPE3\"],\n)\n
"},{"location":"oauth2/#get_access_token","title":"get_access_token","text":"

Returns an OAuth2Token object for the service given the authorization code passed in the redirection callback.

Raises a GetAccessTokenError if an error occurs.

Parameters

Example

access_token = await client.get_access_token(\"CODE\", \"https://www.tintagel.bt/oauth-callback\")\n
"},{"location":"oauth2/#refresh_token","title":"refresh_token","text":"

Returns a fresh OAuth2Token object for the service given a refresh token.

Raises a RefreshTokenNotSupportedError if no refresh_token_endpoint was provided.

Parameters

Example

access_token = await client.refresh_token(\"REFRESH_TOKEN\")\n
"},{"location":"oauth2/#revoke_token","title":"revoke_token","text":"

Revokes a token.

Raises a RevokeTokenNotSupportedError if no revoke_token_endpoint was provided.

Parameters

Example

await client.revoke_token(\"TOKEN\")\n
"},{"location":"oauth2/#get_id_email","title":"get_id_email","text":"

Returns the id and the email (if available) of the authenticated user from the API provider. It assumes you have asked for the required scopes.

Raises a GetIdEmailError if an error occurs.

Parameters

Example

user_id, user_email = await client.get_id_email(\"TOKEN\")\n
"},{"location":"oauth2/#oauth2token-class","title":"OAuth2Token class","text":"

This class is a wrapper around a standard Dict[str, Any] that bears the response of get_access_token. Properties can vary greatly from a service to another but, usually, you can get access token like this:

access_token = token[\"access_token\"]\n
"},{"location":"oauth2/#is_expired","title":"is_expired","text":"

A utility method is provided to quickly determine if the token is still valid or needs to be refreshed.

Example

if token.is_expired():\n    token = await client.refresh_token(token[\"refresh_token\"])\n    # Save token to DB\n\naccess_token = token[\"access_token\"]\n# Do something useful with this access token\n
"},{"location":"oauth2/#provided-clients","title":"Provided clients","text":"

We provide several ready-to-use clients for widely used services with configured endpoints and specificites took into account.

"},{"location":"oauth2/#openid","title":"OpenID","text":"

Generic client for providers following the OpenID Connect protocol. Besides the Client ID and the Client Secret, you'll have to provide the OpenID configuration endpoint, allowing the client to discover the required endpoints automatically. By convention, it's usually served under the path .well-known/openid-configuration.

from httpx_oauth.clients.openid import OpenID\n\nclient = OpenID(\"CLIENT_ID\", \"CLIENT_SECRET\", \"https://example.fief.dev/.well-known/openid-configuration\")\n
"},{"location":"oauth2/#discord","title":"Discord","text":"
from httpx_oauth.clients.discord import DiscordOAuth2\n\nclient = DiscordOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Warning about get_id_email

Email is optional for Discord accounts, so the email might be None.

"},{"location":"oauth2/#facebook","title":"Facebook","text":"
from httpx_oauth.clients.facebook import FacebookOAuth2\n\nclient = FacebookOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#get_long_lived_access_token","title":"get_long_lived_access_token","text":"

Returns an OAuth2Token object with a long-lived access token given a short-lived access token.

Raises a GetLongLivedAccessTokenError if an error occurs.

Parameters

Example

long_lived_access_token = await client.get_long_lived_access_token(\"TOKEN\")\n
"},{"location":"oauth2/#github","title":"GitHub","text":"
from httpx_oauth.clients.github import GitHubOAuth2\n\nclient = GitHubOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Tip

You should enable Email addresses permission in the Permissions & events section of your GitHub app parameters. You can find it at https://github.com/settings/apps/{YOUR_APP}/permissions.

"},{"location":"oauth2/#google","title":"Google","text":"
from httpx_oauth.clients.google import GoogleOAuth2\n\nclient = GoogleOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#kakao","title":"Kakao","text":"
from httpx_oauth.clients.kakao import KakaoOAuth2\n\nclient = KakaoOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#linkedin","title":"LinkedIn","text":"
from httpx_oauth.clients.linkedin import LinkedInOAuth2\n\nclient = LinkedInOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#naver","title":"NAVER","text":"
from httpx_oauth.clients.naver import NaverOAuth2\n\nclient = NaverOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n
"},{"location":"oauth2/#okta","title":"Okta","text":"

Based on the OpenID client. You need to provide the domain of your Okta domain for automatically discovering the required endpoints.

from httpx_oauth.clients.okta import OktaOAuth2\n\nclient = OktaOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", \"example.okta.com\")\n
"},{"location":"oauth2/#reddit","title":"Reddit","text":"
from httpx_oauth.clients.reddit import RedditOAuth2\n\nclient = RedditOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Warning about get_id_email

Reddit API never return email addresses. Thus, e-mail will always be None.

"},{"location":"oauth2/#franceconnect","title":"FranceConnect","text":"
from httpx_oauth.clients.franceconnect import FranceConnectOAuth2\n\nclient = FranceConnectOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\")\n

Integration server

Since you need to go through a heavy validation process before getting your client ID and secret, you can use during development the integration server with demo credentials. You can enable this mode by setting the integration flag to True.

from httpx_oauth.clients.franceconnect import FranceConnectOAuth2\n\nclient = FranceConnectOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", integration=True)\n
"},{"location":"oauth2/#shopify","title":"Shopify","text":"

The OAuth2 client for Shopify allows you to authenticate shop owners so your app can make calls to the Shopify Admin API. Besides the Client ID and Secret, you'll need the shop subdomain of the shop you need to access.

from httpx_oauth.clients.shopify import ShopifyOAuth2\n\nclient = ShopifyOAuth2(\"CLIENT_ID\", \"CLIENT_SECRET\", \"my-shop\")\n

get_id_email is based on the Shop resource

The implementation of get_id_email calls the Get Shop endpoint of the Shopify Admin API. It means that it'll return you the ID of the shop and the email of the shop owner.

"},{"location":"oauth2/#customize-httpx-client","title":"Customize HTTPX client","text":"

By default, requests are made using httpx.AsyncClient with default parameters. If you wish to customize settings, like setting timeout or proxies, you can do this by overloading the get_httpx_client method.

from typing import AsyncContextManager\n\nimport httpx\nfrom httpx_oauth.oauth2 import OAuth2\n\n\nclass OAuth2CustomTimeout(OAuth2):\n    def get_httpx_client(self) -> AsyncContextManager[httpx.AsyncClient]:\n        return httpx.AsyncClient(timeout=10.0)  # Use a default 10s timeout everywhere.\n\n\nclient = OAuth2CustomTimeout(\n    \"CLIENT_ID\",\n    \"CLIENT_SECRET\",\n    \"AUTHORIZE_ENDPOINT\",\n    \"ACCESS_TOKEN_ENDPOINT\",\n    refresh_token_endpoint=\"REFRESH_TOKEN_ENDPOINT\",\n    revoke_token_endpoint=\"REVOKE_TOKEN_ENDPOINT\",\n)\n
"}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 865723d8fd289e63544c608fd1401782b6cd4044..a6c388046cb877ee5343a12c75b068fcee213da6 100644 GIT binary patch delta 12 Tcmb=gXOr*d;J6h$k*yK{8BPQI delta 12 Tcmb=gXOr*d;CLN0k*yK{8J`3U