Skip to main content

Overview & Concepts

Authentication in social.plus

social.plus uses a dual authentication approach to ensure both application security and user verification:

API Key

Purpose: Identifies your application to social.plus servers
Scope: Application-level authentication
Usage: Required for SDK initialization
Security: Keep secure, never expose in client code

Auth Token

Purpose: Server-to-server verification that the user is validated by your backend
Scope: User-level authentication with your system
Usage: Optional for development, required for production
Security: Generated by your backend, proves user is legitimate

How Auth Tokens Work

Auth tokens enable server-to-server communication between social.plus and your backend:
1

User Authentication

Your app authenticates the user with your own authentication system (login, OAuth, etc.)
2

Backend Token Generation

Your backend server generates an auth token for the verified user and sends it to your app. Learn how to implement this →
3

social.plus Verification

When your app logs into social.plus, the auth token proves to social.plus that your backend has verified this user
4

Secure Communication

social.plus can now trust that this user session is legitimate and validated by your system
Why Auth Tokens? This approach ensures that only users who have been properly authenticated by your backend can access social.plus features, maintaining security and preventing unauthorized access.

When Do You Need Each?

  • Production
  • Development
// Production mode - API key + auth tokens
const client = Client.createClient({
  apiKey: 'your-prod-api-key',
  region: 'sg'
});

// Secure login with auth token from your backend
await client.login({
  userId: 'user-123',
  displayName: 'John Doe',
  authToken: 'token-generated-by-your-backend' // Proves user is verified by your system
});
Auth tokens must be generated by your secure backend after verifying the user. This ensures server-to-server trust between social.plus and your authentication system.

Quick Start (Basic Authentication)

Step 1: Initialize the SDK

Start by setting up the social.plus client with your API key:
let client = try! AmityClient(apiKey: "your-api-key", region: .SG)

Step 2: Login User

Authenticate users to access social.plus features:
Task { @MainActor in
    do {
        try await client.login(
            userId: "user-123",
            displayName: "John Doe",
            authToken: "your-auth-token", // Optional for development
            sessionHandler: sessionHandler
        )
        print("Login successful")
    } catch {
        print("Login failed: \(error)")
    }
}

Step 3: Check Authentication Status

Verify if a user is currently logged in:
if (client.sessionState == .established) {
    let currentUserId = client.getCurrentUserId()
    print("Current user: \(currentUserId)")
} else {
    // Proceed to social.plus Authentication
    authenticateToSocialPlus()
}

Step 4: Logout

End the user session: For an extra layer of security, which ensures accessToken revocation prior to performing logout(). Should the SDK fail to revoke the accessToken, the SDK will not proceed to logout and will throw an exception to notify the failure.
do {
    try await client.secureLogout()
} catch {
    /// Handle error from revoking accessToken here
}

Understanding Session States

Session states indicate what’s happening with user authentication. social.plus SDK automatically manages these states according to the flow shown in the diagram below:

notLoggedIn

Ready for login - user needs to authenticate
Entry points: App start (no session), logout, login failure

establishing

Login in progress - authentication being processed
Entry point: When login() is called from notLoggedIn state

established

Fully authenticated - SDK ready, all features available
Entry points: Successful login, successful token renewal

tokenExpired

Token renewal needed - automatic renewal attempted
Entry point: When auth token expires during established state

terminated

Session forcibly ended - user banned or deleted
Entry points: User banned/deleted from established or tokenExpired states

Session Flow

Understanding the complete session state flow helps you build responsive apps:
1

SDK Initialization

App starts: Always begins in the start state, then immediately moves to:
  • No saved session: Moves to notLoggedIn state
  • Has saved session: Moves to established state (if session valid)
2

Login Process

User attempts login:
  • notLoggedInestablishing (login in progress)
  • Login succeeds: establishingestablished
  • Login fails: establishingnotLoggedIn
3

Active Session Management

During active use in established state:
  • Token expires: establishedtokenExpired
  • Token renewed successfully: tokenExpiredestablished
  • User banned/deleted: establishedterminated
  • Manual logout: establishednotLoggedIn
4

Token Expiration Handling

When in tokenExpired state:
  • Auto-renewal succeeds: Returns to established state
  • Auto-renewal fails: User may need to re-authenticate
  • User banned during renewal: Moves to terminated state
  • Manual logout: Moves to notLoggedIn state
5

Session Termination

From terminated state:
  • Only way out is through logout → notLoggedIn
  • User must re-authenticate to access features again
Session state diagram image temporarily removed while the asset is unavailable. The textual flow description above preserves the full logic.

Observing Session State

Monitor session state changes to handle authentication in your app:
  • iOS
  • Android
  • TypesScript
  • Flutter
var cancellable: AnyCancellable?
// Observe session state changes
cancellable = client.$sessionState.sink { sessionState in
    switch sessionState {
    case .notLoggedIn:
        // Show login screen
        self?.showLogin()
    case .establishing:
        // Show loading indicator
        self?.showLoading()
    case .established:
        // Hide loading indicator, proceed to app
        self?.hideLoading()
        self?.proceedToApp()
    case .tokenExpired:
        // Attempt to refresh token (Optional)
        self?.showTokenRefreshIndicator()
    case .terminated:
        // Handle session termination
        self?.handleTermination()
    }
}

Advanced Session Management

For production apps, you’ll need sophisticated session handling with automatic token refresh:

Session Handlers for Token Refresh

Session handlers automatically manage token lifecycle:
  • iOS
  • Android
  • TypesScript
  • Flutter
class ProductionSessionHandler: AmitySessionHandler {
    func sessionWillRenewAccessToken(renewal: AccessTokenRenewal) {
        // Call your backend to get a fresh token
        AuthService.shared.refreshToken { result in
            switch result {
            case .success(let newToken):
                renewal.renewWithAuthToken(withAuthToken: newToken)
            case .failure(let error):
                print("Token refresh failed: \(error)")
                renewal.unableToRetrieveAuthToken()
            }
        }
    }
}

// Use during login
let sessionHandler = ProductionSessionHandler()
try await client.login(
    userId: userId,
    displayName: displayName,
    authToken: authToken,
    sessionHandler: sessionHandler
)

Security Best Practices

Production Token Management

Auth tokens must be generated by your secure backend to establish server-to-server trust with social.plus.Refer to the general API Reference introduction until the dedicated authentication endpoint page is published.
// Example Node.js backend - generates tokens for verified users
app.post('/api/auth/social-plus-token', async (req, res) => {
  const { userId } = req.body;
  
  // STEP 1: Verify user is authenticated in YOUR system
  const user = await verifyUserInYourSystem(userId);
  if (!user) {
    return res.status(401).json({ error: 'User not authenticated in your system' });
  }
  
  // STEP 2: Generate social.plus auth token for this verified user
  const authToken = generateSocialPlusToken(userId);
  
  // STEP 3: Return token to your app for social.plus login
  res.json({ 
    authToken,
    message: 'Token generated for verified user'
  });
});
Why this approach?
  • Your backend vouches for the user’s authenticity to social.plus
  • social.plus trusts users who have valid tokens from your verified backend
  • Prevents unauthorized access to social.plus features
  • Maintains security boundary between your auth system and social.plus

Authentication Best Practices

  • Monitor session state changes in your app’s main navigation logic
  • Handle token expiration gracefully with automatic refresh
  • Provide clear feedback to users during state transitions
  • Clean up subscriptions when components unmount
  • Use secure logout when security is critical
  • Store tokens securely using platform-specific secure storage
  • Don’t ignore session state changes - they indicate important authentication events
  • Don’t store sensitive data when user is not authenticated
  • Don’t make API calls before reaching established state
  • Don't forget to handle the terminated state - users may be banned
  • Don’t expose API keys in client-side code
  • Don’t use plain text storage for auth tokens

Troubleshooting

Symptoms: Login never completes, app shows loading indefinitelySolutions:
  1. Check your API key and network connection
  2. Verify authentication token is valid
  3. Ensure you’re using the correct region
  4. Check for console errors or network timeouts
Symptoms: Users get logged out too oftenSolutions:
  1. Check your backend token expiration settings
  2. Verify session handler implementation
  3. Ensure token refresh logic works correctly
  4. Consider longer token expiration for better UX
Symptoms: Tokens don’t refresh automaticallySolutions:
  1. Verify you’re passing the session handler during login
  2. Check that your backend token has appropriate expiration
  3. Ensure session handler implementation handles errors
  4. Test with shorter token expiration for debugging
Symptoms: App crashes when authentication state changesSolutions:
  1. Ensure UI updates happen on the main thread
  2. Handle all possible session states in switch statements
  3. Add proper null checks and error handling
  4. Clean up observers when components unmount

Next Steps