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 providedaccessToken
expires and is refreshed internally using therefreshToken
.onRefreshTokenExpired()
This callback is triggered when the providedrefreshToken
expires. In this case, you need to provide a newaccessToken
andrefreshToken
from 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.