> For the complete documentation index, see [llms.txt](https://decideai.gitbook.io/decideai-whitepaper/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://decideai.gitbook.io/decideai-whitepaper/decide-id-integration/oidc-integration.md).

# OIDC Integration

**DecideID OIDC Integration Guide**

***

#### Overview

DecideID offers a full-featured OpenID Connect (OIDC) provider that enables application developers to integrate proof-of-humanity (PoH) verification and user reputation data into any web or mobile application. Built on the Internet Computer Protocol (ICP), DecideID ensures decentralized identity management with strong privacy guarantees.

***

#### Key Features

* **Proof of Humanity**: Confirm users are unique humans, not bots.
* **Reputation Levels**: Access user trust levels (e.g., Silver, Gold).
* **Decentralized Infrastructure**: Powered by the Internet Computer.
* **Privacy-Centric Design**: User-controlled data consent and access.
* **OIDC Standard Compliance**: Integrates with any OAuth 2.0/OIDC-compatible libraries.

***

#### Supported Scopes

* **poh** — Returns verification status and reputation data.

***

#### Getting Started

**Prerequisites**

* A DecideID developer account
* Familiarity with OAuth 2.0 / OIDC flows
* HTTPS-enabled redirect URIs for production environments

**Available Environments**

* **UI / Authorization Endpoint**: Uses a user-facing canister for login flow.
* **API Endpoint**: Uses the backend canister for token and user data access.

***

#### Developer Portal

**Access the Dashboard**

1. Go to <https://id.decideai.xyz/#/developer>
2. Sign up or log in using your email address.
3. Navigate to the "OIDC Clients" section.

<figure><img src="/files/SziFicJxUxxXFi3327ln" alt=""><figcaption></figcaption></figure>

**Register a New Client**

1. Click **Register New Client**
2. Complete the form:
   * **Client ID**: Unique identifier
   * **App Name**: Display name for user consent screens
   * **Redirect URIs**: Allowed callback URLs (must be HTTPS)
   * **Scopes**: Default scope is `poh`
3. Click **Register Client**
4. Save your **Client ID** and **Client Secret** securely

<figure><img src="/files/wY0eZychCuysEeDdTy4g" alt=""><figcaption></figcaption></figure>

**Manage Clients**

* View registered clients
* *Edit and regenerate client credentials — coming soon*

<figure><img src="/files/vZzffRP1MFfV8AU8i0WD" alt=""><figcaption></figcaption></figure>

***

#### OIDC Authorization Code Flow

1. **Authorization Request**: Redirect user to authorization endpoint
2. **User Consent**: User reviews and grants permissions
3. **Authorization Code**: Returned to your app’s redirect URI
4. **Token Exchange**: Use code to retrieve access and ID tokens
5. **User Info**: Use access token to retrieve identity details

***

#### API Reference

**Base URL (Production)**

```
https://rlz47-aqaaa-aaaah-qdcra-cai.icp0.io
```

**OpenID Configuration**

```
GET /.well-known/openid-configuration
```

Returns:

```json
{
  "issuer": "https://id.decideai.xyz",
  "authorization_endpoint": "https://id.decideai.xyz/#/authorize",
  "token_endpoint": "https://rlz47-aqaaa-aaaah-qdcra-cai.icp0.io/token",
  "userinfo_endpoint": "https://rlz47-aqaaa-aaaah-qdcra-cai.icp0.io/userinfo",
  "jwks_uri": "https://rlz47-aqaaa-aaaah-qdcra-cai.icp0.io/.well-known/jwks.json",
  "response_types_supported": ["code"],
  "subject_types_supported": ["public"],
  "id_token_signing_alg_values_supported": ["ES256K"]
}
```

**JWKS**

```
GET /.well-known/jwks.json
```

Returns JSON Web Keys for validating ID tokens.

***

#### Authorization Request

```
GET /authorize
```

Required query parameters:

* `client_id`
* `redirect_uri`
* `response_type=code`
* `scope=poh`
* `state=random-string`

**Example:**

```
https://id.decideai.xyz/#/authorize?client_id=my-app&redirect_uri=https%3A%2F%2Fmyapp.com%2Fcallback&response_type=code&scope=poh&state=xyz123
```

***

#### Token Exchange

```
POST /token
```

**Headers:**

```
Content-Type: application/x-www-form-urlencoded
```

**Body:**

```
grant_type=authorization_code&code=CODE&client_id=ID&client_secret=SECRET&redirect_uri=URI
```

**Response:**

```json
{
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "poh",
  "id_token": "..."
}
```

***

#### User Info Endpoint

```
GET /userinfo?scope=poh
```

**Headers:**

```
Authorization: Bearer ACCESS_TOKEN
```

**Response (scope = poh):**

Response Object

* sub - A unique user id attatched the user
* verified - Whether the user currently has a valid proof of humanity credential.&#x20;
* reputation\_level - The users current reputation level
  * gold: **The highest reputation level**. Requires a reverification of the account at least once. Note, we will assign "gold" status for 2 weeks for new accounts and then they will transition to "silver" this is so that we don't penalize new accounts. In the future these rules may change.
  * silver: Users are automatically downgraded to silver after two weeks, requiring reverification to regain gold status.&#x20;
* verification\_date - The date the user last perfromed a verification. Not necessarily a successful verification.&#x20;

```json
{
  "sub": "unique-user-id",
  "verified": true, // If they are currently verified
  "reputation_level": "gold", // Either "gold" or "silver"
  "verification_date": "2024-01-15T10:30:00Z" // When they were last verified
}
```

***

#### Token Structure Example (Decoded JWT)

**ID Token**

```json
{
  "iss": "https://id.decideai.xyz",
  "sub": "user-unique-id",
  "aud": "your-client-id",
  "exp": 1712345678,
  "iat": 1712341678,
  "scope": "poh"
}
```

**Access Token (Example payload)**

```json
{
  "sub": "user-unique-id",
  "verified": true,
  "reputation_level": "Silver"
}
```

***

#### Sample App: Node.js + Express

```javascript
const express = require('express');
const axios = require('axios');
const qs = require('querystring');
const app = express();

const CLIENT_ID = 'YOUR_CLIENT_ID';
const CLIENT_SECRET = 'YOUR_CLIENT_SECRET';
const REDIRECT_URI = 'https://yourapp.com/callback';

// STEP 1: Redirect user to the authorization screen
app.get('/login', (req, res) => {
  const authUrl = `https://id.decideai.xyz/#/authorize?client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&response_type=code&scope=poh&state=random123`;
  res.redirect(authUrl);
});

// STEP 2: Handle the redirect URI callback with authorization code
app.get('/callback', async (req, res) => {
  const { code } = req.query;
  const tokenUrl = 'https://rlz47-aqaaa-aaaah-qdcra-cai.icp0.io/token';

  try {
    // STEP 3: Exchange authorization code for access + ID tokens
    const tokenResponse = await axios.post(tokenUrl, qs.stringify({
      grant_type: 'authorization_code',
      code,
      redirect_uri: REDIRECT_URI,
      client_id: CLIENT_ID,
      client_secret: CLIENT_SECRET
    }), {
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
    });

    const { access_token, id_token } = tokenResponse.data;

    // STEP 4: Use the access token to fetch user's PoH verification status
    const userInfoResponse = await axios.get('https://rlz47-aqaaa-aaaah-qdcra-cai.icp0.io/userinfo?scope=poh', {
      headers: {
        Authorization: `Bearer ${access_token}`
      }
    });

    // STEP 5: Display user info result (or pass to your frontend/session)
    res.json({
      id_token,
      user_info: userInfoResponse.data
    });

  } catch (error) {
    console.error('Error during callback handling:', error.response?.data || error.message);
    res.status(500).send('OIDC login failed');
  }
});

app.listen(3000, () => console.log('App running on http://localhost:3000'));
```

#### Consent Screen Preview

When users are redirected to the authorization endpoint, they see a branded DecideID login and authorization interface.

**Step 1: Sign In Screen**

* Branded with the DecideID logo and name.
* Shows the requesting app (e.g., OpenChat).
* Prompts users to continue with Internet Identity.
* Includes an option to create a new DecideID account if the user doesn’t already have one.

**Step 2: Authorization Screen**

* Clearly states that the application wants access to your DecideID account.
* Lists the specific permissions requested (e.g., Proof of Humanity verification status).
* Provides "Authorize" and "Cancel" buttons.
* Displays a reminder that access can be revoked at any time via account settings.

Screenshots:<br>

<figure><img src="/files/lDjHSiFLXfbAhO67frWa" alt=""><figcaption><p>Authorization request with Login</p></figcaption></figure>

<figure><img src="/files/I08syOCsBYWTROddAPJg" alt=""><figcaption><p>Authorization prompt with permission summary</p></figcaption></figure>

***

#### Error Handling

**Format:**

```json
{
  "error": "error_code",
  "error_description": "Explanation"
}
```

**Common Errors**

* **invalid\_client**: Check client credentials
* **invalid\_grant**: Authorization code expired or invalid
* **invalid\_request**: Redirect URI mismatch
* **invalid\_scope**: Scope not recognized (currently only `poh` is supported)

***

#### Testing & Debugging

* Use the development environment for integration testing
* Walk through the full flow manually
* Validate JWTs using the JWKS endpoint
* Check for HTTPS and URI mismatches
* Log non-sensitive API responses for diagnostics

***

#### Security Best Practices

* Never expose `client_secret` in frontend code
* Always use HTTPS for redirects
* Validate the `state` parameter for CSRF protection
* Use secure storage for tokens
* Implement token expiration handling

***

#### Support

* [Official Documentation](https://id.decideai.xyz/#/developer)
* Refer to [OIDC Specs](https://openid.net/specs/)
* Contact the DecideID support team for integration issues
