pywry.auth¶
OAuth2 authentication system — providers, token storage, session management, and flow orchestration.
Package Exports¶
OAuth2 authentication system for PyWry.
Provides OAuth2 provider abstractions, token storage, session management, and auth flow orchestration for both native window and deploy modes.
Classes¶
AuthFlowManager
¶
AuthFlowManager(provider: OAuthProvider, token_store: TokenStore | None = None, session_manager: SessionManager | None = None, use_pkce: bool = True, auth_timeout: float = 120.0)
Orchestrates OAuth2 authentication flows.
Supports two modes:
-
Native mode: Opens a dedicated auth window pointing at the provider's authorize URL, captures the redirect on an ephemeral localhost HTTP server, and exchanges the code for tokens.
-
Deploy mode: Returns the
/auth/loginURL for the frontend to navigate to. The server-side routes handle the actual flow.
Initialize the auth flow manager.
Attributes¶
Functions¶
run_native
¶
run_native(show_window: Any | None = None, close_window: Any | None = None, window_config: dict[str, Any] | None = None) -> AuthFlowResult
Run the OAuth2 flow in native window mode.
This method blocks until authentication completes, times out, or is cancelled.
Raises:
| Type | Description |
|---|---|
AuthFlowTimeout
|
If the callback is not received within the timeout. |
AuthFlowCancelled
|
If the user closes the auth window or aborts. |
AuthenticationError
|
If the provider returns an error. |
run_deploy
¶
Get the login URL for deploy mode.
In deploy mode, the actual OAuth2 flow is handled server-side
by the routes in deploy_routes.py. This method simply
returns the URL that the frontend should navigate to.
authenticate
¶
authenticate(app: Any, show_window: Any | None = None, close_window: Any | None = None, window_config: dict[str, Any] | None = None) -> AuthFlowResult
Unified authentication entry point.
Detects the app mode and runs the appropriate flow.
cancel
¶
Cancel the current authentication flow.
Sets the cancellation event which unblocks _wait_for_callback_with_cancellation.
OAuthProvider
¶
OAuthProvider(client_id: str, client_secret: str = '', scopes: list[str] | None = None, authorize_url: str = '', token_url: str = '', userinfo_url: str = '', revocation_url: str = '')
Bases: ABC
Abstract base class for OAuth2 providers.
Attributes:
| Name | Type | Description |
|---|---|---|
client_id |
str
|
OAuth2 client identifier registered with the provider. |
client_secret |
str
|
Client secret or empty string for public clients. |
scopes |
list[str]
|
Scopes requested during the authorization flow. |
authorize_url |
str
|
Provider authorization endpoint. |
token_url |
str
|
Provider token endpoint. |
userinfo_url |
str
|
Provider userinfo endpoint, if supported. |
revocation_url |
str
|
Provider token revocation endpoint, if supported. |
Initialize an OAuth provider.
Functions¶
close
async
¶
Close the shared HTTP client.
Notes
Call this from application shutdown hooks to release open sockets.
build_authorize_url
¶
build_authorize_url(redirect_uri: str, state: str, pkce: PKCEChallenge | None = None, extra_params: dict[str, str] | None = None) -> str
Build the full authorization URL.
exchange_code
abstractmethod
async
¶
exchange_code(code: str, redirect_uri: str, pkce_verifier: str | None = None, nonce: str | None = None) -> OAuthTokenSet
Exchange authorization code for tokens.
Raises:
| Type | Description |
|---|---|
TokenError
|
If the code exchange fails. |
refresh_tokens
abstractmethod
async
¶
Refresh an expired access token.
Raises:
| Type | Description |
|---|---|
TokenRefreshError
|
If the refresh fails. |
get_userinfo
async
¶
Fetch user profile information from the provider.
Raises:
| Type | Description |
|---|---|
HTTPError
|
Raised when the userinfo endpoint returns an error response. |
revoke_token
async
¶
Revoke a token at the provider (RFC 7009).
Posts to the revocation_url if one is configured.
Subclasses with non-standard revocation APIs should override.
GenericOIDCProvider
¶
GenericOIDCProvider(client_id: str, client_secret: str = '', issuer_url: str = '', scopes: list[str] | None = None, authorize_url: str = '', token_url: str = '', userinfo_url: str = '', revocation_url: str = '', *, require_id_token_validation: bool = True)
Bases: OAuthProvider
Generic OpenID Connect provider.
Supports auto-discovery from /.well-known/openid-configuration
if an issuer_url is provided.
Attributes:
| Name | Type | Description |
|---|---|---|
issuer_url |
str
|
Base issuer URL used for OIDC discovery and issuer validation. |
require_id_token_validation |
bool
|
Controls whether ID tokens are validated after token exchange. |
Initialize a generic OIDC provider.
Functions¶
close
async
¶
Close the shared HTTP client.
Notes
Call this from application shutdown hooks to release open sockets.
build_authorize_url
¶
build_authorize_url(redirect_uri: str, state: str, pkce: PKCEChallenge | None = None, extra_params: dict[str, str] | None = None) -> str
Build the full authorization URL.
get_userinfo
async
¶
Fetch user profile information from the provider.
Raises:
| Type | Description |
|---|---|
HTTPError
|
Raised when the userinfo endpoint returns an error response. |
validate_id_token
async
¶
Validate an OIDC ID token.
Checks signature (via JWKS), issuer, audience, expiry, and nonce.
Raises:
| Type | Description |
|---|---|
TokenError
|
If validation fails for any reason. |
exchange_code
async
¶
exchange_code(code: str, redirect_uri: str, pkce_verifier: str | None = None, nonce: str | None = None) -> OAuthTokenSet
Exchange authorization code for tokens via OIDC token endpoint.
Raises:
| Type | Description |
|---|---|
TokenError
|
Raised when discovery fails, the token endpoint is unavailable, or the token exchange response is invalid. |
refresh_tokens
async
¶
Refresh tokens via the OIDC token endpoint.
Raises:
| Type | Description |
|---|---|
TokenRefreshError
|
Raised when discovery or the refresh request fails. |
revoke_token
async
¶
Revoke a token via the OIDC revocation endpoint.
Triggers endpoint auto-discovery before delegating to the base implementation.
GoogleProvider
¶
Bases: GenericOIDCProvider
Google OAuth2 provider with preset endpoints.
Notes
Google authorization requests default to offline access and consent prompts so refresh tokens are returned consistently.
Initialize the Google OAuth provider.
Functions¶
close
async
¶
Close the shared HTTP client.
Notes
Call this from application shutdown hooks to release open sockets.
exchange_code
async
¶
exchange_code(code: str, redirect_uri: str, pkce_verifier: str | None = None, nonce: str | None = None) -> OAuthTokenSet
Exchange authorization code for tokens via OIDC token endpoint.
Raises:
| Type | Description |
|---|---|
TokenError
|
Raised when discovery fails, the token endpoint is unavailable, or the token exchange response is invalid. |
refresh_tokens
async
¶
Refresh tokens via the OIDC token endpoint.
Raises:
| Type | Description |
|---|---|
TokenRefreshError
|
Raised when discovery or the refresh request fails. |
get_userinfo
async
¶
Fetch user profile information from the provider.
Raises:
| Type | Description |
|---|---|
HTTPError
|
Raised when the userinfo endpoint returns an error response. |
revoke_token
async
¶
Revoke a token via the OIDC revocation endpoint.
Triggers endpoint auto-discovery before delegating to the base implementation.
validate_id_token
async
¶
Validate an OIDC ID token.
Checks signature (via JWKS), issuer, audience, expiry, and nonce.
Raises:
| Type | Description |
|---|---|
TokenError
|
If validation fails for any reason. |
build_authorize_url
¶
build_authorize_url(redirect_uri: str, state: str, pkce: PKCEChallenge | None = None, extra_params: dict[str, str] | None = None) -> str
Build a Google authorization URL with offline access defaults.
GitHubProvider
¶
Bases: OAuthProvider
GitHub OAuth2 provider.
GitHub uses a non-standard token exchange (no OIDC) and a separate API endpoint for user info.
Notes
GitHub is not OIDC-based here, so token exchange and revocation use provider-specific endpoints and payloads.
Initialize the GitHub OAuth provider.
Functions¶
close
async
¶
Close the shared HTTP client.
Notes
Call this from application shutdown hooks to release open sockets.
build_authorize_url
¶
build_authorize_url(redirect_uri: str, state: str, pkce: PKCEChallenge | None = None, extra_params: dict[str, str] | None = None) -> str
Build the full authorization URL.
get_userinfo
async
¶
Fetch user profile information from the provider.
Raises:
| Type | Description |
|---|---|
HTTPError
|
Raised when the userinfo endpoint returns an error response. |
exchange_code
async
¶
exchange_code(code: str, redirect_uri: str, pkce_verifier: str | None = None, nonce: str | None = None) -> OAuthTokenSet
Exchange an authorization code for a GitHub access token.
Raises:
| Type | Description |
|---|---|
TokenError
|
Raised when the exchange request fails or GitHub returns an error payload. |
refresh_tokens
async
¶
Refresh GitHub tokens using GitHub's refresh-token flow.
Raises:
| Type | Description |
|---|---|
TokenRefreshError
|
Raised when the refresh request fails or GitHub returns an error payload. |
revoke_token
async
¶
Revoke a GitHub token via the Applications API.
Uses DELETE /applications/{client_id}/token with HTTP
Basic authentication (client_id / client_secret).
MicrosoftProvider
¶
MicrosoftProvider(client_id: str, client_secret: str = '', tenant_id: str = 'common', scopes: list[str] | None = None)
Bases: GenericOIDCProvider
Microsoft / Azure AD OAuth2 provider.
Attributes:
| Name | Type | Description |
|---|---|---|
tenant_id |
str
|
Azure AD tenant identifier used to build authorize and token endpoints. |
Initialize the Microsoft OAuth provider.
Functions¶
close
async
¶
Close the shared HTTP client.
Notes
Call this from application shutdown hooks to release open sockets.
build_authorize_url
¶
build_authorize_url(redirect_uri: str, state: str, pkce: PKCEChallenge | None = None, extra_params: dict[str, str] | None = None) -> str
Build the full authorization URL.
exchange_code
async
¶
exchange_code(code: str, redirect_uri: str, pkce_verifier: str | None = None, nonce: str | None = None) -> OAuthTokenSet
Exchange authorization code for tokens via OIDC token endpoint.
Raises:
| Type | Description |
|---|---|
TokenError
|
Raised when discovery fails, the token endpoint is unavailable, or the token exchange response is invalid. |
refresh_tokens
async
¶
Refresh tokens via the OIDC token endpoint.
Raises:
| Type | Description |
|---|---|
TokenRefreshError
|
Raised when discovery or the refresh request fails. |
get_userinfo
async
¶
Fetch user profile information from the provider.
Raises:
| Type | Description |
|---|---|
HTTPError
|
Raised when the userinfo endpoint returns an error response. |
revoke_token
async
¶
Revoke a token via the OIDC revocation endpoint.
Triggers endpoint auto-discovery before delegating to the base implementation.
validate_id_token
async
¶
Validate an OIDC ID token.
Checks signature (via JWKS), issuer, audience, expiry, and nonce.
Raises:
| Type | Description |
|---|---|
TokenError
|
If validation fails for any reason. |
SessionManager
¶
SessionManager(provider: OAuthProvider, token_store: TokenStore, session_key: str = 'default', session_store: SessionStore | None = None, refresh_buffer_seconds: int = 60, on_reauth_required: Callable[[], None] | None = None)
Manages OAuth2 token lifecycle with automatic refresh.
Initialize the session manager.
Functions¶
initialize
async
¶
Load existing tokens from store and validate.
save_tokens
async
¶
Persist tokens and schedule background refresh.
get_access_token
async
¶
Get a valid access token, refreshing if near expiry.
Raises:
| Type | Description |
|---|---|
TokenExpiredError
|
If the token is expired and cannot be refreshed. |
refresh
async
¶
Refresh the access token.
Uses the stored refresh token to obtain a new access token.
Falls back to on_reauth_required if refresh fails.
Raises:
| Type | Description |
|---|---|
TokenRefreshError
|
If refresh fails and no re-auth callback is set. |
logout
async
¶
Clear all tokens and cancel scheduled refresh.
Optionally revokes the token at the provider.
TokenStore
¶
MemoryTokenStore
¶
Bases: TokenStore
In-memory token store for development and single-process use.
Thread-safe via asyncio.Lock, same pattern as MemorySessionStore.
Initialize the memory token store.
Functions¶
RedisTokenStore
¶
RedisTokenStore(redis_url: str = 'redis://localhost:6379/0', prefix: str = 'pywry', pool_size: int = 10)
Bases: TokenStore
Redis-backed token store for multi-worker deployments.
Uses Redis hash keys with optional TTL based on token expires_in.
Initialize the Redis token store.
Functions¶
PKCEChallenge
dataclass
¶
PKCE code verifier and challenge pair.
Attributes:
| Name | Type | Description |
|---|---|---|
verifier |
str
|
The code verifier (high-entropy random string). |
challenge |
str
|
The code challenge (base64url-encoded SHA-256 hash of verifier). |
method |
str
|
The challenge method, always "S256". |
Functions¶
generate
classmethod
¶
generate(length: int = 64) -> PKCEChallenge
Generate a new PKCE code verifier and challenge.
Functions¶
create_provider_from_settings
¶
create_provider_from_settings(settings: Any) -> OAuthProvider
Create an OAuthProvider instance from OAuth2Settings.
Raises:
| Type | Description |
|---|---|
AuthenticationError
|
If the provider type is unknown or settings are invalid. |
Notes
The settings object is accessed via getattr so callers may supply
configuration objects with compatible attribute names rather than a single
concrete settings type.
get_token_store
¶
get_token_store(backend: str = 'memory', **kwargs: Any) -> TokenStore
Factory function for token stores.
Returns a singleton instance. Call reset_token_store() to clear
the cached instance (e.g. in tests).
Submodules¶
| Module | Description |
|---|---|
| Providers | OAuthProvider ABC and concrete implementations (Google, GitHub, Microsoft, OIDC) |
| Token Store | Pluggable token storage backends (memory, keyring, Redis) |
| Flow | AuthFlowManager — orchestrates the full OAuth2 authorization code flow |
| Session | SessionManager — token lifecycle with automatic background refresh |
| Deploy Routes | FastAPI router for server-side OAuth2 in deploy mode |
| Callback Server | Ephemeral localhost server for capturing OAuth2 redirects |
| PKCE | RFC 7636 PKCE code challenge generation |