OAuth¶
client.oauth: /oauth/authorize and /api/v1/oauth/...
Bases: Resource
OAuth2 and OpenID Connect: build sign-in links, exchange codes, read the user's claims.
Most apps use sweatstack.fastapi or sweatstack.streamlit, which do this for you.
authorization_url(*, client_id, redirect_uri, code_challenge=None, scope=DEFAULT_SCOPE, prompt=None, state=None, nonce=None, integration=None, email_auth_mode=None)
¶
Builds the URL to send a user to for signing in with SweatStack.
Endpoint: GET /oauth/authorize
Parameters:
-
client_id(str) –Your app's client ID.
-
redirect_uri(str) –Where SweatStack sends the user back to; must be registered.
-
code_challenge(str | None, default:None) –A PKCE challenge from :meth:
generate_pkce_params. -
scope(str, default:DEFAULT_SCOPE) –Space-separated scopes.
-
prompt(str | None, default:None) –The OpenID Connect
prompt. Leave it out and SweatStack skips the consent screen when the user's grant already covers the request;"consent"always shows it. -
state(str | None, default:None) –An opaque value to check on the way back, against CSRF.
-
nonce(str | None, default:None) –Echoed in the
id_tokenthat comes with the code exchange. -
integration(str | None, default:None) –One provider (
"garmin_connect","intervals_icu","wahoo"): the user skips the sign-in chooser and goes straight to it. -
email_auth_mode(str | None, default:None) –"existing_only"presents email sign-in as for existing accounts, so a new user picks a wearable sign-in instead.
Returns:
-
str(str) –The authorization URL.
Examples:
from sweatstack import Client
client = Client()
verifier, challenge = client.oauth.generate_pkce_params()
url = client.oauth.authorization_url(
client_id="YOUR_CLIENT_ID",
redirect_uri="http://localhost:8000/callback",
code_challenge=challenge,
)
exchange_code(code, *, client_id, code_verifier=None, client_secret=None, persist=False)
¶
Exchanges an authorization code for tokens, and signs this client in with them.
Endpoint: POST /api/v1/oauth/token
The tokens stay in this client. In a server, keep them with the user's session; they are that user's credentials, not the machine's.
Parameters:
-
code(str) –The
codefrom the redirect back to your app. -
client_id(str) –Your app's client ID.
-
code_verifier(str | None, default:None) –The PKCE verifier, if you sent a challenge.
-
client_secret(str | None, default:None) –Your app's secret, for confidential clients.
-
persist(bool, default:False) –Also save the tokens on this machine for later sessions, as
authenticate()does. Never in a server.
Returns:
-
TokenResponse(TokenResponse) –access_token,refresh_tokenand their metadata.
Raises:
-
SweatStackAuthError–If the code or credentials are rejected.
-
SweatStackAPIError–If the API request fails for any other reason.
-
ValueError–If
persistis set on a client built withambient_credentials=False.
Examples:
from sweatstack import Client
client = Client()
tokens = client.oauth.exchange_code(
"code-from-redirect", client_id="YOUR_CLIENT_ID", code_verifier="verifier"
)
generate_pkce_params()
¶
Generates a PKCE code verifier and its S256 code challenge.
Returns:
-
str–tuple[str, str]:
(code_verifier, code_challenge). Send the challenge with -
str–meth:
authorization_url; keep the verifier for :meth:exchange_code.
Examples:
from sweatstack import Client
client = Client()
verifier, challenge = client.oauth.generate_pkce_params()
userinfo()
¶
Retrieves the OpenID Connect claims of the user, and why they may have no data.
Endpoint: GET /api/v1/oauth/userinfo
Requires the openid scope. sub and registered_at always come; the name claims
(name, given_name, family_name) need profile and email needs the
email scope, otherwise they are None. The response also has issue (beta):
None when there is nothing to say, otherwise the one thing to tell the user now.
issue.destination says the user can fix it in the Portal: pass it to
client.portal.sessions.create() when they click. It is None on delegated tokens
and on syncing issues, so show a button only when it is set. Issues are reported only
for the capabilities your app's scopes reach.
Without the openid scope, client.profile.status() gives the same issue.
Returns:
-
UserInfoResponse(UserInfoResponse) –The claims and the optional
issue.
Raises:
-
SweatStackAuthError–If the token lacks the
openidscope. -
SweatStackAPIError–If the API request fails for any other reason.
Examples:
from sweatstack import Client
client = Client()
user = client.oauth.userinfo()
if user.issue:
print(user.issue.message)