# /api/auth/session (dashboard)

Source-derived dashboard endpoint contract, authentication, request validation, responses, and errors.

Source: https://docs.minds.sh/docs/api/platform/reference/dashboard--api-auth-session



This is the **dashboard** service route. Its origin and authentication are described in [Platform API overview](/docs/api/platform) and [Authentication](/docs/api/platform/authentication). A path shared by another service is a different endpoint.

| Property                       | Contract                                                                       |
| ------------------------------ | ------------------------------------------------------------------------------ |
| Methods                        | GET                                                                            |
| Path                           | `/api/auth/session`                                                            |
| Path parameters                | None                                                                           |
| Query parameters read in route | None read directly; schema validation below may define additional fields       |
| Headers read in route          | No additional direct header reads; authentication helpers may read credentials |

## Authentication and access [#authentication-and-access]

OAuth browser flow using HTTP-only l1fe\_\* cookies. Exchange/refresh/logout have endpoint-specific inputs and rate limits.

## Method behavior [#method-behavior]

The handler excerpt preserves field validation, response envelopes, cookie changes, and exception branches. Values returned by service helpers retain their named response type above; for passthrough routes, the upstream response is authoritative.

### GET [#get]

```typescript
export async function GET(request: NextRequest): Promise<NextResponse> {
  // Rate limit: 60 session checks per minute per IP
  const clientIp = getClientIp(request);
  if (!checkRateLimit(clientIp, 'session')) {
    return NextResponse.json(
      { error: 'rate_limited', error_description: 'Too many requests. Please try again later.' },
      { status: 429 }
    );
  }

  const cookieStore = await cookies();
  const accessToken = cookieStore.get('l1fe_access_token')?.value;

  if (!accessToken) {
    return NextResponse.json({ authenticated: false }, { status: 401 });
  }

  // Fetch user info from Auth v4's userinfo endpoint (server-to-server)
  try {
    const userInfoResponse = await fetch(`${SSO_URL}/v4/oauth/userinfo`, {
      headers: { Authorization: `Bearer ${accessToken}` },
    });

    if (!userInfoResponse.ok) {
      // Token is invalid or expired — clear cookies
      const response = NextResponse.json(
        { authenticated: false, reason: 'token_invalid' },
        { status: 401 }
      );
      response.cookies.delete('l1fe_access_token');
      response.cookies.delete('l1fe_refresh_token');
      response.cookies.delete('l1fe_id_token');
      return response;
    }

    const userInfo = await userInfoResponse.json();

    return NextResponse.json({
      authenticated: true,
      user: {
        id: userInfo.sub,
        email: userInfo.email,
        name: userInfo.name,
        picture: userInfo.picture,
        emailVerified: userInfo.email_verified,
      },
      // Expose only non-sensitive session metadata to the client
      expiresAt: cookieStore.get('l1fe_expires_at')?.value || null,
    });
  } catch (err) {
    console.error('Session check failed:', err);
    return NextResponse.json(
      { authenticated: false, reason: 'session_check_failed' },
      { status: 500 }
    );
  }
}
```

Source: `minds-ui/apps/app/app/api/auth/session/route.ts:21`.

## Response and error branches [#response-and-error-branches]

Literal HTTP statuses in the route: 401, 429, 500. Shared management error classes are defined in [Errors and responses](/docs/api/platform/errors).

```typescript
NextResponse.json(
      { error: 'rate_limited', error_description: 'Too many requests. Please try again later.' },
      { status: 429 }
    )
```

Source: `minds-ui/apps/app/app/api/auth/session/route.ts:25`.

```typescript
NextResponse.json({ authenticated: false }, { status: 401 })
```

Source: `minds-ui/apps/app/app/api/auth/session/route.ts:35`.

```typescript
NextResponse.json(
        { authenticated: false, reason: 'token_invalid' },
        { status: 401 }
      )
```

Source: `minds-ui/apps/app/app/api/auth/session/route.ts:46`.

```typescript
userInfoResponse.json()
```

Source: `minds-ui/apps/app/app/api/auth/session/route.ts:56`.

```typescript
NextResponse.json({
      authenticated: true,
      user: {
        id: userInfo.sub,
        email: userInfo.email,
        name: userInfo.name,
        picture: userInfo.picture,
        emailVerified: userInfo.email_verified,
      },
      // Expose only non-sensitive session metadata to the client
      expiresAt: cookieStore.get('l1fe_expires_at')?.value || null,
    })
```

Source: `minds-ui/apps/app/app/api/auth/session/route.ts:58`.

```typescript
NextResponse.json(
      { authenticated: false, reason: 'session_check_failed' },
      { status: 500 }
    )
```

Source: `minds-ui/apps/app/app/api/auth/session/route.ts:72`.

## Evidence [#evidence]

Generated from the local source snapshot on 2026-09-12. This page documents implemented code and does not certify a deployed service, permissions configuration, or successful provider operation.

Source file: `minds-ui/apps/app/app/api/auth/session/route.ts`. SHA-256: `9eefed22e1990047342fc2c5cc062989d9947ff690aced202da0dffe206f189f`.
