# Remote MCP Device Authentication and OAuth Flow: Complete Implementation Guide

> Implement secure remote device authentication and OAuth 2.0 flow for headless devices. Learn how users authorize access via a separate browser session.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: how-to-guide
- Published: 2026-08-01

---

**Remote MCP uses the OAuth 2.0 Device Authorization Grant to authenticate headless devices through a secure polling mechanism where users authorize access via a separate browser session.**

The wonderwhy-er/DesktopCommanderMCP repository implements a robust authentication system for remote devices using the OAuth 2.0 Device Authorization Grant. This Remote MCP device authentication flow enables secure access for headless or input-constrained devices by delegating user interaction to a secondary browser session. According to the source documentation in [`src/remote-device/README.md`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/remote-device/README.md), the implementation follows the official OAuth 2.0 specification to ensure strong security guarantees while maintaining a simple user experience.

## How the OAuth 2.0 Device Flow Works in Remote MCP

The Remote MCP device authentication process follows the standard OAuth 2.0 Device Authorization Grant through five distinct phases. Each phase ensures that devices without browsers or input capabilities can securely obtain access tokens.

1. **Device initiates login** – The client sends a `POST /device/code` request to the server's *device-code* endpoint. The response includes a **device code**, **user code**, and verification URL.
2. **User authorizes** – The user opens the verification URL on any browser, enters the short-lived user code, and signs in with their account.
3. **Device polls for token** – While the user authorizes, the client repeatedly polls `POST /token` with the device code at the specified interval (typically every 5 seconds). Once authorization completes, the server returns an **access token**.
4. **Secure channel establishment** – The client stores the access token locally in encrypted storage for subsequent API calls.
5. **Token renewal** – If provided, the client uses a **refresh token** to silently obtain new access tokens before expiration.

## Client-Side Implementation: Requesting Device Codes

In [`src/auth/deviceAuth.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/auth/deviceAuth.ts), the client-side logic handles the initial device code request and token polling. The `startDeviceAuth()` function initiates the flow, while `pollForToken()` manages the polling loop.

### Initiating the Authentication Flow

The following TypeScript implementation demonstrates how the Remote MCP client requests a device code and begins the polling process:

```typescript
import { startDeviceAuth } from './auth/deviceAuth';

async function initRemoteMcp() {
  // Trigger the device‑code request
  const { device_code, user_code, verification_uri, expires_in, interval } =
    await startDeviceAuth();

  console.log(`Visit ${verification_uri} and enter code: ${user_code}`);

  // Poll for the token
  const token = await pollForToken(device_code, interval);
  // Store token securely (e.g., encrypted local storage)
  await saveToken(token);
}

```

## Server-Side Implementation: Handling Device Codes and Tokens

The server implementation in [`src/server/routes/device.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server/routes/device.ts) manages the device code lifecycle and token issuance. This includes generating unique codes, validating user authorization status, and issuing bearer tokens.

### Generating Device and User Codes

When a device initiates authentication, the server generates a UUID-based device code and a human-readable user code. The `deviceCodeHandler` function in [`src/server/routes/device.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server/routes/device.ts) persists these mappings with expiration timestamps:

```typescript
import { v4 as uuidv4 } from 'uuid';
import { addDeviceCode } from './store';

export async function deviceCodeHandler(req, res) {
  const deviceCode = uuidv4();
  const userCode = generateHumanReadableCode(); // e.g., “ABCD‑EFGH”
  const verificationUri = `${process.env.BASE_URL}/device`;

  // Persist the mapping with an expiration timestamp
  await addDeviceCode({
    deviceCode,
    userCode,
    expiresAt: Date.now() + 10 * 60 * 1000, // 10 min
  });

  res.json({
    device_code: deviceCode,
    user_code: userCode,
    verification_uri: verificationUri,
    expires_in: 600,
    interval: 5,
  });
}

```

### Processing Token Polling Requests

The `tokenHandler` function validates device codes and returns access tokens once the user completes authorization. Stored in [`src/server/routes/device.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server/routes/device.ts), this endpoint handles the polling requests from waiting devices:

```typescript
import { getDeviceCodeEntry, generateAccessToken } from './store';

export async function tokenHandler(req, res) {
  const { device_code } = req.body;
  const entry = await getDeviceCodeEntry(device_code);

  if (!entry) return res.status(400).json({ error: 'invalid_device_code' });
  if (Date.now() > entry.expiresAt) return res.status(400).json({ error: 'expired_token' });
  if (!entry.authorized) return res.status(428).json({ error: 'authorization_pending' });

  const accessToken = generateAccessToken(entry.userId);
  res.json({ access_token: accessToken, token_type: 'Bearer', expires_in: 3600 });
}

```

## Secure Token Storage and Session Management

After obtaining an access token, the Remote MCP client stores credentials securely using encrypted local storage. The `saveToken()` function ensures that bearer tokens remain accessible for authenticated API calls while protecting against local extraction attacks. If the server issues a refresh token during the `tokenHandler` exchange, the client can silently renew sessions without requiring repeated user authorization.

## Key Files in the DesktopCommanderMCP Repository

The following source files define the end-to-end authentication mechanism in the wonderwhy-er/DesktopCommanderMCP repository:

- **[`src/remote-device/README.md`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/remote-device/README.md)** – Overview of the remote device feature and OAuth flow description
- **[`src/auth/deviceAuth.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/auth/deviceAuth.ts)** – Client-side helpers that request device codes and poll for access tokens
- **[`src/server/routes/device.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server/routes/device.ts)** – Server-side endpoints that issue device codes and exchange them for tokens
- **[`src/server/store.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server/store.ts)** – Persistence layer for device-code mappings and token storage
- **[`package.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/package.json)** – Lists OAuth-related dependencies such as `axios` and `jsonwebtoken`

## Summary

Remote MCP device authentication implements the OAuth 2.0 Device Authorization Grant to securely connect headless devices to the DesktopCommanderMCP service. Key implementation details include:

- The **device flow** separates user interaction from device authentication by using short-lived user codes and verification URLs
- **`startDeviceAuth()`** in [`src/auth/deviceAuth.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/auth/deviceAuth.ts) initiates the flow while **`pollForToken()`** handles the polling loop
- Server endpoints in **[`src/server/routes/device.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server/routes/device.ts)** manage code generation, validation, and token issuance
- Tokens are stored in **encrypted local storage** with support for silent renewal via refresh tokens
- The 10-minute expiration window for device codes ensures security while allowing adequate time for user authorization

## Frequently Asked Questions

### What is the OAuth 2.0 Device Authorization Grant?

The OAuth 2.0 Device Authorization Grant is a protocol designed for devices that lack browsers or input methods, such as IoT devices or CLI tools. It allows these devices to obtain access tokens by having users complete authorization on a separate device with a browser, such as a smartphone or laptop.

### How long does the device code remain valid in Remote MCP?

According to the implementation in [`src/server/routes/device.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server/routes/device.ts), device codes expire after **10 minutes** (600 seconds). The `expiresAt` timestamp is set to `Date.now() + 10 * 60 * 1000` when the code is generated, providing users with sufficient time to complete authentication.

### What happens if the user doesn't authorize the device before expiration?

If the user fails to authorize the device before the 10-minute window closes, the `tokenHandler` returns an `expired_token` error with HTTP status 400. The device must then restart the authentication flow by requesting a new device code through `startDeviceAuth()`.

### Can Remote MCP refresh access tokens without user interaction?

Yes, if the initial token exchange provides a refresh token, the Remote MCP client can silently obtain new access tokens before the current one expires. This keeps the remote device online indefinitely without requiring repeated user authorization, as implemented in the token storage logic of [`src/auth/deviceAuth.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/auth/deviceAuth.ts).