---
title: Sign in with Inth
description: Let people sign in to your app with their Inth account. Each person
  approves what your app can read or change. Inth uses OAuth 2.1 and OpenID
  Connect.
seoTitle: Add Sign in with Inth to your app with OAuth 2.1 and OpenID Connect
lastModified: "2026-11-08T15:11:52Z"
---
Let people sign in to your app with their Inth account. You do not store an Inth password. Each person approves the access that your app gets. They can remove that access at any time.

Inth is an OAuth 2.1 and OpenID Connect provider. Most OAuth libraries need only three values to connect to Inth. These values are the issuer URL, a client ID, and a client secret.

## How do I get a client ID?

Inth registers each partner app by hand. To ask for a client ID, send an email to [support@inth.com](mailto:support@inth.com). If your team has a shared Slack channel with Inth, you can send a message there. Include this data:

* The name of your app and the URL of its website.
* An HTTPS link to your logo.
* HTTPS links to your privacy policy and your terms of service.
* Each redirect URI for your app.
* The scopes that your app needs.
* The client type: confidential or public.

Each redirect URI must use HTTPS. For local tests, you can use `http://localhost` or `http://127.0.0.1`. A redirect URI cannot have a fragment.

Use a confidential client when your server does the token exchange. Use a public client for a mobile or desktop app that cannot keep a secret.

A browser app must do the token exchange on its server. The token endpoint does not accept calls from JavaScript on other websites.

Inth sends you a client ID. A confidential client also gets a client secret. Keep the client secret on your server. Do not put it in browser code or in a mobile app.

The Inth consent screen shows your app name, logo, and website. It also shows a **Verified by Inth** badge. Each person sees this data before they approve your app. Inth keeps your privacy policy and terms of service on record. The consent screen does not show them.

## Which endpoints do I use?

If your library supports OpenID Connect discovery, give it the issuer URL. The library finds the other endpoints.

|Endpoint|URL|
|--|--|
|Issuer|`https://inth.com/api/auth`|
|Discovery|`https://inth.com/api/auth/.well-known/openid-configuration`|
|Authorization|`https://inth.com/api/auth/oauth2/authorize`|
|Token|`https://inth.com/api/auth/oauth2/token`|
|User info|`https://inth.com/api/auth/oauth2/userinfo`|
|Signing keys (JWKS)|`https://inth.com/api/auth/jwks`|
|Revocation|`https://inth.com/api/auth/oauth2/revoke`|

Partner apps cannot use the `end_session_endpoint` from the discovery document. To disconnect a person, [revoke the refresh token](#how-do-i-disconnect-a-person-from-my-app).

## How do I add sign-in?

Inth supports the authorization code flow. All clients must use PKCE with the `S256` method. This rule applies to confidential clients too.

Each call in this flow sends `resource=https://api.inth.com`. This parameter tells Inth to issue an access token for the Inth API. The Inth API refuses an access token without it.

1. Make a random code verifier. Make its `S256` code challenge.
2. Make a random `state` value. Keep it with the code verifier for this sign-in.
3. Send the person to the authorization endpoint:

```txt
https://inth.com/api/auth/oauth2/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://app.example.com/oauth/callback
  &scope=openid profile email offline_access projects.read
  &state=YOUR_STATE
  &code_challenge=YOUR_CODE_CHALLENGE
  &code_challenge_method=S256
  &resource=https://api.inth.com
```

4. The person signs in to Inth. Then they approve the scopes for your app.
5. Inth sends the person to your redirect URI with `code`, `state`, and `iss`.
6. Make sure that `state` is the value that you sent in step 3.
7. Make sure that `iss` is `https://inth.com/api/auth`.
8. Send the code to the token endpoint. Include the code verifier:

```sh
curl https://inth.com/api/auth/oauth2/token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -d grant_type=authorization_code \
  -d code=THE_CODE \
  -d redirect_uri=https://app.example.com/oauth/callback \
  -d code_verifier=YOUR_CODE_VERIFIER \
  -d resource=https://api.inth.com
```

A public client has no client secret. It sends `client_id` in the request body instead of `-u`.

9. Validate the ID token. Check its signature with the keys from the JWKS endpoint. Then make sure that `iss` is `https://inth.com/api/auth`, `aud` is your client ID, and `exp` is in the future.
10. Use the `sub` claim as the ID of the person in your app. Do not use the email address as the ID, because a person can change it.

## Which scopes can my app ask for?

Ask for only the scopes that your app uses. The consent screen tells the person, in one sentence, what your app can read or change. Your app can ask for only the scopes that Inth registered for your client.

|Scope|What your app gets|
|--|--|
|`openid`|The person's Inth ID (`sub`). All clients must ask for it.|
|`profile`|The person's name and profile image.|
|`email`|The person's email address.|
|`offline_access`|A refresh token. Without it, the person must sign in again after 15 minutes.|
|`organizations.read`|The organizations of the person.|
|`projects.read`|Projects, their consent configuration, and the vendors seen on them.|

The discovery document lists all scopes in `scopes_supported`. Tell us which scopes you need when you ask for your client ID.

## How do I find the organizations of a person?

Ask for the `organizations.read` scope. Then send the access token to the Inth API:

```sh
curl https://api.inth.com/v1/organizations \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

The response lists each organization of the person, with the role of the person in it.

## How do I call the Inth API?

Send the access token in the `Authorization` header:

```sh
curl https://api.inth.com/v1/projects \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

The API accepts a request only when the token has the scope for it. Read the [REST API reference](/docs/rest-api) for each endpoint and its scope.

## How do I keep a person signed in?

An access token expires after 15 minutes. Use the refresh token to get a new access token:

```sh
curl https://inth.com/api/auth/oauth2/token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -d grant_type=refresh_token \
  -d refresh_token=REFRESH_TOKEN \
  -d resource=https://api.inth.com
```

A public client sends `client_id` in the request body instead of `-u`.

Each refresh response has a new refresh token. Save it. Do not use the old refresh token again.

A refresh does not add scopes. To get more scopes, send the person through sign-in again.

## What happens when a person removes access?

A person can remove your app in the Inth Dashboard, on **Account** > **Security** > **Connected apps**. This list shows your app while it has a refresh token for that person. After the person removes your app, your next refresh fails with `invalid_grant`. Send the person through sign-in again.

The current access token stays valid until it expires. This time is 15 minutes or less.

## How do I disconnect a person from my app?

When a person disconnects Inth in your app, revoke the refresh token:

```sh
curl https://inth.com/api/auth/oauth2/revoke \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -d token=REFRESH_TOKEN \
  -d token_type_hint=refresh_token
```

A public client sends `client_id` in the request body instead of `-u`.

Then delete the tokens that you keep for that person.
