React Native SDK

Link to this section

The Kinde React Native SDK allows developers to quickly and securely integrate a new or an existing React Native application into the Kinde platform. Kinde has separate SDKs for the following versions of React Native 0.5-0.59, 0.6-0.69 and 0.7.

Note: Since version 0.60, we have already supported Typescript.

You can view the React Native v0.5-0.59 GitHub repo here.

Register for Kinde

Link to this section

If you haven’t already got a Kinde account, register for free here (no credit card required).

You need a Kinde domain to get started, e.g. yourapp.kinde.com.

Configure React Native

Link to this section

Add the Kinde React Native SDK as a dependency.

The easiest way to install the SDK is via npm or yarn:

// With npm
npm i @kinde-oss/react-native-sdk-0-5x --save

// With yarn
yarn add @kinde-oss/react-native-sdk-0-5x

Configure Kinde

Link to this section

Set callback URLs

Link to this section
  1. In Kinde, go to Settings > Applications.
  2. View the application details. This is where you get app keys and set the callback URLs.
  3. Add your callback URLs in the relevant fields. For example: - Allowed callback URLs: {your_url_scheme}://<your_kinde_host>//kinde_callback - for example myapp://myhost.kinde.com//kinde_callback - Allowed logout redirect URLs: {your_url_scheme}://<your_kinde_host>//kinde_ logoutcallback - for example myapp://myhost.kinde.com//kinde_ logoutcallback
  4. Select Save.

Add environments

Link to this section

Kinde comes with a production environment, but you can set up other environments if you want to. Note that each environment needs to be set up independently, so you need to use the Environment subdomain in the code block above for those new environments.

Configure your app

Link to this section

Environment variables

Link to this section

Put these variables in your .env file:

  • KINDE_ISSUER_URL - your Kinde domain
  • KINDE_POST_CALLBACK_URL - After the user authenticates we will callback to this address. Make sure this URL is under your allowed callback URLs.
  • KINDE_POST_LOGOUT_REDIRECT_URL - where you want users to be redirected to after logging out. Make sure this URL is under your allowed logout redirect URLs.
  • KINDE_CLIENT_ID - you can find this on the App keys page
KINDE_ISSUER_URL=https://your_kinde_domain.kinde.com
KINDE_POST_CALLBACK_URL=your_url_scheme://your_kinde_domain.kinde.com/kinde_callback
KINDE_POST_LOGOUT_REDIRECT_URL=your_url_scheme://your_kinde_domain.kinde.com/kinde_callback
KINDE_CLIENT_ID=your_kinde_client_id

Configuration example:

KINDE_ISSUER_URL=https://myhost.kinde.com
KINDE_POST_CALLBACK_URL=myapp://myhost.kinde.com/kinde_callback
KINDE_POST_LOGOUT_REDIRECT_URL=myapp://myhost.kinde.com/kinde_callback
KINDE_CLIENT_ID=myclient@live
Link to this section

If your app was launched from an external URL registered to your app you can access and handle it from any component you want with Linking:

For class component:

...
import { ..., Linking, ... } from 'react-native';
...
componentDidMount() {
    Linking.getInitialURL()
        .then((url) => {
            if (url) {
							// Need to implement
            }
        })
        .catch((err) => console.error("An error occurred", err));

    Linking.addEventListener('url', (event) => {
        if (event.url) {
					// Need to implement
        }
    })
}
...

You’ll need to link RCTLinking to your project by following the steps described here. If you also want to listen to incoming app links during your app’s execution, you’ll need to add the following lines to your AppDelegate.m

// iOS 9.x or newer
#import <React/RCTLinkingManager.h>
- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

If you’re targeting iOS 8.x or older, you can use the following code instead:

// iOS 8.x or older
#import <React/RCTLinkingManager.h>
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  return [RCTLinkingManager application:application openURL:url
                      sourceApplication:sourceApplication annotation:annotation];
}

Please make sure you have configuration URL scheme in Info.plist, so app can be opened by deep link:

...
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLName</key>
    <string>myapp</string> // you can change it
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myapp</string> // you can change it
    </array>
  </dict>
</array>
...

Open AndroidManifest.xml and update your scheme:

<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="myapp" android:host="your_kinde_host" />  // Please modify sheme and host to reflect your preferences.
</intent-filter>

Integrate with your app

Link to this section

You’ll need to create a new instance of the KindeSDK object. Please execute this code below:

...
import { KindeSDK } from '@kinde-oss/react-native-sdk-0-5x';
...

...
state = {
  ...
  client: new KindeSDK(YOUR_KINDE_ISSUER, YOUR_KINDE_REDIRECT_URI, YOUR_KINDE_CLIENT_ID, YOUR_KINDE_LOGOUT_REDIRECT_URI, YOUR_SCOPES)
  ...
}
...

Log in and registration

Link to this section

The Kinde provides methods for easily implementing a login / register flow.

As an example if you add buttons in your render as follows:

<View>
    <View>
        <Button title="Sign In" onPress={this.handleSignIn} />
    </View>
    <View>
        <Button title="Sign Up" color="#000" onPress={this.handleSignUp} />
    </View>
</View>

Then define new functions that match for each button. Make sure you’ve already defined KindeSDK as client in the state.

...
constructor() {
  ...
  this.handleSignUp = this.handleSignUp.bind(this);
  this.handleSignIn = this.handleSignIn.bind(this);
  ...
}

handleSignUp() {
  this.state.client.register();
}

handleSignIn() {
  this.state.client.login();
}
...

Handle redirect

Link to this section

Once your user is redirected back to your app from Kinde, using the getToken method to get token instance from Kinde:

...
constructor() {
  ...
  this.handleCallback = this.handleCallback.bind(this);
  ...
}
...

componentWillMount() {
    Linking.getInitialURL()
        .then((url) => {
            if (url) {
                this.handleCallback(url);
            }
        })
    .catch((err) => console.error("An error occurred", err));

    Linking.addEventListener('url', (event) => {
        if (event.url) {
          this.handleCallback(event.url);
        }
    })
}

async handleCallback(url) {
    if (!this.state.client.isAuthenticated) { // Check to see if the user is already logged in
        try {
            const token = await this.state.client.getToken(url);
            console.log('token here', token);
        } catch (error) {
            console.log(error);
        }
    }
}

This is implemented in much the same way as logging in or registering. The Kinde SPA client comes with a logout method:

...
constructor() {
  ...
  this.handleLogout = this.handleLogout.bind(this);
  ...
}
...

handleLogout() {
  ...
  this.state.client.logout();  //calling it
  ...
}

View user profile

Link to this section

You can get an authorized user’s profile from any component using the Kinde React Native hook.

Caution: Before you call the API, make sure that you’ve already authenticated. If not, errors will appear there.

To access the user information, use the OAuthApi class exported from @kinde-oss/react-native-sdk-0-5x, then call the getUser method of OAuthApi instance:

...
import { ..., OAuthApi, ApiClient, ... } from '@kinde-oss/react-native-sdk-0-5x';
...

...
constructor() {
  ...
  this.getUserProfile = this.getUserProfile.bind(this);
  ...
}

...
getUserProfile() {
	const apiClient = new ApiClient(YOUR_KINDE_ISSUER),
	const userApi = new OAuthApi(apiClient);
  const data = await userApi.getUser();
  console.log(data);
}

View users in Kinde

Link to this section

Go to the Users page in Kinde to see who has registered.

User Permissions

Link to this section

After a user signs in and they are verified, the token return includes permissions for that user. User permissions are set in Kinde, but you must also configure your application to unlock these functions.

Example permissions:

const permissions = [
    "create:todos",
    "update:todos",
    "read:todos",
    "delete:todos",
    "create:tasks",
    "update:tasks",
    "read:tasks",
    "delete:tasks"
];

We provide helper functions to more easily access permissions:

this.state.client.getPermission("create:todos");
// {orgCode: "org_1234", isGranted: true}

this.state.client.getPermissions();
// {orgCode: "org_1234", permissions: ["create:todos", "update:todos", "read:todos"]}

A practical example in code might look something like:

if (this.state.client.getPermission("create:todos").isGranted) {
    // Need to implement
}

An audience is the intended recipient of an access token - for example the API for your application. The audience argument can be passed to the Kinde client to request an audience be added to the provided token.

The audience of a token is the intended recipient of the token.

...
state = {
  ...
  client: new KindeSDK(YOUR_KINDE_ISSUER, YOUR_KINDE_REDIRECT_URI, YOUR_KINDE_CLIENT_ID, YOUR_KINDE_LOGOUT_REDIRECT_URI, YOUR_SCOPES,
  {
    audience: 'api.yourapp.com'
  })
  ...
}
...

For details on how to connect, see Register an API

Overriding scope

Link to this section

By default the KindeSDK requests the following scopes:

  • profile
  • email
  • offline
  • openid

You can override this by passing scope into the KindeSDK

...
state = {
  ...
  client: new KindeSDK(YOUR_KINDE_ISSUER, YOUR_KINDE_REDIRECT_URI, YOUR_KINDE_CLIENT_ID, YOUR_KINDE_LOGOUT_REDIRECT_URI, "profile email offline openid")
  ...
}
...

Getting claims

Link to this section

We have provided a helper to grab any claim from your id or access tokens. The helper defaults to access tokens:

this.state.client.getClaim("aud");
// ["api.yourapp.com"]

this.state.client.getClaim("given_name", "id_token");
// "David"

Organizations Control

Link to this section

Create an organization

Link to this section

To have a new organization created within your application, you will need to run a similar function to below:

<Button title="Create Organization" onPress={this.handleSignIn} />

Then define new function that match for button. Make sure you’ve already defined KindeSDK as client in the state.

...
constructor() {
  ...
  this.handleCreateOrg = this.handleCreateOrg.bind(this);
  this.handleSignIn = this.handleSignIn.bind(this);
  ...
}

handleCreateOrg() {
  this.state.client.createOrg();
}

// You can also pass org_name as your organization
this.state.client.createOrg({org_name: 'Your Organization'});
...

Sign and sign in to organizations

Link to this section

Kinde has a unique code for every organization. You’ll have to pass this code through when you register a new user. Example function below:

this.state.client.register({org_code: "your_org_code"});

If you want a user to sign into a particular organization, pass this code along with the sign in method:

this.state.client.login({org_code: "your_org_code"});

Following authentication, Kinde provides a json web token (jwt) to your application. Along with the standard information we also include the org_code and the permissions for that organization (this is important as a user can belong to multiple organizations and have different permissions for each).

Example of a returned token:

{
    "aud": [],
    "exp": 1658475930,
    "iat": 1658472329,
    "iss": "https://your_subdomain.kinde.com",
    "jti": "123457890",
    "org_code": "org_1234",
    "permissions": ["read:todos", "create:todos"],
    "scp": ["openid", "profile", "email", "offline"],
    "sub": "kp:123457890"
}

The id_token will also contain an array of organizations that a user belongs to - this is useful if you wanted to build out an organization switcher for example.

{
...
	"org_codes": ["org_1234", "org_4567"]
...
}

There are two helper functions you can use to extract information:

this.state.client.getOrganization();
// {orgCode: "org_1234"}

this.state.client.getUserOrganizations();
// {orgCodes: ["org_1234", "org_abcd"]}

Once the user has successfully authenticated, you’ll have a JWT and possibly a refresh token that should be stored securely.

Recommendations on secure token storage can be found here.

SDK API Reference

Link to this section
Property Type Is required Default Description
issuer string Yes Either your Kinde instance url or your custom domain. e.g https://yourapp.kinde.com/
redirectUri string Yes The url that the user will be returned to after authentication
clientId string Yes The id of your application - get this from the Kinde admin area
logoutRedirectUri string No Where your user will be redirected upon logout
scope boolean No openid offline The scopes to be requested from Kinde
additionalParameters object No {} Additional parameters that will be passed in the authorization request
additionalParameters - audience string No The audience claim for the JWT

KindeSDK methods

Link to this section
Property Description Arguments Usage Sample output
login Constructs redirect url and sends user to Kinde to sign in org_code?: string kinde.login();
register Constructs redirect url and sends user to Kinde to sign up org_code?: string kinde.register();
logout Logs the user out of Kinde kinde.logout();
getToken Returns the raw Access token from URL after logged from Kinde url: string kinde.getToken(url); eyJhbGciOiJIUzI1...
createOrg Constructs redirect url and sends user to Kinde to sign up and create a new org for your business org_name?: string kinde.createOrg(); or kinde.createOrg({org_name: 'your organization name'}); redirect
getClaim Gets a claim from an access or id token claim: string, tokenKey?: string kinde.getClaim('given_name', 'id_token'); "David"
getPermission Returns the state of a given permission `key: string kinde.getPermission(‘read:todos’);` {orgCode: "org_1234", isGranted: true}
getPermissions Returns all permissions for the current user for the organization they are logged into kinde.getPermissions(); {orgCode: "org_1234", permissions:"create:todos", "update:todos", "read:todos""create:todos","update:todos","read:todos"}
getOrganization Get details for the organization your user is logged into kinde.getOrganization(); {orgCode: "org_1234"}
getUserDetails Returns the profile for the current user kinde.getUserDetails(); {given_name: "Dave"; id: "abcdef"; family_name: "Smith"; email: dave@smith.com"}
getUserOrganizations Gets an array of all organizations the user has access to kinde.getUserOrganizations(); {orgCodes:"org_1234", "org_5678""org1​234","org5​678"}

Sometimes there will be issues related to caching when you develop React Native. There are some recommendations for cleaning the cache:

  1. Remove node_modules, yarn.lock or package-lock.json
  2. Clean cache: yarn cache clean or npm cache clean --force
  3. Make sure you have changed values in .env file
  4. Trying to install packages again: yarn install or npm install
  5. Run Metro Bundler: yarn start --reset-cache or npm start --reset-cache

Assume your StarterKit path is <StarterKit_PATH>.

  1. Clean cache. cd <StarterKit_PATH>/android./gradlew clean
  2. Follow the steps in the above general tips.
  1. Follow the steps at the above general tips.
  2. Clean cache. cd <StarterKit_PATH>/rm -rf Pods && rm -rd Podfile.lock
  3. Clean build folders on Xcode.

If you need help connecting to Kinde, please contact us at support@kinde.com.

Talk to us

If you can’t find what you’re looking for in our help center — email our team

Contact us
Talk to us