The Kinde PHP SDK allows developers to integrate with Composable Commerce APIs using PHP native interfaces, models and helpers instead of manually using the HTTP and JSON API.

You can also view the PHP docs and PHP starter kit in GitHub.

Register for Kinde

Link to this section

If you haven’t already got a Kinde account, register for free here (no credit card required). This will give you a Kinde domain, which you need to get started, e.g. yourapp.kinde.com

Install Composer and then execute the following command:

php composer.phar require kinde-oss/kinde-auth-php

Or add the following to your composer.json file:

"require": {
    "kinde-oss/kinde-auth-php": "*"
}

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) - for example, http://localhost:8000/callback
    • Allowed logout redirect URLs - for example, 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

The following variables need to be replaced in the code snippets below.

  • KINDE_HOST - your Kinde domain - e.g. https://your_kinde_domain.kinde.com
  • KINDE_REDIRECT_URL - your callback url, make sure this URL is under your allowed callback redirect URLs. - e.g. http://localhost:8000/callback
  • 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. - e.g. http://localhost:8000
  • KINDE_CLIENT_ID - you can find this on the Application details page
  • KINDE_CLIENT_SECRET - you can find this on the Application details page

Integrate with your app

Link to this section

Add the composer autoloader to your app.

require_once(__DIR__ . "/vendor/autoload.php");

Create a new instance of the Kinde Auth client object before you initialize your app.

...
use Kinde\KindeSDK\KindeClientSDK;
use Kinde\KindeSDK\Configuration;
use Kinde\KindeSDK\Sdk\Enums\GrantType;
...
private $kindeClient;
private $kindeConfig;

public function __construct()
{
...
		$this->kindeClient = new KindeClientSDK("KINDE_HOST", "KINDE_REDIRECT_URL", "KINDE_CLIENT_ID", "KINDE_CLIENT_SECRET", "KINDE_GRANT_TYPE");
		$this->kindeConfig = new Configuration();
		$this->kindeConfig->setHost("KINDE_HOST");
...
}

Sign in and registration

Link to this section

The Kinde client provides methods for easy login and registration.

You can add buttons in your HTML as follows:

<div class="navigation">
    <a href="/login" type="button">Login</a>
    <a href="/register" type="button">Register</a>
</div>

You will also need to route /login and /register to the SDK methods:

$this->kindeClient->login();

$this->kindeClient->register();

Manage redirects

Link to this section

When the user is redirected back to your site from Kinde, this will call your callback URL defined in the KINDE_REDIRECT_URL variable. You will need to route /callback to call a function to handle this.

public function callback() {
		// Need to implement, e.g: call an api,etc... In this case, we will get a token:
		$token = $this->kindeClient->getToken();
		$this->kindeConfig->setAccessToken($token->access_token);
		print_r($token);
}

You can also get the current authentication status with isAuthenticated

public function callback()
{
    if (!$this->kindeClient->isAuthenticated) {
				// Need to implement, e.g: call an api,etc... In this case, we will get a token:
        $token = $this->kindeClient->getToken();
        $this->kindeConfig->setAccessToken($token->access_token);
        print_r($token);

    }
}

For more information, please check out Kinde\KindeSDK\Sdk\Enums\AuthStatus

Link to this section

By default, your cookie will apply to the full domain and sub folder from which the code is called from. You can override both the path and domain using the following helper functions.

$storage = Storage::getInstance();
        // Set the cookie path to root so it applies to the whole domain
$storage->setCookiePath('/');
        // Set the cookie domain without a prefix so it can be applied to all subdomains
$storage->setCookieDomain('yourdomain.com');

The Kinde SPA client comes with a logout method.

$this->kindeClient->logout();

Get user information

Link to this section

To access the user information, use the getUserDetails helper function:

$this->kindeClient->getUserDetails();
// returns
[
	'given_name' => 'Dave',
  'id' => 'abcdef',
  'family_name' => 'Smith',
  'email' => 'dave@smith.com',
  'picture' => 'https://link_to_avatar_url.kinde.com',
]

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.

"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->kindeClient->getPermission("create:todos");
// ["orgCode" => "org_1234", "isGranted" => true]

$this->kindeClient->getPermissions();
// ["orgCode" => "org_1234", "permissions" => ["create:todos", "update:todos", "read:todos"]]

A practical example in code might look something like:

if ($this->kindeClient->getPermission("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.

public function __construct()
{
		...
		$this->kindeClient = new KindeClientSDK("KINDE_HOST", "KINDE_REDIRECT_URL", "KINDE_CLIENT_ID", "KINDE_CLIENT_SECRET", "KINDE_GRANT_TYPE", "KINDE_POST_LOGOUT_REDIRECT_URL", "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

public function __construct()
{
		...
		$this->kindeClient = new KindeClientSDK("KINDE_HOST", "KINDE_REDIRECT_URL", "KINDE_CLIENT_ID", "KINDE_CLIENT_SECRET", "KINDE_GRANT_TYPE", "KINDE_POST_LOGOUT_REDIRECT_URL", "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->kindeClient->getClaim("aud");
// ["name" => "aud", "value" => ["api.yourapp.com"]]

$this->kindeClient->getClaim("given_name", "id_token");
// ["name" => "aud", "value" => "David"]

Create an organization

Link to this section

To create a new organization within your application, run a similar function to below:

public function register()
{
		$this->kindeClient->createOrg();
}

You can also pass org_name as your organization

$this->kindeClient->createOrg(["org_name" => "Your Organization"]);

Sign up 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->kindeClient->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->kindeClient->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->kindeClient->getOrganization();
// ["orgCode" => "org_1234"]

$this->kindeClient->getUserOrganizations();
// ["orgCodes" => ["org_1234", "org_abcd"]]

For more information about how organizations work in Kinde, see Kinde organizations for developers.

We have provided a helper to grab any feature flag from access_token:

$this->kindeClient->getFlag('theme');
// returns
[
    "code" => "theme",
    "type" => "string",
    "value" => "pink",
    "is_default" => false // whether the fallback value had to be used
]

// Another usage case
$this->kindeClient->getFlag('is_dark_mode');
// returns
[
    "code": "is_dark_mode",
    "type": "boolean",
    "value": true,
    "is_default": false
]

// This flag does not exist - default value provided
$this->kindeClient->getFlag('create_competition', ["defaultValue" => false]);
// returns
[
    "code": "create_competition",
    "type" => "boolean",
    "value": false,
    "is_default": true // because fallback value had to be used
]

// The flag type was provided as string, but it is an integer
$this->kindeClient->getFlag('competitions_limit', {defaultValue: 3}, 's');
// should error out - Flag "competitions_limit" is type integer - requested type string


// This flag does not exist, and no default value provided
$this->kindeClient->getFlag('new_feature');
// should error out - This flag was not found, and no default value has been provided

We also provide wrapper functions which should leverage getFlag above:

// [--- Boolean ---]
$this->kindeClient->getBooleanFlag('is_dark_mode');

// with default value
$this->kindeClient->getBooleanFlag('is_dark_mode', false);
// [--- Boolean ---]


// [--- String ---]
$this->kindeClient->getStringFlag('theme');

// with default value
$this->kindeClient->getStringFlag('theme', 'blue');
// [--- String ---]


// [--- Integer ---]
$this->kindeClient->getIntegerFlag('competitions_limit');

// with default value
$this->kindeClient->getIntegerFlag('competitions_limit', 1);
// [--- Integer ---]

Once the user has successfully authenticated, you’ll have a JWT and a refresh token and that has been stored securely. E.g. using the getAccessToken method of the Storage class to get an access token.

...
use Kinde\\KindeSDK\\Sdk\\Storage\\Storage;
...

$storage = Storage::getInstance();

$accessToken = $storage->getAccessToken();

print_r($accessToken);

The token will be stored in the cookie. To specify the expiration time, you can use the setTokenTimeToLive method.

$storage->setTokenTimeToLive(time() + 3600) // Live in 1 hour
Link to this section

By default, your token cookie will be local to the subdomain that made the login request (e.g. login.yourdomain.com), so app.yourdomain.com will have no visibility of this.

You can confirm this in your browser, for example in Chrome go to Developer tools and under Application > Storage > Cookies, look at the Domain column.

To achieve cross sub-domain use the cookie needs to be set to the root domain rather than the subdomain. You can do this by adding the following code after initializing the KindeClient:

$storage = Storage::getInstance();
$storage->setCookieDomain('yourdomain.com');

SDK API reference

Link to this section

Either your Kinde instance URL or your custom domain. e.g https://yourapp.kinde.com/

Type: string

Required: yes

The url that the user will be returned to after authentication.

Type: string

Required: yes

The unique ID of your application. Get this from the Application details section in Kinde.

Type: string

Required: yes

The unique client secret of your Kinde application. Get this from the Application details section in Kinde.

Type: string

Required: yes

The grantType for Kinde Authorization varies for each OAuth 2 flow. You can use:

  • Authorization code: GrantType::authorizationCode: Intended for confidential clients, e.g. web-servers.
  • Authorization code with PKCE: GrantType::PKCE: Extension for public clients, e.g. single page web applications and mobile applications, and confidential clients, e.g. web-servers. Note that the code_challenge and code_challenge_method parameters are also required for this grant type.
  • Client credentials flow: GrantType::clientCredentials: Intended for confidential clients where machine-to-machine communication is required.

Type: string

Required: yes

logoutRedirectUri

Link to this section

Where your user will be redirected when they sign out.

Type: string

Required: yes

The scopes to be requested from Kinde.

Type: string

Required: No

Default:

openid profile email offline

additionalParameters

Link to this section

Additional parameters that will be passed in the authorization request.

Type: array

Required: No

Default: [ ]

additionalParameters - audience

Link to this section

The audience claim for the JWT.

Type: string

Required: No

KindeSDK methods

Link to this section

Constructs redirect url and sends user to Kinde to sign in.

Arguments:

org_code?: string

Usage:

$kinde->login();

Constructs redirect url and sends user to Kinde to sign up.

Arguments:

org_code?: string

Usage:

$kinde->register();

Logs the user out of Kinde.

Usage:

$kinde->logout();

Returns the raw access token from URL after logged from Kinde.

Usage:

$kinde->getToken();

Sample output:

[
	"access_token" => "eyJhbGciOiJSUzI...",
	"expires_in" => 86400,
	"id_token" => "eyJhbGciOiJSU...",
	"refresh_token" => "yXI1bFQKbXKLD7AIU...",
	"scope" => "openid profile email offline",
	"token_type" => "bearer"
];

Constructs redirect url and sends user to Kinde to sign up and create a new org for your business.

Arguments:

org_name?: string

Usage:

$kinde->createOrg();
or
$kinde->createOrg(["org_name" => "your organization name"});

Sample output:

redirect

Gets a claim from an access or ID token.

Arguments:

claim: string, tokenKey?: string

Usage:

$kinde->getClaim("given_name", "id_token");

Sample output:

David

Returns the state of a given permission.

Arguments:

key: string

Usage:

$kinde->getPermission("read:todos");

Sample output:

[
	"orgCode" => "org_1234",
	"isGranted" => true
];

getPermissions

Link to this section

Returns all permissions for the current user for the organization they are logged into.

Usage:

$kinde->getPermissions();

Sample output:

[
	"orgCode" => "org_1234",
	"permissions" => ["create:todos", "update:todos", "read:todos"]
];

getOrganization

Link to this section

Get details for the organization your user is logged into.

Usage:

$kinde->getOrganization();

Sample output:

[
	"orgCode" => "org_1234"
];

getUserDetails

Link to this section

Returns the profile for the current user.

Usage:

$kinde->getUserDetails();

Sample output:

[
	"given_name" => "Dave",
	"id" => "abcdef",
	"family_name" => "Smith",
	"email" => "mailto:dave@smith.com"
];

getUserOrganizations

Link to this section

Gets an array of all organizations the user has access to.

Usage:

$kinde->getUserOrganizations();

Sample output:

[
	"orgCodes" => ["org_8de8711f46a", "org_820c0f318de"]
];

Gets a feature flag from an access token.

Arguments:

flagName: string, options?: ["defaultValue" => any]

Usage:

$kinde->getFlag("is_dark_mode");

Sample output:

[
	"code": "is_dark_mode",
	"type": "boolean",
	"value": true,
	"is_default": false
];

getBooleanFlag

Link to this section

Gets a boolean feature flag from an access token.

Arguments:

flagName: string, defaultValue?: boolean

Usage:

$kinde->getBooleanFlag("is_dark_mode", false);

Sample output:

[
	"code": "is_dark_mode",
	"type": "boolean",
	"value": false,
	"is_default": true
];

Gets a string feature flag from an access token.

Arguments:

flagName: string, defaultValue?: string

Usage:

$kinde->getStringFlag('theme');

Sample output:

[
	"code": "theme",
	"type": "string",
	"value": "black",
	"is_default": false
];

getIntegerFlag

Link to this section

Gets a integer feature flag from an access token.

Arguments:

flagName: string, defaultValue?: integer

Usage:

$kinde->getIntegerFlag("competitions_limit");

Sample output:

[
	"code": "competitions_limit",
	"type": "integer",
	"value": 1,
	"is_default": false
];

isAuthenticated

Link to this section

To check user authenticated or not.

Usage:

$kinde->isAuthenticated

Sample output:

true or false

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 support