# 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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://decideai.gitbook.io/decideai-whitepaper/decide-id-integration/oidc-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
