Enable Server Side User Authentication
Server-side user authentication in the LikeMinds SDK ensures secure and reliable user verification by handling authentication on the backend. It protects sensitive user data, prevents unauthorized access, and enables seamless session management. This approach enhances security while providing a smooth integration experience for developers.
Prerequisites
For each tech stacks below, LikeMinds Feed SDK should be integrate using the Getting Started Guide.
Steps to Enable Server-Side User Authentication
Step 1: Create an API on your Server to start a User Session with LikeMinds
Create a new API on your backend server that will handle user authentication with LikeMinds. This API should call the LikeMinds Initiate API to create a new user session. The Initiate API will return an accessToken and refreshToken that will be used to authenticate subsequent requests to the LikeMinds SDK.
Step 2: Create a function on Frontend to get tokens
Create a function to get accessToken and refreshToken from your backend using Initiate API.
- Android
 - iOS
 - Flutter
 - ReactJS
 - ReactNative
 
suspend fun getTokens():Pair<String,String>{
  // your implementation to fetch LikeMinds Authentication Tokens
  return Pair(accessToken, refreshToken)
}
func getTokens() -> (String, String)? {
    // your implementation to fetch LikeMinds Authentication Tokens
    return (accessToken, refreshToken)
}
Future<(String, String)> getTokens() async {
...
// implementation
...
return (accessToken, refreshToken);
}
function getTokens() {
  // Your implementation to fetch the LikeMinds Authentication tokens
  // Also save these tokens in the initial state of the application as you will be required to pass these tokens to LMClientOverlayProvider.
}
function getTokens() {
  // Your implementation to fetch the LikeMinds Authentication tokens
  // Also save these tokens in the initial state of the application as you will be required to pass these tokens to LMOverlayProvider.
}
Step 3: Create an instance of LMFeedCoreCallbacks
- Android
 - iOS
 - Flutter
 - ReactJS
 - ReactNative
 
While setting up LikeMinds Feed SDK in onCreate() method of the Application class, extend LMFeedCoreCallback and pass the instance of the same in LMFeedCore.setup()
val application = this
val theme = LMFeedTheme.SOCIAL_FEED
val enablePushNotifications = false
val deviceId = null
val domain = "ENTER YOUR DOMAIN HERE"
val lmFeedCoreCallback = object : LMFeedCoreCallback {
    override fun onAccessTokenExpiredAndRefreshed(
        accessToken: String,
        refreshToken: String
    ) {
        Log.d("Example","accessToken: $accessToken, refreshToken: $refreshToken")
    }
    override fun onRefreshTokenExpired(): Pair<String?, String?> {
        return runBlocking{
          getTokens()
        }
    }
}
LMFeedCore.setup(
    application = application,
    theme,
    enablePushNotifications = enablePushNotifications,
    deviceId = deviceId,
    domain = domain,
    lmFeedCoreCallback = lmFeedCoreCallback
)
Implement the LMFeedCoreCallback protocol in your class, which has the callbacks to manage tokens.
class ClientSDKCallBack: LMFeedCoreCallback {
  func onAccessTokenExpiredAndRefreshed(accessToken: String, refreshToken: String) {
    // Store the updated tokens
  }
  func onRefreshTokenExpired(_ completionHandler: (((accessToken: String, refreshToken: String)?) -> Void)?) {
    // Call inititate api from your backend and return the fetched accessToken and refreshToken
    // completionHandler?((accessToken, refreshToken))
    // In case the call fails, return nil
    // completionHandler?(nil)
  }
}
While setting up the LMFeedCore in the main function pass LMFeedCoreCallback, which will be invoked when the accessToken and refreshToken expire.
void main(){
  WidgetsFlutterBinding.ensureInitialized();
  // create callback object
  final lmFeedCallback = LMFeedCoreCallback(
      onAccessTokenExpiredAndRefreshed: (accessToken, refreshToken) {
        debugPrint("Access token expired and refreshed");
      },
      onRefreshTokenExpired: () async {
        // get accessToken, refreshToken from your backend
        final (accessToken, refreshToken) = await getTokens();
        // return `LMAuthToken` with `accessToken` and `refreshToken` received from your backend
        return (LMAuthTokenBuilder()
              ..accessToken(accessToken!)
              ..refreshToken(refreshToken!))
            .build();
      },
    )
  // Call setup function before the runApp() function
  await LMFeedCore.instance.initialize(
    // change the feed theme as per your requirements
    config: LMFeedConfig(
      feedThemeType: LMFeedThemeType.social,
    ),
    lmFeedCallback: lmFeedCallback,
  );
...
runApp(YourApp());
}
Create an instance of LMCoreCallbacks and pass in the necessary callback functions.
const lmCoreCallback = new LMCoreCallbacks(
  onAccessTokenExpiredAndRefreshed(accessToken: string, refreshToken: string) {
    // Handle Access and Refresh token as per your implementation
  },
  async onRefreshTokenExpired() {
    // Get New Tokens and return it in the below format
    return {
      accessToken: "YOUR NEW ACCESS TOKEN",
      refreshToken: "YOUR NEW REFRESH TOKEN",
    };
  }
);
Create an instance of LMCoreCallbacks and pass in the necessary callback functions.
const lmCoreCallback = new LMCoreCallbacks(
  onAccessTokenExpiredAndRefreshed(accessToken: string, refreshToken: string) {
    // Handle Access and Refresh token as per your implementation
  },
  async onRefreshTokenExpired() {
    // Get New Tokens and return it in the below format
    return {
      accessToken: "YOUR NEW ACCESS TOKEN",
      refreshToken: "YOUR NEW REFRESH TOKEN",
    };
  }
);
LMFeedCoreCallback has two callbacks:
onAccessTokenExpiredAndRefreshed(): This callback is triggered when the providedaccessTokenexpires and is refreshed internally using therefreshToken.onRefreshTokenExpired()This callback is triggered when the providedrefreshTokenexpires. In this case, you need to provide a newaccessTokenandrefreshTokenfrom your backend server using our initiate API.
Step 4: Send the received token to LikeMinds SDK
- Android
 - iOS
 - Flutter
 - ReactJS
 - ReactNative
 
Upon receiving the accessToken and refreshToken from your backend server, call LMFeedCore.showFeed() function with these tokens.
val context = this // instance of context
val accessToken = "RECEIVED ACCESS TOKEN"
val refreshToken = "RECEIVED REFRESH TOKEN"
val successCallback = { response : UserResponse? ->
    //user session initiated successfully, write your logic here
    Unit
} // callback triggered when the initiate user call is successful
val failureCallback = { errorMessage ->
  Log.e("Example", errorMessage)
  Unit
} // callback triggered when the initiate user call fails
LMFeedCore.showFeed(
    context = context,
    accessToken = accessToken,
    refreshToken = refreshToken,
    success = successCallback,
    error = failureCallback
)
Upon receiving the accessToken and refreshToken from your backend server, call LMFeedCore.shared.showFeed() function with these tokens.
import LikeMindsFeedCore
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) {
    // Pass the earlier created Implementation of LMFeedCoreCallback
     LMFeedCore.shared.showFeed(accessToken: accessToken, refreshToken: refreshToken, handler: ClientSDKCallback(), completionHandler: { })
}
Use the getTokens() function, to fetch the tokens to login without API Key. Upon receiving the accessToken and refreshToken, call LMFeedCore.instance.showFeedWithoutApiKey() function with these tokens.
// get accessToken, refreshToken from your backend
final (accessToken, refreshToken) = await getTokens();
LMResponse response =
    await LMFeedCore.instance.showFeedWithoutApiKey(
      accessToken : "YOUR_ACCESS_TOKEN",
      refreshToken : "YOUR_REFRESH_TOKEN",
    );
Open up src/App.tsx and replace its contents with the following code:
import { useState } from "react";
import {
  LMSocialFeed,
  LMFeedNotificationHeader,
  LMFeedCustomEvents,
  initiateFeedClient,
  LMCoreCallbacks
} from "@likeminds.community/likeminds-feed-reactjs";
function App() {
  const [userDetails, setUserDetails] = useState<{
    accessToken?: string;
    refreshToken?: string;
  }>({
    accessToken: "ENTER YOUR ACCESS TOKEN",
    refreshToken: "ENTER YOUR REFRESH TOKEN",
  });
  const lmCoreCallback = new LMCoreCallbacks(
    onAccessTokenExpiredAndRefreshed(accessToken: string, refreshToken: string) {
      // Handle Access and Refresh token as per your implementation
    },
    async onRefreshTokenExpired() {
      // Get New Tokens and return it in the below format
      return {
        accessToken: "YOUR NEW ACCESS TOKEN",
        refreshToken: "YOUR NEW REFRESH TOKEN",
      };
    }
  );
  // Initiated LMFeedClient
  const lmFeedClient = initiateFeedClient();
  // Initiated LMFeedCustomEvents
  const customEventClient = new LMFeedCustomEvents();
  return (
    <div className="lm-wrapper">
      <LMFeedNotificationHeader customEventClient={customEventClient} />
      <LMSocialFeed //Change as per selected theme
        client={lmFeedClient}
        customEventClient={customEventClient}
        userDetails={userDetails}
        LMFeedCoreCallbacks={lmCoreCallback}
      ></LMSocialFeed>
    </div>
  );
}
export default App;
Add the LMOverlayProvider and pass the accessToken and refreshToken returned in Step 2.
import {
  LMOverlayProvider
} from "@likeminds.community/feed-rn-core";
import {LMFeedClient} from '@likeminds.community/feed-rn';
import { LMCoreCallbacks } from "@likeminds.community/feed-rn-core/setupFeed";
import { GestureHandlerRootView } from "react-native-gesture-handler";
const App = () => {
  const [myClient, setMyClient] = useState<LMFeedClient>();
  const accessToken = "<YOUR_INITIAL_ACCESS_TOKEN>";
  const refreshToken = "<USER_INITIAL_REFRESH_TOKEN>";
  const onboardUser = <"BOOLEAN">;
  useEffect(() => {
    async function generateClient() {
      // Initiate LMChatClient as described in step 2
      const res: any = initMyClient();
      setMyClient(res);
    }
    generateClient();
  }, []);
  const lmCoreCallback = new LMCoreCallbacks(
    onAccessTokenExpiredAndRefreshed(accessToken: string, refreshToken: string) {
      // Handle Access and Refresh token as per your implementation
    },
    async onRefreshTokenExpired() {
      // Get New Tokens and return it in the below format
      return {
        accessToken: "YOUR NEW ACCESS TOKEN",
        refreshToken: "YOUR NEW REFRESH TOKEN",
      };
    }
  );
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <LMOverlayProvider
        myClient={myClient}
        accessToken={accessToken}
        refreshToken={refreshToken}
        callbackClass={lmCoreCallback}
        isUserOnboardingRequired={onboardUser}
      >
        {/* Follow step 4 in Getting Started to add navigation logic after user is successfully initiated with LM servers */}
      </LMOverlayProvider>
    </GestureHandlerRootView>
  );
};
export default App;
Conclusion
After completing these steps, your application will be configured with server-side user authentication for the LikeMinds SDK. This setup provides:
- Secure user verification through backend authentication
 - Protected sensitive user data
 - Seamless session management
 - Automatic token refresh handling
 
Make sure to test the authentication flow thoroughly in your development environment before deploying to production.