Skip to content

Native app sign-in

A native app signs in to an external provider in an authentication browser, such as ASWebAuthenticationSession. It then trades a one-time code for an ordinary Savorum session. The instance operator sets up the providers.

Check auth_features in capabilities first:

  • auth.native_sign_in: your app can sign in with an OIDC, SAML, or managed provider.
  • auth.native_link: a signed-in app can link an OIDC or SAML identity.
  • auth.managed_session: the instance uses a managed hosting provider.
  • auth.managed_native_session: your app can redeem a hosting grant for a session.
  • The return target is always savorum://auth/callback. Savorum rejects any other.
  • Use PKCE with code_challenge_method=S256. No other method works.
  • A code lasts one minute and works once. The first attempt uses it up, even if that attempt fails, so start over rather than retrying.
  • Send the instance Origin on every POST.
  • Read the session cookie name from the instance’s OpenAPI document, not a hard-coded value.
  1. Create a random state and a PKCE code verifier. Open begin a native sign-in in the authentication browser with redirect_uri, state, code_challenge, and code_challenge_method=S256.

  2. The person signs in with the provider. Savorum then opens savorum://auth/callback with a code and your state, or with error and state if sign-in failed or was cancelled.

  3. Check that state matches, then post to finish a native sign-in:

    { "code": "<code>", "code_verifier": "<verifier>", "redirect_uri": "savorum://auth/callback" }

The response is the same as any sign-in: the session cookie, the user, and the CSRF token. If the request carries an older session, Savorum ends it, so switching accounts leaves nothing behind.

Accepting an invitation is a browser flow. Send the person to the web app for that.

When the hosting service gives your app a grant, post the grant and your PKCE verifier to redeem a managed session grant:

{ "grant": "<grant>", "code_verifier": "<verifier>" }

The response is an ordinary session, as for sign-in above.

A signed-in app can add an OIDC or SAML identity to the account. Send the session cookie and X-CSRF-Token with both requests.

  1. Create a state and verifier as for sign-in. Post code_challenge and code_challenge_method=S256 to start a native link. The response holds a link_ticket that lasts one minute.
  2. Open begin a native sign-in with the sign-in parameters plus link_ticket.
  3. After the provider, Savorum opens the return target with a link code and your state. Nothing is linked yet.
  4. Post the code, verifier, and return target to finish a native link.

Linking ends the account’s sessions, including the app’s own. The response carries a replacement session: store it in place of the old one.

A wrong or reused code returns 400 with invalid_grant. An identity that belongs to another account returns 409 with identity_conflict. In both cases the current session stays signed in. A link code doesn’t work for sign-in.