> For the complete documentation index, see [llms.txt](https://authdocs.skill-mine.com/licentio-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://authdocs.skill-mine.com/licentio-documentation/usecases/desktop-sso-integration.md).

# Desktop SSO Integration

To integrate the **Skillmine Auth login page** into a desktop application, you can use either of the following authentication flows:

1. **Browser-Based Authorization Flow**
2. **Device Authorization Flow**

Each flow requires setting up your client in the Skillmine Auth admin portal first.

***

### 🛠️ Prerequisites

Before starting integration:

1. Go to the Skillmine Auth Admin Portal.
2. Create the **Client Settings** and **Blueprint Configuration** using the below documentation:
   * 📄 [Blueprint Settings](https://authdocs.skill-mine.com/licentio-documentation/blueprints)
   * 📄 [Client Settings](https://authdocs.skill-mine.com/licentio-documentation/settings/open-id-connect-setttings/client-settings)
3. Note down the generated `client_id`, `client_secret` (if applicable), and the `baseurl` of your auth instance.

***

### 🌐 Option 1: Browser-Based Authorization Flow

In this method, your desktop app opens the Skillmine Auth login page in the user's default browser and handles the authentication callback.

#### 🔗 Step 1: Generate Authorization URL

Build an authorization URL using the following structure:

```url
  {{baseurl}}/authz-srv/authz?
  client_id=YOUR_CLIENT_ID
  &response_type=token
  &scope=openid%20profile%20user_info_all
  &redirect_uri=YOUR_DESKTOP_REDIRECT_URL
  &groups_info=0
  &response_mode=query
```

🔁 Replace placeholders:

* `client_id`: From Skillmine Auth admin portal
* `redirect_uri`: URL your app listens to for the redirect (can be a custom scheme like `myapp://callback` for native apps)

#### 🖥️ Step 2: Open in Browser

When your desktop app launches and no session is active:

* Open the authorization URL in the user's browser.
* After successful login, the user will be redirected to your app’s redirect URI with either an `access_token` or an authorization `code`.

#### 🔐 Step 3: Token Handling

* If you use `response_type=code`, exchange the code for a token by calling the **Token API**.
* If you use `response_type=token`, the token will be returned directly in the redirect URL.

#### 🔄 Step 4: Session Maintenance

* Periodically call the **Introspection API** to check token validity.
* On logout, call the **Logout API** to properly terminate the session.

#### 📘 Well-Known Endpoint

Fetch available endpoints (token URL, logout URL, etc.):

```
bashCopyEdit{{api_base_url}}/.well-known/openid-configuration
```

This JSON provides all the necessary URLs for token exchange, introspection, and logout.

***

### 🖥️ Option 2: Device Authorization Flow

This flow is ideal for native desktop apps without embedded browsers or with limited input capabilities.

#### 📲 Step 1: Request Device Code

Call the **Device Authorization Endpoint** with your `client_id` and required `scope`. The response will look like:

```json
{
  "device_code": "2fa60989-a880-40b0-a7d1-42c973ff6b51",
  "user_code": "30CATn",
  "verification_uri": "{{api_base_url}}/device/verify",
  "verification_uri_complete": "{{api_base_url}}/device/verify?user_code=30CATn",
  "expires_in": 8600,
  "interval": 5
}
```

#### 💻 Step 2: Display Info to User

Show the following to the user:

* A link to open (`verification_uri_complete`)
* A `user_code` they may need to enter

The user will open the link in a browser, log in via Skillmine Auth, and enter the code if required.

#### 🔁 Step 3: Poll for Status

In the background, your app must poll the **Verification Status Endpoint**:

**POST** `{{baseurl}}/device/code/verification`\
**Body:**

```json
{
  "device_code": "2fa60989-a880-40b0-a7d1-42c973ff6b51"
}
```

Poll at intervals specified in the response (`interval: 5` seconds).

**Possible Responses**

**While Waiting:**

```json
{
  "success": false,
  "code": 400,
  "error": {
    "error": "authorization_pending",
    "error_description": "The provided authorization grant is invalid : authorization_pending"
  }
}
```

**On Success:**

```json
{
  "success": true,
  "code": 200,
  "data": {
    "is_validated": true,
    "validated_time": "2025-06-10T08:06:43.284Z"
  }
}
```

#### ✅ Step 4: Proceed to Dashboard

Once authentication is successful, your app can redirect the user to the main dashboard or start using the token.

***

## Sample : Desktop SSO Integration with Electron using Skillmine Auth

This guide explains how to implement **Single Sign-On (SSO)** in an Electron-based desktop application using **Skillmine Auth**, with token-based authentication and user info retrieval.

### 🧱 Prerequisites

* Access to [Skillmine Auth Admin Portal](https://authdocs.skill-mine.com)
* Valid `client_id` and `redirect_uri`
* Node.js v14+ and Electron installed
* Install dependencies

```
npm install electron open express axios
```

### ⚙️ Step 1: Configure Skillmine Auth

#### ➔ Client Settings

Create a new client in the Skillmine Auth admin panel:

* Allowed Grant Types: `authorization_code`, `implicit`
* Redirect URI: `http://localhost:3000/callback`
* Scopes: `openid profile user_info_all`
* Response Types: `token` (or `code`)

📎 Docs: [Client Settings](https://authdocs.skill-mine.com/licentio-documentation/settings/open-id-connect-setttings/client-settings)

### 📂 Step 2: Sample Electron Code

#### 1. **main.js** (Electron main process)

```javascript
const { app, BrowserWindow } = require('electron');
const express = require('express');
const http = require('http');
const url = require('url');
const axios = require('axios');
const path = require('path');
const open = require('open').default;

const CLIENT_ID = 'your-client-id';
const REDIRECT_URI = 'http://localhost:3000/callback';
const AUTH_BASE_URL = 'https://your-skillmine-auth.com';
const SCOPE = 'openid profile user_info_all';

let mainWindow;

function createMainWindow(userName) {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    }
  });

  mainWindow.loadFile('index.html');
  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.webContents.send('user-welcome', userName);
  });
}

function startSSOFlow() {
  const expressApp = express();
  const server = http.createServer(expressApp);

  expressApp.get('/callback', async (req, res) => {
    const parsedUrl = url.parse(req.url, true);
    const accessToken = parsedUrl.query.access_token;

    try {
      const userinfoUrl = `${AUTH_BASE_URL}/authz-srv/userinfo`;
      const response = await axios.get(userinfoUrl, {
        headers: { Authorization: `Bearer ${accessToken}` }
      });

      const userName = response.data.name || response.data.preferred_username || 'User';
      res.send('<h2>Login successful. You may now close this window.</h2>');
      server.close();

      createMainWindow(userName);
    } catch (error) {
      res.status(500).send('Error fetching user info.');
      server.close();
    }
  });

  server.listen(3000, async () => {
    const authUrl = `${AUTH_BASE_URL}/authz-srv/authz` +
      `?client_id=${CLIENT_ID}` +
      `&response_type=token` +
      `&scope=${encodeURIComponent(SCOPE)}` +
      `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`;

    await open(authUrl);
  });
}

app.whenReady().then(() => {
  startSSOFlow();
});
```

#### 2. **preload.js** (Exposes IPC)

```javascript
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  onUserWelcome: (callback) => ipcRenderer.on('user-welcome', (event, name) => callback(name))
});
```

#### 3. **index.html** (Renderer process UI)

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Skillmine Auth SSO</title>
</head>
<body>
  <h1 id="welcome">Authenticating...</h1>
  <script>
    window.electronAPI.onUserWelcome((name) => {
      document.getElementById('welcome').textContent = `👋 Welcome ${name}`;
    });
  </script>
</body>
</html>
```

### Step 3 : Execution

```
npx electron .
```

### ✅ Summary Flow

```
Electron App Start → Check Session → Open Browser Login → Skillmine Auth → Redirect with Token → Fetch User Info → Show Welcome Message
```
