# 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
```


---

# 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://authdocs.skill-mine.com/licentio-documentation/usecases/desktop-sso-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.
