Overview of HTTPX OAuth
masterhttpx library. It is designed to facilitate OAuth flows in asynchronous Python environments.repository·master·Indexed 41 days ago
https://github.com/frankie567/httpx-oauthAn asynchronous OAuth client for Python built on top of the HTTPX library. It provides streamlined OAuth flows, a generic OAuth2 class for any compliant service, and pre-configured clients for providers including Google, GitHub, Discord, Facebook, Microsoft, and LinkedIn. Includes specialized integrations for FastAPI via the OAuth2AuthorizeCallback dependency to handle authorization callbacks.
httpx library. It is designed to facilitate OAuth flows in asynchronous Python environments.Install the httpx-oauth package using pip to use the async OAuth client with HTTPX.
pip install httpx-oauthWhen an error occurs during the OAuth2 callback process (e.g., the user denies access or the authorization code is invalid), the OAuth2AuthorizeCallback dependency raises an OAuth2AuthorizeCallbackError.
Because OAuth2AuthorizeCallbackError inherits from FastAPI's HTTPException, it is handled by FastAPI's default exception handler automatically. However, you can implement a custom exception handler to provide specialized error responses (e.g., custom JSON structures or specific logging).
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from httpx_oauth.integrations.fastapi import OAuth2AuthorizeCallbackError
app = FastAPI()
@app.exception_handler(OAuth2AuthorizeCallbackError)
async def oauth2_authorize_callback_error_handler(request: Request, exc: OAuth2AuthorizeCallbackError):
detail = exc.detail
status_code = exc.status_code
return JSONResponse(
status_code=status_code,
content={"message": "The OAuth2 callback failed", "detail": detail},
)Use the OAuth2AuthorizeCallback dependency to handle OAuth2 authorization callbacks in a FastAPI application. This dependency automatically reads the required query parameters from the request and returns a tuple containing the access_token and the state.
To use it:
OAuth2 client with your credentials and endpoints.OAuth2AuthorizeCallback passing the client and the name of your callback route.Depends(oauth2_authorize_callback) in your FastAPI route handler to retrieve the token and state.from fastapi import FastAPI, Depends
from httpx_oauth.integrations.fastapi import OAuth2AuthorizeCallback
from httpx_oauth.oauth2 import OAuth2
client = OAuth2("CLIENT_ID", "CLIENT_SECRET", "AUTHORIZE_ENDPOINT", "ACCESS_TOKEN_ENDPOINT")
oauth2_authorize_callback = OAuth2AuthorizeCallback(client, "oauth-callback")
app = FastAPI()
@app.get("/oauth-callback", name="oauth-callback")
async def oauth_callback(access_token_state=Depends(oauth2_authorize_callback)):
token, state = access_token_state
# Do something usefulYou can use the generic OAuth2 class to adapt to any OAuth2-compliant service by providing the necessary endpoints. The refresh_token_endpoint and revoke_token_endpoint are optional depending on the provider's capabilities.
from httpx_oauth.oauth2 import OAuth2
client = OAuth2(
"CLIENT_ID",
"CLIENT_SECRET",
"AUTHORIZE_ENDPOINT",
"ACCESS_TOKEN_ENDPOINT",
refresh_token_endpoint="REFRESH_TOKEN_ENDPOINT",
revoke_token_endpoint="REVOKE_TOKEN_ENDPOINT",
)The OAuth2Token class is a wrapper around the token response dictionary. It includes a helper method is_expired() to check if the token is no longer valid based on the expires_at or expires_in fields.
Common usage:
access_token = token["access_token"]
if token.is_expired():
# handle refresh logic
passaccess_token = token["access_token"]For providers that support it, use the refresh_token method to obtain a fresh access token using a refresh token. This returns an OAuth2Token dictionary-like object.
access_token = await client.refresh_token("REFRESH_TOKEN")revoke_token method to request the revocation of an access or refresh token from the provider.Use the get_authorization_url method to generate the URL where you should redirect the user to request their approval. You must provide a redirect_uri and can optionally specify a list of scopes.
authorization_url = await client.get_authorization_url(
"https://www.tintagel.bt/oauth-callback", scope=["SCOPE1", "SCOPE2", "SCOPE3"],
)After receiving an authorization code, use the get_access_token method to exchange it for a valid access token. This returns an OAuth2Token dictionary-like object.
access_token = await client.get_access_token("CODE", "https://www.tintagel.bt/oauth-callback")By default, the library uses httpx.AsyncClient. To customize settings such as timeouts or proxies, subclass the OAuth2 class and override the get_httpx_client method.
from typing import AsyncContextManager
import httpx
from httpx_oauth.oauth2 import OAuth2
class OAuth2CustomTimeout(OAuth2):
def get_httpx_client(self) -> AsyncContextManager[httpx.AsyncClient]:
return httpx.AsyncClient(timeout=10.0) # Use a default 10s timeout everywhere.
client = OAuth2CustomTimeout(
"CLIENT_ID",
"CLIENT_SECRET",
"AUTHORIZE_ENDPOINT",
"ACCESS_TOKEN_ENDPOINT",
refresh_token_endpoint="REFRESH_TOKEN_ENDPOINT",
revoke_token_endpoint="REVOKE_TOKEN_ENDPOINT",
)