LiveComponent that encapsulates the OAuth connect flow.
Creates an authorization session bound to a completion origin and a fresh intent reference, opens the provider's consent page in a popup, and receives the callback result via a JS hook and postMessage.
The browser only ever sees an opaque, short-lived completion handle. The
component never receives, forwards, or displays an access or refresh token.
On success it hands the handle to the parent LiveView, which finishes the flow
on the server with Tango.verify_authorization/4 and
Tango.multi_finalize_authorization/5, using the tenant from its own
authenticated assigns.
Usage
<.live_component
module={Tango.Live.OAuthComponent}
id="github-oauth"
provider="github"
tenant_id="user-123"
callback_url="http://localhost:4000/api/oauth/callback"
completion_origin="http://localhost:4000"
on_connect="oauth_connected"
on_error="oauth_error"
/>Required Assigns
provider— provider slug string (e.g."github")tenant_id— tenant identifier stringcallback_url— the URL where Tango's API Router handles callbackscompletion_origin— exact origin of the page hosting this component (e.g."https://app.example.com"). It must be listed inconfig :tango, :allowed_completion_origins; the callback page posts to this origin only.
Optional Assigns
scopes— list of scope strings (defaults to provider's default scopes)intent_reference— opaque reference that ties the completion to the action that started it (defaults to a random value per click)expected_connection_id/expected_subject— set when reauthorizing an existing connectionauth_params— extra provider authorization parametersbutton_class— CSS classes for the connect buttonbutton_label— override button text (default: "Connect {Provider}")on_connect— event name sent to parent on success (default:"oauth_connected")on_error— event name sent to parent on failure (default:"oauth_error")
Events Sent to Parent
On success, sends {on_connect, %{provider: ..., tenant_id: ..., completion_handle: ..., intent_reference: ...}} via send/2. The handle is not a credential, but it is
single-use and must be completed by trusted server code.
On error, sends {on_error, %{error: reason}} via send/2, where reason is
a stable category and never a provider response.
Completion and error messages for any intent other than the pending one are ignored, so a stale or replayed message cannot cancel the flow in flight.