Kinde’s NodeJS SDK helps developers integrate with Express server using middleware helper functions, instead of manually using the HTTP and JSON API.

  • Node version 18.x.x or newer
  • A Kinde account - register for free here (no credit card required)
  • A Kinde domain - you get this when you register, e.g. yourdomain.kinde.com

Execute one of following commands. Both npm and yarn are acceptable.

npm install @kinde-oss/kinde-nodejs-sdk
// or
yarn add @kinde-oss/kinde-nodejs-sdk

Set callback URLs

Link to this section
  1. In Kinde, go to Settings > Applications > [Your app] > View details.
  2. Add your callback URLs in the relevant fields. For example:
    • Allowed callback URLs (also known as redirect URIs) - such as http://localhost:8000/callback
    • Allowed logout redirect URLs - such as http://localhost:8000
  3. 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. Make sure the redirect URLs you use are allowed callback redirect URLs.

  • KINDE_HOST - your Kinde domain, e.g. https://yourdomain.kinde.com
  • KINDE_CLIENT_ID - In Kinde, go to Settings > Applications > [your app] > View details.
  • KINDE_CLIENT_SECRET - In Kinde, go to Settings > Applications > [your app] > View details.
  • KINDE_REDIRECT_URL - your callback url, e.g. http://localhost:8000/callback
  • KINDE_POST_LOGOUT_REDIRECT_URL - where you want users to be redirected to after signing out, e.g. http://localhost:8000

Integrate with your app

Link to this section

You need to add the module express-session to initiate a session and execute the following JS code to create a KindeClient instance:

...
const { KindeClient, GrantType } = require('@kinde-oss/kinde-nodejs-sdk');
const session = require('express-session');
...

...
app.use(
  session({
    secret: '<secret_string>',
    saveUninitialized: true,
    cookie: { maxAge: 1000 * 60 * 60 * 24 },// 1 day, you can customize here
		resave: false,
  }),
);
...

const options = {
  domain: KINDE_HOST,
  clientId: KINDE_CLIENT_ID,
  clientSecret: KINDE_CLIENT_SECRET,
  redirectUri: KINDE_REDIRECT_URL,
  logoutRedirectUri: KINDE_POST_LOGOUT_REDIRECT_URL,
  grantType: YOUR_GRANT_TYPE,// Check detail at sdk/constant/GrantType.js
};

const client = new KindeClient(options);

Sign in and sign up

Link to this section

The Kinde client provides methods for easy sign in and sign up. You can add buttons in your HTML as follows:

<a href="/login">Sign in</a>
<a href="/register">Sign up</a>

You will also need to route /login and /register to the SDK methods in the middleware.

Client Credential flow

Link to this section
...
app.get('/login', client.login(),(req, res) => {
	// do something in next step
	return res.redirect('/');
});

app.get('/register', client.register(),(req, res) => {
	// do something in next step
	return res.redirect('/');
});
...

Authorization Code flow and PKCE flow

Link to this section

Route /callback to set up these flows. When the user is redirected back to your site from Kinde, this will call your callback URL defined in the KINDE_REDIRECT_URL variable.

...
app.get('/login', client.login(),(req, res) => {
	// do something in next step
	return res.redirect('/');
});
app.get('/register', client.register(),(req, res) => {
	// do something in next step
	return res.redirect('/');
});
app.get('/callback', client.callback(), (req, res) => {
	// do something in next step
	return res.redirect('/');
});
...

// You can also pass state as your register url or your login url
http(s)://<your_host>/register?state=<your_state> //Register
http(s)://<your_host>/login?state=<your_state> //Login

Check authenticated users

Link to this section

We’ve provided a helper to get a boolean value to check if a user is signed in by verifying that the access token is still valid.

client.isAuthenticated(req); // Boolean: true or false

The Kinde SDK comes with a logout method.

app.get("/logout", client.logout());

Get user information

Link to this section

You need to have already authenticated before you call the API, otherwise an error will occur.

Use the OAuthApi class, then call the getUser method.

...
const { OAuthApi } = require('@kinde-oss/kinde-nodejs-sdk');
...

const apiInstance = new OAuthApi();
apiInstance.getUser((error, data, response) => {
  if (error) {
    console.error(error);
  } else {
    console.log('API called successfully. Returned data: ' + 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.

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:

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

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

A practical example in code might look something like:

if (client.getPermission(req, "create:todos")["isGranted"]) {
    // create new a todo
}

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.

const options = {
  ...
	// rest options
	...,
  audience: 'api.yourapp.com',
};

const client = new KindeClient(options);

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 scopes into the KindeSDK

const options = {
  ...
	// rest options
	...,
  scope: 'openid profile email offline',
};

const client = new KindeClient(options);

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:

client.getClaim(req, "aud");
// ['api.yourapp.com']

client.getClaim(req, "given_name", "id_token");
// 'David'

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:

...
app.get('/createOrg', client.createOrg(), (req, res) => {
	// do something in next step
	return res.redirect('/');
});
...

You can also pass org_name as your create organization url in the query; the full url will be like this:

http(s)://<your_host>/createOrg?org_name=<your_org_name>

Sign up and sign in to organizations

Link to this section

The Kinde client provides methods for you easily sign up and sign in users into organizations. You can add links in your HTML as follows:

<a href="/login?org_code=<your_org_code>">Sign in</a>
<a href="/register?org_code=<your_org_code>">Sign up</a>

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:

client.getOrganization(req);
// { orgCode: 'org_1234' }

client.getUserOrganizations(req);
// { 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.

SDK API reference

Link to this section
PropertyTypeIs requiredDefaultDescription
domainstringYesEither your Kinde instance url or your custom domain. e.g. https://yourapp.kinde.com/
clientIdstringYesThe id of your application - get this from the Kinde admin area
clientSecretstringYesThe id secret of your application - get this from the Kinde admin area
redirectUristringYesThe url that the user will be returned to after authentication
logoutRedirectUristringYesWhere your user will be redirected upon logout
grantTypestringYesDefine the grant type when using the SDK
audiencestringNoThe audience claim for the JWT
scopestringNoopenid profile email offlineThe scopes to be requested from Kinde

KindeSDK methods

Link to this section
PropertyDescriptionArgumentsUsageSample output
loginConstructs redirect url and sends user to Kinde to sign inclient.login();
registerConstructs redirect url and sends user to Kinde to sign upclient.register();
logoutLogs the user out of Kindeclient.logout();
callbackCallback middleware function for Kinde OAuth 2.0 flowclient.callback();
isAuthenticatedCheck if the user is authenticatedrequest - object (Request object)client.isAuthenticated(req);true or false
createOrgConstructs redirect url and sends user to Kinde to sign up and create a new org for your businessorg_name?stringclient.createOrg();
getClaimGets a claim from an access or id tokenrequest - object (Request object), claimstringtokenKey?stringclient.getClaim(req, 'given_name', 'id_token');'David'
getPermissionReturns the state of a given permissionkeystringclient.getPermission(req, 'read:todos');{ orgCode : 'org_1234', isGranted : true}
getPermissionsReturns all permissions for the current user for the organization they are logged intorequest - object (Request object)client.getPermissions(req);{ orgCode : 'org_1234', permissions : ['create:todos', 'update:todos', 'read:todos'] }
getOrganizationGet details for the organization your user is logged intorequest - object (Request object)client.getOrganization(req);{ orgCode : 'org_1234' }
getUserDetailsReturns the profile for the current userrequest - object (Request object)client.getUserDetails(req);{ given_name: 'Dave', id: 'abcdef', family_name : 'Smith', email : 'mailto:dave@smith.com' }
getUserOrganizationsGets an array of all organizations the user has access torequest - object (Request object)client.getUserOrganizations(req);{ orgCodes: ['org_7052552de68', 'org_5a5c29381327'] }

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