Documentation Index
Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
Sign in with Google, Apple, Farcaster, Discord, Twitter, Facebook, or GitHub.
Setup
- Enable providers in Dynamic Dashboard → Social
- Whitelist your deep link URL in Security → Whitelist Mobile Deeplink
- Add OAuth callback activity to
AndroidManifest.xml:
<!-- OAuth Callback Activity (Required) -->
<activity
android:name="com.dynamic.sdk.android.Auth.AuthCallbackActivity"
android:exported="true"
android:launchMode="singleTop"
android:noHistory="true"
android:theme="@android:style/Theme.Translucent.NoTitleBar">
<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="yourappscheme" />
</intent-filter>
</activity>
Implementation
Social Login with Providers
Use the sdk.auth.social.connect() method to authenticate with social providers:
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Module.Auth.SocialAuthModule
val sdk = DynamicSDK.getInstance()
// Google Sign-In
fun signInWithGoogle() {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.GOOGLE)
}
// Apple Sign-In
fun signInWithApple() {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.APPLE)
}
// Farcaster Sign-In
fun signInWithFarcaster() {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.FARCASTER)
}
// Discord Sign-In
fun signInWithDiscord() {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.DISCORD)
}
// Twitter Sign-In
fun signInWithTwitter() {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.TWITTER)
}
// Facebook Sign-In
fun signInWithFacebook() {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.FACEBOOK)
}
// GitHub Sign-In
fun signInWithGitHub() {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.GITHUB)
}
Supported Providers
The SDK supports the following social providers:
| Provider | Enum Value |
|---|
| Google | SocialAuthModule.SocialProvider.GOOGLE |
| Apple | SocialAuthModule.SocialProvider.APPLE |
| Farcaster | SocialAuthModule.SocialProvider.FARCASTER |
| Discord | SocialAuthModule.SocialProvider.DISCORD |
| Twitter | SocialAuthModule.SocialProvider.TWITTER |
| Facebook | SocialAuthModule.SocialProvider.FACEBOOK |
| GitHub | SocialAuthModule.SocialProvider.GITHUB |
Complete Social Authentication Example
Here’s a complete example showing how to implement social authentication in Jetpack Compose:
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Email
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Module.Auth.SocialAuthModule
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class SocialLoginViewModel : ViewModel() {
private val sdk = DynamicSDK.getInstance()
private val _errorMessage = MutableStateFlow<String?>(null)
val errorMessage: StateFlow<String?> = _errorMessage
private val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading
fun signInWithGoogle() {
_errorMessage.value = null
_isLoading.value = true
try {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.GOOGLE)
} catch (e: Exception) {
_errorMessage.value = "Google sign-in failed: ${e.message}"
_isLoading.value = false
}
}
fun signInWithApple() {
_errorMessage.value = null
_isLoading.value = true
try {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.APPLE)
} catch (e: Exception) {
_errorMessage.value = "Apple sign-in failed: ${e.message}"
_isLoading.value = false
}
}
fun signInWithFarcaster() {
_errorMessage.value = null
_isLoading.value = true
try {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.FARCASTER)
} catch (e: Exception) {
_errorMessage.value = "Farcaster sign-in failed: ${e.message}"
_isLoading.value = false
}
}
fun signInWithDiscord() {
_errorMessage.value = null
_isLoading.value = true
try {
sdk.auth.social.connect(SocialAuthModule.SocialProvider.DISCORD)
} catch (e: Exception) {
_errorMessage.value = "Discord sign-in failed: ${e.message}"
_isLoading.value = false
}
}
}
@Composable
fun SocialLoginScreen(viewModel: SocialLoginViewModel) {
val errorMessage by viewModel.errorMessage.collectAsState()
val isLoading by viewModel.isLoading.collectAsState()
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center
) {
Text(
text = "Sign In",
style = MaterialTheme.typography.headlineLarge,
modifier = Modifier.padding(bottom = 32.dp)
)
// Google button
Button(
onClick = { viewModel.signInWithGoogle() },
modifier = Modifier.fillMaxWidth(),
enabled = !isLoading,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface
)
) {
Text("Continue with Google")
}
Spacer(modifier = Modifier.height(12.dp))
// Apple button
Button(
onClick = { viewModel.signInWithApple() },
modifier = Modifier.fillMaxWidth(),
enabled = !isLoading,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface
)
) {
Text("Continue with Apple")
}
Spacer(modifier = Modifier.height(12.dp))
// Farcaster button
Button(
onClick = { viewModel.signInWithFarcaster() },
modifier = Modifier.fillMaxWidth(),
enabled = !isLoading,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface
)
) {
Text("Continue with Farcaster")
}
Spacer(modifier = Modifier.height(12.dp))
// Discord button
Button(
onClick = { viewModel.signInWithDiscord() },
modifier = Modifier.fillMaxWidth(),
enabled = !isLoading,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface
)
) {
Text("Continue with Discord")
}
// Error message
errorMessage?.let { error ->
Spacer(modifier = Modifier.height(16.dp))
Text(
text = error,
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.bodySmall
)
}
// Loading indicator
if (isLoading) {
Spacer(modifier = Modifier.height(16.dp))
CircularProgressIndicator(modifier = Modifier.size(24.dp))
}
}
}
Listening for Authentication State
After social authentication succeeds, use Kotlin Flow to handle the authenticated user:
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.UserProfile
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class AuthManager : ViewModel() {
private val sdk = DynamicSDK.getInstance()
private val _user = MutableStateFlow<UserProfile?>(null)
val user: StateFlow<UserProfile?> = _user
fun startListening(onAuthenticated: () -> Unit) {
// Check if already authenticated
if (sdk.auth.isAuthenticated()) {
onAuthenticated()
return
}
// Listen for authentication changes
viewModelScope.launch {
sdk.auth.authenticatedUserChanges.collect { user ->
_user.value = user
if (user != null) {
onAuthenticated()
}
}
}
}
}
Best Practices
1. Deep Link URL Management
- Use a consistent deep link URL format
- Ensure the URL is whitelisted in your Dynamic dashboard
- Test deep link handling in your app
- Make sure the
redirectUrl in ClientProps matches your URL scheme
2. User Experience
- Show loading states during authentication
- Provide clear error messages
- Handle user cancellation gracefully
- Display provider-specific branding appropriately
3. Security
- Never store sensitive authentication data
- Use secure network connections
- Implement proper session management
- Follow provider-specific security guidelines
Troubleshooting
Callback Not Working
- Verify your app’s URL scheme is configured correctly in
AndroidManifest.xml
- Check that the
redirectUrl in ClientProps matches your URL scheme
- Ensure your deep link URL is whitelisted in Dynamic dashboard under Security → Whitelist Mobile Deeplink
- Verify the
AuthCallbackActivity is properly configured in your manifest
Provider Not Working
- Confirm provider is enabled in Dynamic dashboard
- Check that OAuth settings are properly configured
- Verify you have the correct permissions/scopes configured
- Test with a different account to rule out account-specific issues
Authentication Fails
- Check network connectivity
- Verify provider credentials in Dynamic dashboard
- Ensure the user’s account with the provider is valid
- Check for any error messages in Logcat
- Verify the provider app is installed (for Apple, Google, etc.)
Create custom-styled social login buttons:
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
@Composable
fun SocialButton(
text: String,
onClick: () -> Unit,
icon: @Composable () -> Unit,
backgroundColor: Color = MaterialTheme.colorScheme.surface,
contentColor: Color = MaterialTheme.colorScheme.onSurface,
enabled: Boolean = true
) {
Button(
onClick = onClick,
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
enabled = enabled,
colors = ButtonDefaults.buttonColors(
containerColor = backgroundColor,
contentColor = contentColor
),
elevation = ButtonDefaults.buttonElevation(
defaultElevation = 2.dp
)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
icon()
Spacer(modifier = Modifier.width(12.dp))
Text(text = text)
}
}
}
@Composable
fun SocialLoginButtons(viewModel: SocialLoginViewModel) {
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
// Google
SocialButton(
text = "Continue with Google",
onClick = { viewModel.signInWithGoogle() },
icon = {
// Add your Google icon here
Text("G", style = MaterialTheme.typography.titleMedium)
}
)
// Apple
SocialButton(
text = "Continue with Apple",
onClick = { viewModel.signInWithApple() },
icon = {
// Add your Apple icon here
Text("", style = MaterialTheme.typography.titleMedium)
},
backgroundColor = Color.Black,
contentColor = Color.White
)
// Farcaster
SocialButton(
text = "Continue with Farcaster",
onClick = { viewModel.signInWithFarcaster() },
icon = {
// Add your Farcaster icon here
Text("🟣", style = MaterialTheme.typography.titleMedium)
}
)
}
}
What’s Next
Now that you have social authentication set up:
- Session Management - Manage authenticated sessions
- Wallet Operations - Work with user wallets
- MFA - Add multi-factor authentication
- Passkeys - Implement passwordless authentication