httpx-oauth

repository·master·Indexed 41 days ago

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

An 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.

Tokens
3.6K
Snippets
17
Records
24
Agent score
52%

What's inside httpx-oauth

  1. Handle OAuth2AuthorizeCallbackError in FastAPI

    master

    When 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},
        )
  2. Integrate OAuth2 authorization callbacks with FastAPI

    master

    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:

    1. Initialize an OAuth2 client with your credentials and endpoints.
    2. Instantiate OAuth2AuthorizeCallback passing the client and the name of your callback route.
    3. Use 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 useful
  3. Create an OAuth2 client

    master

    You 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",
    )
  4. Handle OAuth2Token objects and expiration

    master

    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
        pass
    access_token = token["access_token"]
  5. Generate an authorization URL

    master

    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"],
    )
  6. Request an access token

    master

    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")
  7. Customize the HTTPX client

    master

    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",
    )