Skip to content

Commit f7138dd

Browse files
authored
Merge pull request #466 from kinde-oss/feat/m2m-for-organizations
Do not Merge: M2M orgs doc
2 parents 7201136 + 3152b8b commit f7138dd

16 files changed

+1123
-2
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
page_id: 44a1ac1e-3e17-44e1-b503-2e0e678f5cc2
3+
title: Give API access to an organization using M2M
4+
sidebar:
5+
order: 8
6+
relatedArticles:
7+
- 9f832d29-1b76-4bb2-b4dc-e4a9a9c327b3
8+
- d2c841f1-78b4-47e0-b899-4d32ae857e0a
9+
---
10+
11+
If you want to give automated systems, AI agents, or backend services access to data in a specific organization, you can do this securely using an **organization-scoped machine-to-machine (M2M) application**.
12+
13+
This type of app is tied to a single organization and can only be used to access resources for that org.
14+
15+
To create an org-scoped M2M app:
16+
17+
1. In Kinde, go to **Organizations**, then select the organization.
18+
2. Select **Machine-to-machine apps**.
19+
3. Follow the steps to create the app and assign the appropriate scopes.
20+
21+
For full details, see [M2M access scoped to organizations](/machine-to-machine-applications/organization-scoped-m2m-apps/m2m-applications-for-organizations/).
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
page_id: 961dea3c-d8e2-47a0-8ab7-deabdb2d6a01
3+
title: Authenticate with M2M applications
4+
sidebar:
5+
order: 3
6+
relatedArticles:
7+
- d2c841f1-78b4-47e0-b899-4d32ae857e0a
8+
- 4cb63554-d6b3-45cf-bdad-2fac4790d3aa
9+
- 65d72460-e870-4d6a-a1ea-35740ca0e2cc
10+
---
11+
12+
You can use a Machine-to-Machine (M2M) application in Kinde to request access tokens using the OAuth 2.0 client credentials flow. These tokens can be used to call Kinde’s APIs or your own APIs with no user interaction required.
13+
14+
## Authorize your application
15+
16+
Before an M2M app can request a token for a specific API audience, it must be authorized for that API.
17+
18+
You can do this in the Kinde dashboard:
19+
20+
1. Go to the M2M application
21+
2. Select **APIs**
22+
3. Choose which APIs this app is allowed to call
23+
4. Select **Save**
24+
25+
You can also authorize apps programmatically using the Kinde Management API.
26+
27+
If the app is not authorized for the given audience, the token request will fail.
28+
29+
## Get an access token
30+
31+
Your M2M application will be provided with a `client_id` and `client_secret` which can be used to request a token.
32+
33+
To get a token, make a `POST` request to your Kinde environment’s token endpoint:
34+
35+
```http
36+
POST https://<your-subdomain>.kinde.com/oauth2/token
37+
```
38+
39+
### Required parameters
40+
41+
The request body must include:
42+
43+
```text
44+
grant_type=client_credentials
45+
&client_id=<your-client-id>
46+
&client_secret=<your-client-secret>
47+
&audience=<your-api-audience>
48+
```
49+
50+
If your app has scopes assigned, you can optionally request them:
51+
52+
```text
53+
&scope=read:users write:flags
54+
```
55+
56+
**Note**: The `audience` parameter tells Kinde which API the token is intended for. Use `https://<your-subdomain>.kinde.com/api/v1` when calling Kinde’s management API. If you're protecting your own custom API, the audience should match the identifier you registered for that API in Kinde.
57+
58+
### Example (cURL)
59+
60+
```bash
61+
curl --request POST 'https://your-subdomain.kinde.com/oauth2/token' \
62+
--header 'Content-Type: application/x-www-form-urlencoded' \
63+
--data-urlencode 'grant_type=client_credentials' \
64+
--data-urlencode 'client_id=your-client-id' \
65+
--data-urlencode 'client_secret=your-client-secret' \
66+
--data-urlencode 'audience=your-api-audience' \
67+
--data-urlencode 'scope=read:users write:flags'
68+
```
69+
70+
### Successful response
71+
72+
A successful request returns a JSON response with an access token:
73+
74+
```json
75+
{
76+
"access_token": "<token>",
77+
"token_type": "Bearer",
78+
"expires_in": 3600
79+
}
80+
```
81+
82+
## Use the token
83+
84+
Once you have a token, include it as a Bearer token in the `Authorization` header when making API calls:
85+
86+
```http
87+
Authorization: Bearer <token>
88+
```
89+
90+
## Example usage
91+
92+
Calling a Kinde API:
93+
94+
```bash
95+
curl https://your-subdomain.kinde.com/api/v1/organizations \
96+
-H "Authorization: Bearer <token>"
97+
```
98+
99+
## Notes
100+
101+
- Access tokens are valid for 1 hour by default.
102+
- The `audience` must match the intended API — tokens are only valid for the audience they’re issued for.
103+
- You can request multiple audiences
104+
- If your M2M app is scoped to an organization, the token will include the `org_code` trusted claim.
105+
- Tokens are JWTs and can be decoded to inspect claims using standard libraries or tools like [Kinde's JWT decoder](https://kinde.com/tools/online-jwt-decoder/).
106+
107+
## Test your M2M app from the Kinde dashboard
108+
109+
You can also generate a token from the UI:
110+
111+
1. Go to your M2M app in Kinde
112+
2. Select the **Test** tab
113+
3. Choose the API you want to test against
114+
4. Select **Generate token**
115+
5. Copy the access token and use it in your API requests
116+
117+
This is useful for debugging or verifying scopes and claims without writing code.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
---
2+
page_id: d2c841f1-78b4-47e0-b899-4d32ae857e0a
3+
title: M2M overview
4+
sidebar:
5+
order: 1
6+
relatedArticles:
7+
- 4cb63554-d6b3-45cf-bdad-2fac4790d3aa
8+
- 961dea3c-d8e2-47a0-8ab7-deabdb2d6a01
9+
- 65d72460-e870-4d6a-a1ea-35740ca0e2cc
10+
---
11+
12+
Machine-to-machine (M2M) applications allow you to authenticate backend services, scripts, or automation tools that need to call your APIs without a user being involved.
13+
14+
M2M apps in Kinde use the OAuth 2.0 client credentials flow to obtain access tokens. These tokens can then be used to securely interact with Kinde APIs or your own APIs.
15+
16+
You can create M2M applications for general use across your business, or scope them to a specific organization for tighter access control.
17+
18+
## Use cases
19+
20+
Common scenarios where M2M apps are useful:
21+
22+
- Internal automation scripts that manage users, flags, or orgs
23+
- CI/CD pipelines that update configuration or deploy features
24+
- AI agents that need to interact with your product on behalf of a customer
25+
- Customer-facing API keys that are tied to a specific tenant
26+
27+
## Types of M2M apps in Kinde
28+
29+
### Global (unscoped) M2M apps
30+
31+
These are not linked to any one organization and can be used to call APIs across multiple orgs. Typically used for admin-level automation or infrastructure integration.
32+
33+
### Org-scoped M2M apps
34+
35+
These are tied to a single organization. Tokens issued to these apps include trusted claims like `org_code`, ensuring that any access is isolated to that organization’s context.
36+
37+
## How M2M authentication works
38+
39+
1. Create an M2M app in the Kinde dashboard
40+
2. Use the provided `client_id` and `client_secret` in a client credentials request
41+
3. Receive an access token in response
42+
4. Use the token to call Kinde APIs or your own backend
43+
44+
Tokens can include scopes to limit access and, if scoped to an org, will include the `org_code` trusted claim.
45+
46+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
page_id: 4cb63554-d6b3-45cf-bdad-2fac4790d3aa
3+
title: Quick start
4+
sidebar:
5+
order: 2
6+
relatedArticles:
7+
- d2c841f1-78b4-47e0-b899-4d32ae857e0a
8+
- 961dea3c-d8e2-47a0-8ab7-deabdb2d6a01
9+
- 65d72460-e870-4d6a-a1ea-35740ca0e2cc
10+
---
11+
12+
This guide shows you how to create a Machine-to-Machine (M2M) application in Kinde, authorize it for an API, and use the client credentials flow to get a token and make a secure API request.
13+
14+
## Step 1 - Create a machine-to-machine app
15+
16+
1. Go to the **Applications** section in your Kinde dashboard
17+
2. Select **Machine-to-machine apps**
18+
3. Choose **Add M2M application**
19+
4. Enter a name
20+
21+
## Step 2 - Create an API in Kinde (if you don't have one)
22+
23+
You can skip this step if you already have an API registered in Kinde.
24+
25+
1. Go to the **APIs** section in your Kinde dashboard
26+
2. Select **Add API**
27+
3. Enter a name
28+
4. Select **Save**
29+
30+
For more detail, see [Register and manage APIs](/developer-tools/your-apis/register-manage-apis/).
31+
32+
## Step 3 - Authorize the app to access an API
33+
34+
1. Open your newly created app
35+
2. Go to the **APIs** tab
36+
3. Select the API (audience) this app should be allowed to call.
37+
4. Select **Save**.
38+
39+
If you skip this step, token requests will be rejected.
40+
41+
## Step 4 - (Optional) Add scopes
42+
43+
If your API uses scopes to define permissions:
44+
45+
1. Go to **APIs** in your Kinde dashboard
46+
2. Choose the API you’re protecting
47+
3. Add scopes (e.g. `read:users`, `write:flags`)
48+
4. Go back to your M2M app and assign those scopes
49+
50+
For more detail, see [Define and manage API scopes](/developer-tools/your-apis/api-scopes-m2m-applications/).
51+
52+
## Step 5 - Get a token
53+
54+
You can test the app in one of two ways:
55+
56+
### Option A - Use the Test tab in Kinde
57+
58+
1. Open your M2M app
59+
2. Go to the **Test** tab
60+
3. Select the API (audience)
61+
4. Copy the generated token
62+
63+
### Option B - Use the client credentials flow directly
64+
65+
```bash
66+
curl --request POST 'https://<your-subdomain>.kinde.com/oauth2/token' \
67+
--header 'Content-Type: application/x-www-form-urlencoded' \
68+
--data-urlencode 'grant_type=client_credentials' \
69+
--data-urlencode 'client_id=your-client-id' \
70+
--data-urlencode 'client_secret=your-client-secret' \
71+
--data-urlencode 'audience=<your-api-audience>' \
72+
--data-urlencode 'scope=read:users write:flags'
73+
```
74+
75+
The response will include a bearer token you can use in requests:
76+
77+
```json
78+
{
79+
"access_token": "<token>",
80+
"token_type": "Bearer",
81+
"expires_in": 3600
82+
}
83+
```
84+
85+
## Step 6 - Use the token in an API call
86+
87+
Include the token in the `Authorization` header:
88+
89+
```bash
90+
curl https://your-subdomain.kinde.com/v1/organizations \
91+
-H "Authorization: Bearer <token>"
92+
```
93+
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
page_id: 65d72460-e870-4d6a-a1ea-35740ca0e2cc
3+
title: Token structure and claims
4+
sidebar:
5+
order: 4
6+
relatedArticles:
7+
- 4cb63554-d6b3-45cf-bdad-2fac4790d3aa
8+
- 961dea3c-d8e2-47a0-8ab7-deabdb2d6a01
9+
- d2c841f1-78b4-47e0-b899-4d32ae857e0a
10+
---
11+
12+
Access tokens issued by Kinde to Machine-to-Machine (M2M) applications are JSON Web Tokens (JWTs)that include trusted claims about the app, scopes, and (if applicable) the organization.
13+
14+
This reference explains what those claims are and how to use them securely in your APIs or services.
15+
16+
## How to view token claims
17+
18+
Tokens returned from the client credentials flow can be decoded using any standard JWT library, or online tools like [Kinde's JWT decoder](https://kinde.com/tools/online-jwt-decoder/).
19+
20+
You do **not** need to validate the signature unless you're verifying tokens on your own backend (outside of Kinde-hosted APIs). For most use cases, Kinde validates the token for you when you call our APIs.
21+
22+
## Example token payloads
23+
24+
### Global M2M app
25+
26+
```json
27+
{
28+
"aud": [
29+
"your-api-audience"
30+
],
31+
"azp": "d4d3c5b74e064badb9625a4aa6241bcc",
32+
"exp": 1751237068,
33+
"gty": [
34+
"client_credentials"
35+
],
36+
"iat": 1751150668,
37+
"iss": "https://<your-subdomain>.kinde.com",
38+
"jti": "f95ed3e0-cc4d-40c4-b95a-9971729b0ae5",
39+
"scope": "read:users write:flags",
40+
"scp": [
41+
"read:users",
42+
"write:flags"
43+
],
44+
"v": "2"
45+
}
46+
```
47+
48+
### Org-scoped M2M app
49+
50+
```json
51+
{
52+
"aud": [
53+
"your-api-audience"
54+
],
55+
"azp": "d4d3c5b74e064badb9625a4aa6241bcc",
56+
"exp": 1751237068,
57+
"gty": [
58+
"client_credentials"
59+
],
60+
"iat": 1751150668,
61+
"iss": "https://<your-subdomain>.kinde.com",
62+
"jti": "f95ed3e0-cc4d-40c4-b95a-9971729b0ae5",
63+
"org_code": "org_ba4a2311eb1",
64+
"scope": "read:users write:flags",
65+
"scp": [
66+
"read:users",
67+
"write:flags"
68+
],
69+
"v": "2"
70+
}
71+
```
72+
73+
## Standard claims
74+
75+
| Claim | Description |
76+
|-------|-------------|
77+
| `aud` | The audience for the token. This is the API that the token is intended for. |
78+
| `azp` | The client ID of the M2M app that requested the token. |
79+
| `exp` | The expiration time of the token. |
80+
| `gty` | The grant type for the token. This is always `client_credentials`. |
81+
| `iat` | The issuance time of the token. |
82+
| `iss` | The issuer of the token. This is the Kinde environment URL. |
83+
| `jti` | The unique identifier for the token. |
84+
| `scope` | The scopes granted to the token. |
85+
| `scp` | The list of scopes initially requested |
86+
| `v` | The version of the token. |
87+
88+
## Additional claims for org-scoped apps
89+
90+
| Claim | Description |
91+
|-------|-------------|
92+
| `org_code` | The organization code for the token. |
93+
94+
95+
96+
## Validating and using claims
97+
98+
In your API or backend service, you can use these claims to enforce access:
99+
100+
- Confirm the `aud` matches the expected audience for your API
101+
- If your endpoint is organization-specific (e.g. `/orgs/:org_code/...`), ensure that `org_code` from the token matches the route parameter
102+
- Use `scopes` to implement scope-based access control (e.g. `write:flags` required to enable a feature flag)
103+
104+
## Notes
105+
106+
- Tokens are signed using asymmetric keys (RS256)
107+
- You can retrieve your Kinde environment’s public keys from the [OpenID configuration endpoint](https://your-subdomain.kinde.com/.well-known/openid-configuration)
108+
- Token claims are added by Kinde based on the M2M app’s configuration and assigned scopes — they cannot be overridden in the token request
109+
- You can request multiple audiences
110+
- You can request specific scopes to limit the permissions of the token

0 commit comments

Comments
 (0)