Keycloak is an open-source Identity and Access Management solution that supports various authentication mechanisms like OAuth2, OpenID Connect, and SAML. It’s commonly used for Single Sign-On (SSO) and securing applications.
In this guide, we will walk through how to integrate Keycloak authentication into a React Native app. Through the course of this blog, it is assumed that you already have set up a keycloak authentication server in you backend. We will cover the basics of setting and configuring keycloak in the React Native app, and implementing the authentication flow.
Prerequisites
Keycloak Server: If you don’t have a Keycloak instance running, you can easily spin one up using Docker or download it from Keycloak’s website.
React Native App: Make sure you have a working React Native app set up.
Step 1.Install Required Packages in you react native project
Run the following command to install the required dependencies:
npm install react-native-app-auth
It willl install react-native-app-auth which islibrary that simplifies OAuth2 authentication flows for mobile apps, and it integrates nicely with Keycloak.
Step 2. Create confuguration file to connect with keycloak in react app
export const keycloakConfig = {
clientId: 'your-client-id',
redirectUrl: '<app-name>://com.<app-name>.app', //replace <app-name> with your apps package name
scopes: ['openid', 'profile', 'email', 'offline_access'],
serviceConfiguration: {
authorizationEndpoint: '<your-keycloak-server-endpoint>/realms/<realm-name>/protocol/openid-connect/auth', //replace <realm-name> with your keycloak realm
tokenEndpoint: '<your-keycloak-server-endpoint>/realms/<realm-name>/protocol/openid-connect/token', //replace <realm-name> with your keycloak realm
}
};
Step 3. Initiate login flow
Calling the login function shown below, will open a pop up window for keycloak login page
import { authorize } from 'react-native-app-auth';
import keycloakConfig from "./keycloakconfig";
async function login() {
try {
const result = await authorize(keycloakConfig);
//result contains the authrisation result object which includes several properties like token, idToken, refressToken, token expiry time
console.log('Access Token:', result.accessToken);
console.log('ID Token:', result.idToken);
} catch (error) {
console.error('Authentication failed:', error);
}
}
After successfull login,keycloak will redirect you to your app (if configuration is accurate). Then you save authrisation result in a react state or securely on mobile device using a library like react-native-keychain for the further use.
Now the login flow is complete, you can follow further to logout and getting new auth results for new token process.
Step 4. Getting new token, if current token is expring:
import { AuthorizeResult, refresh } from "react-native-app-auth";
//check if current token is expired
export const isTokenExpired = async (tokenExpiryTime) => {
const expireDateTime = new Date(tokenExpiryTime).getTime();
const currentTime = new Date().getTime();
// return true if token expired
return expireDateTime < currentTime;
}
// gets new auth result and token
export const getNewAuthResult = async (refreshToken) => {
try {
const newAuthResult = await refresh(keycloakConfig, {
refreshToken: refreshToken
})
console.log(newAuthResult.accessToken);
return newAuthResult;
} catch (error) {
console.log('Error: ', error);
}
}
This function will get you the updated authresult if you want in case current token is expired or about to be expired.
This function will make you log out of the current session of the app.
Troubleshooting:
If you get errors like invalid uri parameter, redirect_uri_mismatch, or cors errors while logging on the pop up window, please make of following things:
You have setup a valid redirect uri, pointing to your app,
Configured you app uri on the keycloak settings for redirection and origins.
Try adding following lines in your main/AndroidManifest.xml file inside <intent-filter> tag.
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="<app-name>" android:host="callback"/> //replace <app-name> with your app name
2.If you are getting errors like login pop window not opening or closing after logging, try to update the android:launchMode="singleTop" in main/AndroidManifest.xml file.