# solid-oidc
[](https://www.npmjs.com/package/solid-oidc)
[](LICENSE)
[](#)
[](#)
**Minimal, zero-build, zero-dependency Solid-OIDC client for browsers.**
A single JavaScript file (~700 lines, 4kb gzipped) that handles the complete Solid-OIDC authentication flow. No bundler, no transpiler, no build step, no npm dependencies. Uses the Web Crypto API natively.
[**Live Demo**](https://javascriptsolidserver.github.io/solid-oidc/example.html) · [**API Reference**](#api-reference) · [**Examples**](#advanced-usage)
---
## Why solid-oidc?
| Feature | solid-oidc | @inrupt/solid-client-authn-browser | @inrupt/oidc-client |
|---------|------------|-----------------------------------|---------------------|
| **Unpacked size** | 34kb | 1,697kb | 18,704kb |
| **Gzipped** | 4kb | ~170kb | ~2MB |
| **Files in package** | 1 | 92 | 100+ |
| **Lines of code** | ~700 | thousands | thousands |
| **Dependencies** | 0 | 5 (+transitive) | 5 (+transitive) |
| **Build step** | None | Rollup | Required |
| **Copy-paste ready** | Yes | No | No |
| **Readable source** | Yes | Compiled/minified | Compiled |
| **Browser native crypto** | Yes (Web Crypto) | No (jose, uuid, events) | No (crypto-js, core-js) |
| **License** | AGPL-3.0 | MIT | MIT |
## Features
- **Zero dependencies** — Pure Web Crypto API, nothing to install
- **Zero build step** — Import from CDN or copy the file
- **Single file** — One `solid-oidc.js`, nothing else
- **~700 lines, 4kb gzipped** — Readable, auditable, hackable
- **Full Solid-OIDC** — Login, logout, token refresh, authenticated fetch
- **DPoP bound tokens** — Secure proof-of-possession (RFC 9449)
- **Persistent sessions** — Survives page refresh via IndexedDB
- **Event-driven** — React to session state changes
---
## Quick Start
```html
Solid App
```
**That's it.** No npm install, no webpack, no configuration.
---
## Installation
### Option 1: CDN (Recommended)
```js
import { Session } from 'https://esm.sh/gh/JavaScriptSolidServer/solid-oidc/solid-oidc.js'
```
### Option 2: npm
```bash
npm install solid-oidc
```
```js
import { Session } from 'solid-oidc'
```
### Option 3: Copy the file
Download [`solid-oidc.js`](solid-oidc.js) and import it directly:
```js
import { Session } from './solid-oidc.js'
```
---
## API Reference
### `new Session(options)`
Create a new session instance.
```js
const session = new Session({
// Optional: Pre-registered client_id (skips dynamic registration)
clientId: 'https://myapp.example/id',
// Optional: Custom database for session persistence
database: new SessionDatabase('my-app'),
// Optional: Event callbacks
onStateChange: (event) => console.log(event.detail),
onExpirationWarning: (event) => console.log('Expiring in', event.detail.expires_in),
onExpiration: () => console.log('Session expired')
})
```
### `session.login(idp, redirectUri)`
Redirect user to identity provider for authentication.
```js
await session.login('https://solidcommunity.net', window.location.href)
```
| Parameter | Description |
|-----------|-------------|
| `idp` | Identity provider URL (e.g., `https://solidcommunity.net`) |
| `redirectUri` | URL to redirect back to after login |
### `session.handleRedirectFromLogin()`
Handle the redirect from the identity provider. Call this on page load.
```js
await session.handleRedirectFromLogin()
```
### `session.restore()`
Restore a previous session using stored refresh token.
```js
try {
await session.restore()
console.log('Session restored')
} catch (error) {
console.log('No session to restore')
}
```
### `session.logout()`
End the session and clear all stored data.
```js
await session.logout()
```
### `session.authFetch(url, options)`
Make an authenticated fetch request. Automatically includes DPoP proof and access token.
```js
const response = await session.authFetch('https://pod.example/private/data.ttl')
const data = await response.text()
```
Falls back to regular `fetch()` if no session is active.
### Properties
| Property | Type | Description |
|----------|------|-------------|
| `session.isActive` | `boolean` | Whether user is logged in |
| `session.webId` | `string \| null` | User's WebID when logged in |
### Methods
| Method | Returns | Description |
|--------|---------|-------------|
| `session.isExpired()` | `boolean` | Whether access token is expired |
| `session.getExpiresIn()` | `number` | Seconds until token expires (-1 if no token) |
### Events
The session extends `EventTarget` and emits these events:
| Event | Detail | Description |
|-------|--------|-------------|
| `sessionStateChange` | `{ isActive, webId }` | Login/logout occurred |
| `sessionExpirationWarning` | `{ expires_in }` | Token refresh failed but not expired |
| `sessionExpiration` | — | Token expired and refresh failed |
```js
session.addEventListener('sessionStateChange', (event) => {
console.log('Active:', event.detail.isActive)
console.log('WebID:', event.detail.webId)
})
```
---
## Advanced Usage
### Custom Session Database
```js
import { Session, SessionDatabase } from './solid-oidc.js'
// Use a custom database name (useful for multiple sessions)
const database = new SessionDatabase('my-app-session')
const session = new Session({ database })
```
### Pre-registered Client ID
Skip dynamic registration by providing your client ID:
```js
const session = new Session({
clientId: 'https://myapp.example/id'
})
```
### Multiple Identity Providers
```js
const providers = [
{ name: 'Solid Community', url: 'https://solidcommunity.net' },
{ name: 'solidweb.org', url: 'https://solidweb.org' },
{ name: 'solidweb.me', url: 'https://solidweb.me' }
]
// Let user choose
const idp = prompt('Choose provider:', providers[0].url)
await session.login(idp, window.location.href)
```
### Handling Token Expiration
```js
const session = new Session({
onExpirationWarning: async (event) => {
console.log(`Token expires in ${event.detail.expires_in}s, refreshing...`)
try {
await session.restore()
} catch {
if (confirm('Session expired. Login again?')) {
await session.login(idp, window.location.href)
}
}
}
})
```
---
## Specifications
This library implements:
| Specification | Description |
|---------------|-------------|
| [RFC 6749](https://tools.ietf.org/html/rfc6749) | OAuth 2.0 |
| [RFC 7636](https://tools.ietf.org/html/rfc7636) | PKCE |
| [RFC 9207](https://tools.ietf.org/html/rfc9207) | Authorization Server Issuer Identification |
| [RFC 7638](https://tools.ietf.org/html/rfc7638) | JWK Thumbprint |
| [RFC 9449](https://tools.ietf.org/html/rfc9449) | DPoP (Demonstration of Proof-of-Possession) |
| [Solid-OIDC](https://solidproject.org/TR/oidc) | Solid OIDC Specification |
---
## Testing
Open [`test.html`](test.html) in a browser to run the test suite:
```bash
npx serve .
# Visit http://localhost:3000/test.html
```
Tests cover:
- Session instantiation and state management
- SessionDatabase (IndexedDB) operations
- Event dispatching
---
## Browser Support
| Requirement | Notes |
|-------------|-------|
| ES Modules | `