Sign in with STX
Describes stx-python 0.8.0, the current release.
Sign in with STX is OpenID Connect on top of connecting members: one round trip gives your server both who the member is (a verified ID token whose sub is their stable STX id) and their tokens. It suits a new app with no login of its own. The protocol is on Sign in with your STX account.
It needs a confidential client (with a secret) whose scopes include openid, on an exchange that publishes /.well-known/openid-configuration. Elsewhere start() raises STXNotAvailableError (connect); see What you can do.
from stx import oauth
connect = oauth.Connect( issuer="https://demo.stxapp.io", client_id=CLIENT_ID, client_secret=CLIENT_SECRET, redirect_uri="https://your.app/auth/stx/callback", scopes=["balance.read", "orders.read", "orders.write"],)
@route("/auth/stx/start")def start(request): started = connect.start(connection=request.args.get("connection")) # "google", "apple", "x" or None request.session["stx_sign_in"] = started.saved().to_dict() return redirect(started.url)
@route("/auth/stx/callback")def callback(request): saved = oauth.SavedSignIn.from_dict(request.session.pop("stx_sign_in")) done = connect.finish(request.url, saved) user = users.find_or_create(stx_sub=done.identity.sub, email=done.identity.email) tokens.set(user.id, done.tokens.to_stored()) return redirect("/")start() always asks for openid, adds a nonce, and returns the URL plus what to keep in the session (state, PKCE verifier, nonce). finish() checks the state first, exchanges the code, and verifies the ID token: its signature against the issuer’s published keys (RS256 or ES256), the issuer, that it is for your app, its expiry and the nonce. The callback errors are the same typed exceptions as for connecting members; a bad ID token raises oauth.STXOAuthException with error == "invalid_id_token".
Key your user record on done.identity.sub, not the email. done.tokens work like any member’s tokens: store them and use member_client from an OAuthClient for the same app. connect.refresh(), connect.disconnect(tokens) (ends the connection at STX) and connect.user_info(access_token, expected_sub=sub) (the member’s claims again) cover the rest.
oauth.AsyncConnect is the asyncio version, with the same methods to await.

