Package Exports
- solid-oidc
Readme
solid-oidc
Minimal, zero-build Solid-OIDC client for browsers.
A single JavaScript file (~500 lines) that handles the complete Solid-OIDC authentication flow. No bundler, no transpiler, no build step required.
Features
- Zero build step - Just import and use
- Single file - Copy
solid-oidc.jsor import from CDN - ~500 lines - Readable, auditable, hackable
- Full Solid-OIDC - Login, logout, token refresh, authenticated fetch
- DPoP bound tokens - Secure proof-of-possession
- Persistent sessions - Survives page refresh via IndexedDB
- Event-driven - React to session state changes
Quick Start
<!DOCTYPE html>
<html>
<head>
<title>Solid App</title>
</head>
<body>
<button id="login">Login</button>
<button id="logout" hidden>Logout</button>
<pre id="output"></pre>
<script type="module">
import { Session } from 'https://esm.sh/gh/JavaScriptSolidServer/solid-oidc/solid-oidc.js'
const session = new Session({
onStateChange: (e) => {
document.getElementById('login').hidden = e.detail.isActive
document.getElementById('logout').hidden = !e.detail.isActive
document.getElementById('output').textContent = e.detail.isActive
? `Logged in as ${e.detail.webId}`
: 'Not logged in'
}
})
// Try to restore previous session
session.restore().catch(() => {})
// Handle redirect from identity provider
session.handleRedirectFromLogin()
// Login button
document.getElementById('login').onclick = () => {
session.login('https://solidcommunity.net', window.location.href)
}
// Logout button
document.getElementById('logout').onclick = () => {
session.logout()
}
</script>
</body>
</html>Installation
Option 1: CDN (Recommended)
import { Session } from 'https://esm.sh/gh/JavaScriptSolidServer/solid-oidc/solid-oidc.js'Option 2: npm
npm install solid-oidcimport { Session } from 'solid-oidc'Option 3: Copy the file
Just copy solid-oidc.js into your project and import it:
import { Session } from './solid-oidc.js'API Reference
new Session(options)
Create a new session instance.
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.
await session.login('https://solidcommunity.net', window.location.href)Parameters:
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.
await session.handleRedirectFromLogin()session.restore()
Restore a previous session using stored refresh token.
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.
await session.logout()session.authFetch(url, options)
Make an authenticated fetch request. Automatically includes DPoP proof and access token.
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 |
session.addEventListener('sessionStateChange', (event) => {
console.log('Active:', event.detail.isActive)
console.log('WebID:', event.detail.webId)
})Advanced Usage
Custom Session Database
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
If your app has a pre-registered client ID, provide it to skip dynamic registration:
const session = new Session({
clientId: 'https://myapp.example/id'
})Multiple Identity Providers
const providers = [
{ name: 'Solid Community', url: 'https://solidcommunity.net' },
{ name: 'Inrupt PodSpaces', url: 'https://login.inrupt.com' },
{ name: 'solidweb.org', url: 'https://solidweb.org' }
]
// Let user choose
const idp = prompt('Choose provider:', providers[0].url)
await session.login(idp, window.location.href)Handling Token Expiration
const session = new Session({
onExpirationWarning: async (event) => {
console.log(`Token expires in ${event.detail.expires_in}s, refreshing...`)
try {
await session.restore()
} catch {
// Refresh failed, maybe prompt re-login
if (confirm('Session expired. Login again?')) {
await session.login(idp, window.location.href)
}
}
}
})Specifications Implemented
- RFC 6749 - OAuth 2.0
- RFC 7636 - PKCE
- RFC 9207 - Authorization Server Issuer Identification
- RFC 9449 - DPoP (Demonstration of Proof-of-Possession)
- Solid-OIDC - Solid OIDC Specification
Testing
Open test.html in a browser to run the test suite. Tests cover:
- Session instantiation and state management
- SessionDatabase (IndexedDB) operations
- Event dispatching
# Serve locally and open test.html
npx serve .
# Then visit http://localhost:3000/test.htmlBrowser Requirements
- ES Modules (
<script type="module">) crypto.subtle(requires HTTPS or localhost)indexedDB(for session persistence)
Works in all modern browsers (Chrome 63+, Firefox 57+, Safari 11+, Edge 79+).
Credits
Based on solid-oidc-client-browser by uvdsl (Christoph Braun). Refactored into a minimal, zero-dependency, single-file library.
License
MIT