534 lines
15 KiB
Plaintext
534 lines
15 KiB
Plaintext
---
|
|
title: Authentication SDK Reference
|
|
description: User authentication and profile management with the InsForge Kotlin SDK
|
|
---
|
|
|
|
import KotlinSdkInstallation from '/snippets/kotlin-sdk-installation.mdx';
|
|
|
|
|
|
## Installation
|
|
|
|
<KotlinSdkInstallation />
|
|
|
|
## signUp()
|
|
|
|
Create a new user account with email and password.
|
|
|
|
### Parameters
|
|
|
|
- `email` (String) - User's email address
|
|
- `password` (String) - User's password
|
|
- `name` (String?, optional) - User's display name
|
|
|
|
### Returns
|
|
|
|
```kotlin
|
|
SignUpResponse
|
|
```
|
|
|
|
### SignUpResponse
|
|
|
|
```kotlin
|
|
data class SignUpResponse(
|
|
/** User object (null when email verification is required) */
|
|
val user: User? = null,
|
|
/** Access token (null when email verification is required) */
|
|
val accessToken: String? = null,
|
|
/** Indicates if email verification is required before sign-in */
|
|
val requireEmailVerification: Boolean = false,
|
|
/** Redirect URL (if applicable) */
|
|
val redirectTo: String? = null,
|
|
/** CSRF token (if applicable) */
|
|
val csrfToken: String? = null,
|
|
/** Refresh token (null when email verification is required) */
|
|
val refreshToken: String? = null
|
|
)
|
|
```
|
|
|
|
### Example (Complete Flow with Verification)
|
|
|
|
```kotlin
|
|
class AuthViewModel : ViewModel() {
|
|
|
|
// Sign up and handle verification requirement
|
|
suspend fun signUp(email: String, password: String, name: String?) {
|
|
try {
|
|
val result = client.auth.signUp(
|
|
email = email,
|
|
password = password,
|
|
name = name
|
|
)
|
|
|
|
if (result.requireEmailVerification) {
|
|
// Show verification code input screen
|
|
// User will receive a 6-digit code via email
|
|
_uiState.value = AuthUiState.RequiresVerification(email)
|
|
} else if (result.accessToken != null) {
|
|
// Registration complete, user is signed in
|
|
_uiState.value = AuthUiState.Authenticated
|
|
}
|
|
} catch (e: InsforgeHttpException) {
|
|
_uiState.value = AuthUiState.Error(e.message ?: "Sign up failed")
|
|
}
|
|
}
|
|
|
|
// Verify email with 6-digit code
|
|
suspend fun verifyEmail(email: String, code: String) {
|
|
try {
|
|
client.auth.verifyEmail(email = email, code = code)
|
|
// Verification successful, user can now sign in
|
|
_uiState.value = AuthUiState.VerificationSuccess
|
|
} catch (e: InsforgeHttpException) {
|
|
_uiState.value = AuthUiState.Error("Invalid verification code")
|
|
}
|
|
}
|
|
|
|
// Resend verification email
|
|
suspend fun resendVerificationEmail(email: String) {
|
|
try {
|
|
client.auth.resendVerificationEmail(email = email)
|
|
// Show success message
|
|
} catch (e: InsforgeHttpException) {
|
|
_uiState.value = AuthUiState.Error("Failed to resend verification email")
|
|
}
|
|
}
|
|
}
|
|
|
|
sealed class AuthUiState {
|
|
object Initial : AuthUiState()
|
|
object Authenticated : AuthUiState()
|
|
object VerificationSuccess : AuthUiState()
|
|
data class RequiresVerification(val email: String) : AuthUiState()
|
|
data class Error(val message: String) : AuthUiState()
|
|
}
|
|
```
|
|
|
|
### Email Verification
|
|
|
|
For users who register with email, the InsForge backend provides three options:
|
|
|
|
1. **No email verification** - Users can sign in immediately after registration. `SignUpResponse` will have `accessToken != null`.
|
|
2. **Link-based verification** - Users must open their email and click the verification link before they can sign in.
|
|
3. **Code-based verification** - The InsForge backend sends a 6-digit verification code to the user's email. The client app needs to display a verification screen where users can enter the code, then call `verifyEmail(email, code)` to complete verification. Only after this can users sign in with email + password.
|
|
|
|
When `requireEmailVerification` is `true`, the response will have:
|
|
- `accessToken = null`
|
|
- `user = null`
|
|
- `requireEmailVerification = true`
|
|
|
|
This indicates that verification via option 2 or 3 is required before the user can sign in.
|
|
|
|
### Related Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `verifyEmail(email, code)` | Verify email with 6-digit code |
|
|
| `resendVerificationEmail(email)` | Resend verification email |
|
|
|
|
---
|
|
|
|
## signIn()
|
|
|
|
Sign in an existing user with email and password.
|
|
|
|
### Example
|
|
|
|
```kotlin
|
|
try {
|
|
val result = client.auth.signIn(
|
|
email = "user@example.com",
|
|
password = "secure_password123"
|
|
)
|
|
|
|
result.user?.let { user ->
|
|
Log.d("Auth", "Welcome back, ${user.profile?.name ?: user.email}")
|
|
}
|
|
} catch (e: InsforgeHttpException) {
|
|
Log.e("Auth", "Sign in failed: ${e.message}")
|
|
}
|
|
```
|
|
|
|
### Email Verification
|
|
|
|
If the sign in response is:
|
|
```json
|
|
{"error":"FORBIDDEN","message":"Email verification required","statusCode":403,"nextActions":"Please verify your email address before logging in"}
|
|
```
|
|
This indicates that verification via option 2 or 3 (link or code, see [signUp()](#email-verification)) is required before the user can sign in.
|
|
|
|
---
|
|
|
|
## signOut()
|
|
|
|
Sign out the current user.
|
|
|
|
### Example
|
|
|
|
```kotlin
|
|
try {
|
|
client.auth.signOut()
|
|
Log.d("Auth", "User signed out")
|
|
} catch (e: InsforgeException) {
|
|
Log.e("Auth", "Sign out failed: ${e.message}")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## signInWithOAuthPage()
|
|
|
|
Sign in directly with a specific OAuth provider. This method opens the OAuth provider's authentication page directly in the system browser.
|
|
|
|
### Supported Providers
|
|
|
|
```kotlin
|
|
enum class OAuthProvider(val value: String) {
|
|
GOOGLE("google"),
|
|
GITHUB("github"),
|
|
DISCORD("discord"),
|
|
LINKEDIN("linkedin"),
|
|
FACEBOOK("facebook"),
|
|
INSTAGRAM("instagram"),
|
|
TIKTOK("tiktok"),
|
|
APPLE("apple"),
|
|
X("x"),
|
|
SPOTIFY("spotify"),
|
|
MICROSOFT("microsoft")
|
|
}
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- `provider` (`OAuthProvider`) - The OAuth provider to authenticate with
|
|
- `redirectUri` (`String`) - Callback URL where InsForge will redirect after authentication
|
|
|
|
### Returns
|
|
|
|
```kotlin
|
|
String // The OAuth authorization URL (also opens in browser automatically)
|
|
```
|
|
|
|
### Example
|
|
|
|
1. Configure BrowserLauncher
|
|
|
|
When creating the InsForge client, configure the `browserLauncher` to handle opening URLs:
|
|
|
|
```kotlin
|
|
val client = createInsforgeClient(baseURL, anonKey) {
|
|
install(Auth) {
|
|
browserLauncher = BrowserLauncher { url ->
|
|
val customTabsIntent = CustomTabsIntent.Builder()
|
|
.setShowTitle(true)
|
|
.build()
|
|
// Handle non-Activity context safely
|
|
if (context is Activity) {
|
|
customTabsIntent.launchUrl(context, Uri.parse(url))
|
|
} else {
|
|
customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
customTabsIntent.launchUrl(context, Uri.parse(url))
|
|
}
|
|
}
|
|
persistSession = true
|
|
sessionStorage = mySessionStorage
|
|
}
|
|
}
|
|
```
|
|
|
|
2. Configure App Link / Deep Link Callback
|
|
|
|
Configure your callback Activity in AndroidManifest.xml:
|
|
|
|
- Option A: Custom URL Scheme (for Development)
|
|
|
|
```xml
|
|
<activity
|
|
android:name=".AuthCallbackActivity"
|
|
android:launchMode="singleTask"
|
|
android:exported="true">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data android:scheme="yourapp" android:host="auth" android:path="/callback" />
|
|
</intent-filter>
|
|
</activity>
|
|
```
|
|
|
|
- Option B: App Links (for Production)
|
|
|
|
```xml
|
|
<activity
|
|
android:name=".AuthCallbackActivity"
|
|
android:launchMode="singleTask"
|
|
android:exported="true">
|
|
<intent-filter android:autoVerify="true">
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data android:scheme="https" android:host="yourdomain.com" android:path="/auth/callback" />
|
|
</intent-filter>
|
|
</activity>
|
|
```
|
|
|
|
3. Initiate OAuth Login with Specific Provider
|
|
|
|
```kotlin
|
|
// Start OAuth flow with Google
|
|
fun startGoogleLogin() {
|
|
lifecycleScope.launch {
|
|
val authUrl = client.auth.signInWithOAuthPage(
|
|
OAuthProvider.GOOGLE,
|
|
"yourapp://auth/callback"
|
|
)
|
|
// Browser opens automatically via browserLauncher
|
|
}
|
|
}
|
|
```
|
|
|
|
4. Handle OAuth Callback
|
|
|
|
```kotlin
|
|
class AuthCallbackActivity : AppCompatActivity() {
|
|
// Example: read the shared InsForge client from your Application class.
|
|
private val client by lazy { (application as MyApp).insforgeClient }
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
handleIntent(intent)
|
|
}
|
|
|
|
override fun onNewIntent(intent: Intent?) {
|
|
super.onNewIntent(intent)
|
|
intent?.let { handleIntent(it) }
|
|
}
|
|
|
|
private fun handleIntent(intent: Intent) {
|
|
intent.data?.let { uri ->
|
|
lifecycleScope.launch {
|
|
try {
|
|
val result = client.auth.handleAuthCallback(uri.toString())
|
|
|
|
Toast.makeText(
|
|
this@AuthCallbackActivity,
|
|
"Success: ${result.email}",
|
|
Toast.LENGTH_SHORT
|
|
).show()
|
|
|
|
startActivity(Intent(this@AuthCallbackActivity, MainActivity::class.java))
|
|
finish()
|
|
} catch (e: Exception) {
|
|
Toast.makeText(
|
|
this@AuthCallbackActivity,
|
|
"Failed: ${e.message}",
|
|
Toast.LENGTH_LONG
|
|
).show()
|
|
finish()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
`client` should come from the same shared InsForge client instance you use elsewhere in the app, such as an `Application` singleton or your DI container.
|
|
|
|
---
|
|
|
|
## getCurrentUser()
|
|
|
|
Fetch the current authenticated user from the server. This is a suspend function that makes a network request.
|
|
|
|
### Returns
|
|
|
|
```kotlin
|
|
CurrentUserResponse // Contains user data from server
|
|
```
|
|
|
|
### Example
|
|
|
|
```kotlin
|
|
try {
|
|
val response = client.auth.getCurrentUser()
|
|
Log.d("Auth", "Email: ${response.email}")
|
|
Log.d("Auth", "Name: ${response.profile?.name ?: "N/A"}")
|
|
} catch (e: InsforgeHttpException) {
|
|
Log.e("Auth", "Failed to get user: ${e.message}")
|
|
}
|
|
```
|
|
|
|
<Note>
|
|
This method makes a network request to fetch user data. For accessing locally cached user state, use `currentUser` StateFlow instead.
|
|
</Note>
|
|
|
|
---
|
|
|
|
## updateProfile()
|
|
|
|
Update current user's profile.
|
|
|
|
### Parameters
|
|
|
|
- `profile` (`Map\<String, Any\>`) - Profile fields to update
|
|
|
|
### Returns
|
|
|
|
```kotlin
|
|
ProfileResponse // Updated profile data
|
|
```
|
|
|
|
### Example
|
|
|
|
```kotlin
|
|
try {
|
|
val result = client.auth.updateProfile(
|
|
mapOf(
|
|
"name" to "JohnDev",
|
|
"bio" to "Android Developer",
|
|
"avatar_url" to "https://example.com/avatar.jpg"
|
|
)
|
|
)
|
|
Log.d("Auth", "Profile updated: ${result.name}")
|
|
} catch (e: InsforgeHttpException) {
|
|
Log.e("Auth", "Update failed: ${e.message}")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Password Reset
|
|
|
|
InsForge supports two password reset methods, configured in the backend:
|
|
|
|
- **Code method**: User receives a 6-digit code via email, verifies it to get a reset token, then resets password
|
|
- **Link method**: User receives a magic link via email containing the reset token, then resets password directly
|
|
|
|
### sendPasswordReset()
|
|
|
|
Send a password reset email to the user. The email will contain either a 6-digit code or a magic link depending on the backend configuration.
|
|
|
|
#### Parameters
|
|
|
|
- `email` (String) - User's email address
|
|
|
|
#### Example
|
|
|
|
```kotlin
|
|
try {
|
|
client.auth.sendPasswordReset(email = "user@example.com")
|
|
// Show message to check email
|
|
showMessage("If your email is registered, you will receive a password reset email.")
|
|
} catch (e: InsforgeHttpException) {
|
|
Log.e("Auth", "Failed to send reset email: ${e.message}")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### exchangeResetPasswordToken()
|
|
|
|
Exchange a 6-digit reset code for a reset token. **This method is only used with the code-based reset flow.**
|
|
|
|
#### Parameters
|
|
|
|
- `email` (String) - User's email address
|
|
- `code` (String) - 6-digit numeric code received via email
|
|
|
|
#### Returns
|
|
|
|
```kotlin
|
|
ResetTokenResponse
|
|
```
|
|
|
|
#### ResetTokenResponse
|
|
|
|
```kotlin
|
|
data class ResetTokenResponse(
|
|
/** Reset token to use with resetPassword() */
|
|
val token: String,
|
|
/** Token expiration timestamp */
|
|
val expiresAt: String?
|
|
)
|
|
```
|
|
|
|
#### Example
|
|
|
|
```kotlin
|
|
try {
|
|
val response = client.auth.exchangeResetPasswordToken(
|
|
email = "user@example.com",
|
|
code = "123456"
|
|
)
|
|
// Store the token and proceed to password reset screen
|
|
val resetToken = response.token
|
|
showPasswordResetScreen(token = resetToken)
|
|
} catch (e: InsforgeHttpException) {
|
|
Log.e("Auth", "Invalid or expired code: ${e.message}")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### resetPassword()
|
|
|
|
Reset the user's password using a reset token.
|
|
|
|
#### Parameters
|
|
|
|
- `newPassword` (String) - New password meeting the configured requirements
|
|
- `otp` (String) - Reset token (from `exchangeResetPasswordToken()` for code flow, or from magic link URL for link flow)
|
|
|
|
#### Example
|
|
|
|
```kotlin
|
|
try {
|
|
client.auth.resetPassword(
|
|
newPassword = "newSecurePassword123",
|
|
otp = resetToken
|
|
)
|
|
// Password reset successful
|
|
showMessage("Password reset successfully. You can now sign in.")
|
|
navigateToSignIn()
|
|
} catch (e: InsforgeHttpException) {
|
|
Log.e("Auth", "Password reset failed: ${e.message}")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
```kotlin
|
|
import dev.insforge.exceptions.InsforgeHttpException
|
|
import dev.insforge.exceptions.InsforgeException
|
|
|
|
try {
|
|
val result = client.auth.signIn(email, password)
|
|
} catch (e: InsforgeHttpException) {
|
|
// HTTP errors from API with error codes
|
|
when (e.error) {
|
|
"INVALID_CREDENTIALS" -> showError("Invalid email or password")
|
|
"USER_NOT_FOUND" -> showError("User not found")
|
|
"EMAIL_NOT_VERIFIED" -> showError("Please verify your email")
|
|
"INVALID_EMAIL" -> showError("Invalid email format")
|
|
"WEAK_PASSWORD" -> showError("Password is too weak")
|
|
else -> showError("Error: ${e.message}")
|
|
}
|
|
} catch (e: InsforgeException) {
|
|
// Other SDK errors (network, parsing, etc.)
|
|
showError("Error: ${e.message}")
|
|
}
|
|
```
|
|
|
|
### Common Error Codes
|
|
|
|
| Error Code | Description |
|
|
|------------|-------------|
|
|
| `INVALID_CREDENTIALS` | Email or password is incorrect |
|
|
| `USER_NOT_FOUND` | No user with this email exists |
|
|
| `EMAIL_NOT_VERIFIED` | Email verification required |
|
|
| `INVALID_EMAIL` | Email format is invalid |
|
|
| `WEAK_PASSWORD` | Password doesn't meet requirements |
|
|
| `USER_ALREADY_EXISTS` | Email is already registered |
|
|
| `SESSION_EXPIRED` | Session has expired, re-login required |
|