Skip to main content
Sign in with Google, Apple, Farcaster, Discord, Twitter, Facebook, or GitHub.

Setup

  1. Enable providers in Dynamic DashboardSocial
  2. Whitelist your deep link URL in SecurityWhitelist Mobile Deeplink
  3. Add OAuth callback activity to AndroidManifest.xml:
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:
ProviderEnum Value
GoogleSocialAuthModule.SocialProvider.GOOGLE
AppleSocialAuthModule.SocialProvider.APPLE
FarcasterSocialAuthModule.SocialProvider.FARCASTER
DiscordSocialAuthModule.SocialProvider.DISCORD
TwitterSocialAuthModule.SocialProvider.TWITTER
FacebookSocialAuthModule.SocialProvider.FACEBOOK
GitHubSocialAuthModule.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

  • 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.)

Advanced: Custom Social Button UI

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:
  1. Session Management - Manage authenticated sessions
  2. Wallet Operations - Work with user wallets
  3. MFA - Add multi-factor authentication
  4. Passkeys - Implement passwordless authentication