Skip to main content

Authentication

The Authentication module manages sign-in, account creation, token storage, and logout. After a successful sign-in, AFCore stores the session securely and attaches authentication tokens to all subsequent API requests.


How It Works

  1. Your app calls signInOrCreateMember with an external user identifier (from your SSO, SAML, or custom identity provider).
  2. If the member exists, AFCore signs them in. If not, it creates the member and signs them in automatically.
  3. AFCore stores the access and refresh tokens in platform-secure storage (Android EncryptedSharedPreferences / iOS Keychain).
  4. All subsequent SDK calls include the token automatically -- no manual header management required.

Sign In or Create a Member

Use signInOrCreateMember to authenticate using an external identity. Optional profile fields seed the member's profile on first creation.

Parameters

ParameterTypeRequiredDescription
externalUserIdStringYesUnique identifier from your identity provider.
emailString?NoMember's email address.
firstNameString?NoGiven name.
middleNameString?NoMiddle name.
lastNameString?NoFamily name.
genderString?No"M" or "F".
dateOfBirthString?NoISO-8601 format (YYYY-MM-DD).
phoneNumberString?NoContact number.
address1String?NoPrimary street address.
address2String?NoSecondary address line.
cityString?NoCity.
stateString?NoTwo-letter state code.
zipString?NoPostal code.
attributesMap<String, String?>?NoFreeform key-value pairs for custom profile data.

Returns

AFResult -- check result.status (Boolean) for success and result.statusMessage for details on failure.

lifecycleScope.launch {
try {
val result = AFCore.authentication().signInOrCreateMember(
externalUserId = "sso-user-98765",
email = "alex@example.com",
firstName = "Alex",
lastName = "Rivera",
dateOfBirth = "1988-07-12",
attributes = mapOf("groupId" to "GR-2504")
)

if (result.status) {
// Session is active. Navigate to the main screen.
navigateToHome()
} else {
// The server rejected the request. Show the reason.
showError("Sign-in failed: ${result.statusMessage}")
}
} catch (e: Exception) {
// Network or unexpected error.
showError("Could not connect: ${e.message}")
}
}

Sign In with Credentials

Use authenticateWithCredentials to sign in a member with a username and password issued by your organization. On success, AFCore stores the session and attaches tokens to subsequent requests automatically.

Parameters

ParameterTypeRequiredDescription
usernameStringYesMember's username.
passwordStringYesMember's password.

Returns

AFResult -- check result.status (Boolean) for success and result.statusMessage for details on failure.

lifecycleScope.launch {
try {
val result = AFCore.authentication().authenticateWithCredentials(
username = usernameField.text.toString(),
password = passwordField.text.toString()
)

if (result.status) {
navigateToHome()
} else {
showError("Invalid credentials: ${result.statusMessage}")
}
} catch (e: Exception) {
showError("Could not connect: ${e.message}")
}
}

Authenticate with Tokens (Experimental)

Experimental API

authenticateWithTokens is marked experimental and should not be adopted in production yet. The signature and behaviour may change in any future release without a major-version bump. The server-side contract (claim shape, refresh semantics, error envelope) is still being validated. Wire it up behind a feature flag if you are evaluating it.

Use authenticateWithTokens when your own auth backend (or a server-side handshake) has already issued an AFCore-compatible access + refresh token pair and you want the SDK to adopt that session without running its own credential exchange. The SDK parses the access token's JWT payload for identity claims, persists both tokens, and emits LOGGED_IN on AFCore.authentication().sessionState (the deprecated AFCore.sessionState alias reflects the same change).

Parameters

ParameterTypeRequiredDescription
accessTokenStringYesJWT access token. Must contain an exp claim and one of advantaMemberId / memberId, otherwise the call returns a failed AFResult without persisting anything.
refreshTokenStringYesCompanion refresh token the SDK uses to obtain a new access token on subsequent 401 responses. Must be non-blank.

Returns

AFResult -- status = true when tokens were persisted and LOGGED_IN was emitted; false when required claims were missing, when either token was blank, or when the extracted memberId was "0".

Re-authentication

On a 401 during normal traffic, the SDK first tries to refresh with the supplied refreshToken. If that also fails, the SDK clears the local session and emits SESSION_EXPIRED. Subscribe to session state and, on SESSION_EXPIRED, obtain a fresh token pair and call authenticateWithTokens again -- re-calling overwrites the previously stored pair and re-emits LOGGED_IN.

lifecycleScope.launch {
val (access, refresh) = myAuthClient.exchange()
val result = AFCore.authentication().authenticateWithTokens(access, refresh)
if (result.status) {
navigateToHome()
} else {
showError("Token auth failed: ${result.statusMessage}")
}
}

Logout

logout() clears all stored tokens and local SDK state for the current member. Call this when the user explicitly signs out.

lifecycleScope.launch {
val result = AFCore.authentication().logout()
if (result.status) {
// Tokens cleared. Return to the login screen.
navigateToSignIn()
}
}

After logout, stop any active geofence monitoring and cancel background sync tasks. The member must sign in again before making any further SDK calls.


Best Practices

  • Call sign-in once per session. AFCore handles token refresh automatically. You do not need to re-authenticate on every app launch -- the stored session persists across launches.
  • Pass profile fields on first sign-in. Optional parameters like firstName, email, and dateOfBirth seed the server-side profile. If the member already exists, these fields are ignored unless the server is configured to update them.
  • Handle token expiry gracefully. If a token refresh fails (for example, after extended offline periods), AFCore throws an exception on the next API call. Catch it and redirect to sign-in.
  • Secure the external user ID. The externalUserId is the bridge between your identity system and AFCore. Validate it server-side if possible.

Error Handling

ScenarioRecommended Action
result.status == falseDisplay result.statusMessage to the user. Common causes: invalid credentials, disabled account, or server maintenance.
Network exceptionShow a retry option. AFCore does not retry authentication automatically.
Token refresh failureRedirect to sign-in. The session has expired.

Quick Reference

// Android
AFCore.authentication().signInOrCreateMember(externalUserId = "id", ...)
AFCore.authentication().authenticateWithCredentials(username = "user", password = "pass")
AFCore.authentication().authenticateWithTokens(accessToken = "...", refreshToken = "...") // experimental
AFCore.authentication().logout()