Adding Authentication
Sign users in with Google, Apple, Microsoft, or MitID and manage authentication sessions
Adding Authentication
By default, username/password login in your app works exactly the same way as it does on your website — no extra SDK work is needed. If you want to add biometric login (Face ID / fingerprint), see Biometric Login.
This page covers social and third-party sign-in — Google, Apple, Microsoft, MitID and more. We currently support the providers listed below, and we continuously add new ones as the need arises.
Supported providers
The SDK supports the following built-in providers:
| Provider | providerName value |
|---|---|
"google" | |
| Apple | "apple" |
| Microsoft | "microsoft" |
| MitID (Denmark) | "signaturgruppenmitid" |
You can also pass any custom provider name as a string if you have configured one in the manager.
Sign in with Google
The signIn() method opens the native authentication flow for the requested provider. It returns a Promise that resolves with the authentication result.
const result = await startiapp.Auth.signIn("google");That single line opens a native Google sign-in dialog. The user authenticates with their Google account, and the SDK returns the result to your code.
Handle the authentication result
Every result object has an isSuccess boolean. When the sign-in succeeds, you get an authorization code and related fields that your backend can exchange for tokens.
const result = await startiapp.Auth.signIn("google");
if (result.isSuccess) {
console.log("Authorization code:", result.authorizationCode);
console.log("Code verifier:", result.codeVerifier);
console.log("Redirect URI:", result.redirectUri);
// Send these to your backend to exchange for access/refresh tokens
await sendToBackend({
authorizationCode: result.authorizationCode,
codeVerifier: result.codeVerifier,
redirectUri: result.redirectUri,
});
} else {
console.log("Sign-in failed:", result.errorMessage);
}The result for a successful sign-in (for Google, Microsoft, MitID) contains:
| Property | Type | Description |
|---|---|---|
isSuccess | true | Indicates success |
providerName | string | The provider that was used |
authorizationCode | string | OAuth authorization code to exchange on your server |
codeVerifier | string | PKCE code verifier for the token exchange |
redirectUri | string | The redirect URI used during the flow |
additionalClaims | Record<string, string> | Extra claims returned by the provider |
A failed result contains:
| Property | Type | Description |
|---|---|---|
isSuccess | false | Indicates failure |
providerName | string | The provider that was used |
errorMessage | string | A human-readable error description |
The authorizationCode is a one-time-use code. Exchange it on your server
immediately and do not store it on the client.
Check for an existing session
Use getCurrentSession() to see if the user already has an active session. This is useful on page load to skip the sign-in screen.
const session = await startiapp.Auth.getCurrentSession();
if (session) {
console.log("User is already signed in.");
console.log("Provider:", session.providerName);
} else {
console.log("No active session -- show sign-in screen.");
}There is also a convenience method isAuthenticated() that returns a simple boolean.
const loggedIn = await startiapp.Auth.isAuthenticated();
if (loggedIn) {
// proceed to the app
} else {
// show the login page
}Both getCurrentSession() and isAuthenticated() are asynchronous because they
query the native bridge.
Sign out
Call signOut() to end the user's session.
const success = await startiapp.Auth.signOut();
if (success) {
console.log("User has been signed out.");
// Redirect to the login page
} else {
console.log("Sign-out failed.");
}Apple sign-in specifics
Apple Sign In returns a different result shape compared to other providers. Instead of authorizationCode + codeVerifier, Apple returns an identity object with user details.
const result = await startiapp.Auth.signIn("apple");
if (result.isSuccess) {
console.log("User ID:", result.identity.userId);
console.log("Email:", result.identity.email);
console.log("Name:", result.identity.name);
console.log("ID Token:", result.identity.idToken);
console.log("Authorization code:", result.authorizationCode);
console.log("Redirect URI:", result.redirectUri);
}The Apple result contains:
| Property | Type | Description |
|---|---|---|
identity.userId | string | Apple's stable user identifier |
identity.email | string | The user's email address |
identity.name | string | null | The user's name (only on first sign-in) |
identity.idToken | string | A signed JWT from Apple |
authorizationCode | string | OAuth authorization code |
redirectUri | string | The redirect URI used during the flow |
Apple only provides the user's name on the very first sign-in. On subsequent
sign-ins, identity.name is null. Make sure your backend stores the name during
the first authentication.
MitID sign-in with options
MitID (via Signaturgruppen) supports additional options. You can require a CPR number (Danish social security number) or specify custom scopes.
// Request CPR number
const result = await startiapp.Auth.signIn("signaturgruppenmitid", {
scope: "openid mitid ssn",
});
if (result.isSuccess) {
console.log("CPR:", result.additionalClaims["cpr"]);
}MitID test environment
During development, MitID uses the pre-production environment (pp.netseidbroker.dk). You can create test identities at pp.mitid.dk/test-tool/frontend/#/create-identity.
Listening for authentication events
The Auth integration dispatches an authenticationCompleted event when sign-in finishes. This can be useful if you want a centralized authentication handler.
startiapp.Auth.addEventListener("authenticationCompleted", function (event) {
const result = event.detail;
if (result.isSuccess) {
console.log("Authenticated with:", result.providerName);
}
});Complete working example
Here is a full example combining all the steps into a simple authentication flow.
async function main() {
if (!startiapp.isRunningInApp()) {
console.log("Authentication requires the native app.");
return;
}
await startiapp.initialize();
// Check for existing session
const existingSession = await startiapp.Auth.getCurrentSession();
if (existingSession) {
console.log("Welcome back! Provider:", existingSession.providerName);
showApp();
return;
}
// No session -- sign in
console.log("No session found. Starting sign-in...");
const result = await startiapp.Auth.signIn("google");
if (result.isSuccess) {
console.log("Signed in successfully!");
console.log("Authorization code:", result.authorizationCode);
// Exchange the authorization code on your backend
await fetch("/api/auth/exchange", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
authorizationCode: result.authorizationCode,
codeVerifier: result.codeVerifier,
redirectUri: result.redirectUri,
provider: result.providerName,
}),
});
showApp();
} else {
console.error("Sign-in failed:", result.errorMessage);
showError(result.errorMessage);
}
}
function showApp() {
document.getElementById("login-screen").style.display = "none";
document.getElementById("app-content").style.display = "block";
}
function showError(message) {
document.getElementById("error-text").textContent = message;
}
// Wire up the sign-out button
document.getElementById("sign-out-btn").addEventListener("click", async function () {
const success = await startiapp.Auth.signOut();
if (success) {
window.location.reload();
}
});
main();