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
- In Kinde, go to Settings > Applications > [Your app] > View details.
- 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
- Allowed callback URLs (also known as redirect URIs) - such as
- Select Save.
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.
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
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);
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.
...
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('/');
});
...
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
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());
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);
}
});
Go to the Users page in Kinde to see who has registered.
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
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);
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'
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>
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.
Property | Type | Is required | Default | Description |
---|---|---|---|---|
domain | string | Yes | Either your Kinde instance url or your custom domain. e.g. https://yourapp.kinde.com/ | |
clientId | string | Yes | The id of your application - get this from the Kinde admin area | |
clientSecret | string | Yes | The id secret of your application - get this from the Kinde admin area | |
redirectUri | string | Yes | The url that the user will be returned to after authentication | |
logoutRedirectUri | string | Yes | Where your user will be redirected upon logout | |
grantType | string | Yes | Define the grant type when using the SDK | |
audience | string | No | The audience claim for the JWT | |
scope | string | No | openid profile email offline | The scopes to be requested from Kinde |
Property | Description | Arguments | Usage | Sample output |
---|---|---|---|---|
login | Constructs redirect url and sends user to Kinde to sign in | client.login(); | ||
register | Constructs redirect url and sends user to Kinde to sign up | client.register(); | ||
logout | Logs the user out of Kinde | client.logout(); | ||
callback | Callback middleware function for Kinde OAuth 2.0 flow | client.callback(); | ||
isAuthenticated | Check if the user is authenticated | request - object (Request object) | client.isAuthenticated(req); | true or false |
createOrg | Constructs redirect url and sends user to Kinde to sign up and create a new org for your business | org_name? : string | client.createOrg(); | |
getClaim | Gets a claim from an access or id token | request - object (Request object), claim : string , tokenKey? : string | client.getClaim(req, 'given_name', 'id_token'); | 'David' |
getPermission | Returns the state of a given permission | key : string | client.getPermission(req, 'read:todos'); | { orgCode : 'org_1234', isGranted : true} |
getPermissions | Returns all permissions for the current user for the organization they are logged into | request - object (Request object) | client.getPermissions(req); | { orgCode : 'org_1234', permissions : ['create:todos', 'update:todos', 'read:todos'] } |
getOrganization | Get details for the organization your user is logged into | request - object (Request object) | client.getOrganization(req); | { orgCode : 'org_1234' } |
getUserDetails | Returns the profile for the current user | request - object (Request object) | client.getUserDetails(req); | { given_name: 'Dave', id: 'abcdef', family_name : 'Smith', email : 'mailto:dave@smith.com' } |
getUserOrganizations | Gets an array of all organizations the user has access to | request - 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.
Developer tools