One-click sign-in
By default, signIn() opens Internet Identity and the user picks how to authenticate. One-click sign-in skips that choice: the user lands directly on the provider’s own screen. Internet Identity is still the signer: it verifies the provider’s token and issues the delegation.
A client is built for one of two entry points, never both:
| Option | Sends the user to | Value |
|---|---|---|
openIdProvider | A provider Internet Identity has built in | "google", "apple", or "microsoft" |
ssoDomain | An organization’s own OpenID provider | The organization’s domain, such as "acme.com" |
Both are constructor options, fixed for the client’s lifetime. To offer several, build one client per choice.
Sign in with a built-in provider
Section titled “Sign in with a built-in provider”import { AuthClient } from "@icp-sdk/auth/client";
const authClient = new AuthClient({ openIdProvider: "google" });await authClient.signIn();The user goes straight to Google’s account chooser. The rest of the flow (getStatus(), getIdentity(), signOut()) is unchanged.
Sign in with an organization’s SSO
Section titled “Sign in with an organization’s SSO”const authClient = new AuthClient({ ssoDomain: "acme.com" });await authClient.signIn();Internet Identity reads the organization’s configuration from https://acme.com/.well-known/ii-openid-configuration and sends the user to the provider named there. Any organization that publishes that file can be signed in against, with nothing registered ahead of time.
The domain is normalized when the client is built: lowercased, IDNA-encoded, and reduced to a host with an optional port. A value carrying a scheme, a path, a query, or a fragment is not a domain, and the client reports it as invalid (see below).
If your app sets a derivationOrigin, the client sends it along with the domain, so Internet Identity uses the client the organization assigned to that origin.
Check a domain the user typed
Section titled “Check a domain the user typed”An app that asks the user for their organization’s domain can show whether it works before they continue. A client built with ssoDomain checks its domain against Internet Identity by itself, and getSsoStatus() returns the result, the same way getStatus() returns the session:
| State | Meaning | Show |
|---|---|---|
checking | Internet Identity is resolving the domain. | A spinner. |
available | The domain is ready for sign-in. name is the organization’s display name, when it publishes one. | “Continue with Acme Corp”. |
invalid | The input is not a domain. | Ask the user to correct it. |
unavailable | The domain publishes no usable configuration, or resolving it failed. retryAfter is when a retry can succeed, when known. | The failure, and a retry button. |
getSsoStatus() is synchronous and never throws, and subscribe() calls back whenever it changes. Build a new client once the user pauses typing, and dispose of the one it replaces, which also stops its check:
let client;let timer;
input.addEventListener("input", () => { // Drop the old domain at once, so Continue never signs in to it. client?.dispose(); client = undefined; showSpinner();
clearTimeout(timer); timer = setTimeout(() => { const next = new AuthClient({ ssoDomain: input.value }); next.subscribe(() => render(next.getSsoStatus())); render(next.getSsoStatus()); client = next; }, 300);});
function render(sso) { switch (sso.state) { case "checking": return showSpinner(); case "available": return enableContinue(sso.name); case "invalid": return showNotADomain(); case "unavailable": return showUnavailable(sso.retryAfter); }}
// Call signIn() before any await, or the browser blocks the popup.continueButton.addEventListener("click", () => { client?.signIn().then(showApp, showSignInError);});A replaced client is disposed before it can report, so a stale result never renders. The debounce builds one client per pause rather than one per keystroke.
For a “Try again” button, call refreshSsoStatus(). While retryAfter is in the future, keep the button disabled and count down to it (“Try again in 2 min”): Internet Identity does not retry a failing domain sooner, and an early retry answers unavailable again at once.
The check also prepares Internet Identity for this domain, so signIn() on the same client starts without waiting. signIn() opens Internet Identity in every state except invalid, which rejects without opening anything. A sign-in through an unavailable domain shows Internet Identity’s own error screen. In every state, signIn() also rejects when the user closes Internet Identity or authentication fails, so handle the rejection.
Request attributes in the same step
Section titled “Request attributes in the same step”A sign-in that goes to one provider can request attributes scoped to that provider, which the user grants on the same screen. See Identity attributes.
Next steps
Section titled “Next steps”- Enterprise SSO: how an organization enables SSO sign-in for its staff.
- Identity attributes: request a name and email with the sign-in.
@icp-sdk/authAPI reference: every option and method.