You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
5.1 KiB
Markdown

# swissoid-back
SwissOID authentication backend for Node.js applications. Provides reusable OIDC authentication components for integrating with SwissOID (Swiss eID).
## Features
- 🔐 Full OIDC Authorization Code Flow implementation
- 🍪 Session management with Redis
- 🔑 JWT verification with JWKS (for validating SwissOID ID tokens and optional DATs)
- 🎯 Built for di-why dependency injection
- 📦 Reusable authentication components
- 🔄 Configurable via environment variables or appConfig
## Installation
```bash
npm install swissoid-back
```
## Requirements
- Node.js >= 18
- Redis server for session storage
- SwissOID client credentials
## Usage
### With express-knifey / graphql-knifey (Recommended)
`swissoid-back` integrates with `express-knifey` middleware handles so gateways/standalone services can share the same DI wiring used across Cronide:
```typescript
import DiContainer, { mergeLDs } from 'di-why';
import { apolloSubgraphServerModularLDGen } from 'graphql-knifey';
import { swissoidAuthLoadDict } from 'swissoid-back';
// Define middleware configuration including OIDC routes
const middlewareConfig = {
global: [
{ name: 'expressCorsMiddleware', priority: 90 },
{ name: 'expressCookieParserMiddleware', priority: 80 },
{ name: 'expressBodyParserMiddleware', priority: 70 },
{ name: 'oidcStandardRoutesMiddleware', priority: 60 },
],
'/graphql': [
{ name: 'expressGraphqlMiddleware', required: true, priority: -100 },
],
};
const diContainer = new DiContainer({
load: mergeLDs(
// GraphQL server with middleware config
apolloSubgraphServerModularLDGen({
resolvers,
typeDefs,
middlewareConfig
}),
// SwissOID authentication components
swissoidAuthLoadDict,
// Your other loaders...
)
});
```
### Direct Express Usage
```typescript
import { swissoidAuthLoadDict } from 'swissoid-back';
// Load OIDC routes directly (this will mount them on the express app)
await diContainer.load('oidcStandardRoutes');
```
### AppConfig Integration
swissoid-back provides an appConfigMap that can be merged with your application's configuration:
```typescript
import { swissoidMergeAppConfigMap } from 'swissoid-back';
const merged = swissoidMergeAppConfigMap(yourAppConfigMap);
export type AppConfig = ReturnType<typeof merged>;
```
### Configuration
Create a `.env` file with the required configuration (see `.env.example` for all options):
```env
# SwissOID Configuration
SWISSOID_ISSUER=https://api.swissoid.com
SWISSOID_CLIENT_ID=your-client-id
SWISSOID_CLIENT_SECRET=your-client-secret
SWISSOID_TOKEN_ENDPOINT=https://api.swissoid.com/token
SWISSOID_JWKS_URI=https://api.swissoid.com/.well-known/jwks.json
# Redis Configuration
REDIS_HOST=localhost
REDIS_PORT=6379
# Session Configuration
SESSION_COOKIE_NAME=connect.sid
SESSION_SECRET=your-session-secret
# Optional: override derived state signing secret
# STATE_SIGNING_SECRET=your-state-secret
# RP Configuration
RP_FRONTEND_URL=http://localhost:3000
COOKIE_DOMAIN=localhost
OIDC_REDIRECT_BASE_URL=http://localhost:3668
```
### Generating strong secrets
Use the helper script to produce high-entropy values for
`SESSION_SECRET` and `STATE_SIGNING_SECRET`:
```bash
npm run generate:secrets
```
You can also invoke the packaged CLI from your own project:
```bash
npx swissoid-back-generate-secrets
```
Example output:
```
SESSION_SECRET=8Qd8d...snipped
STATE_SIGNING_SECRET=Ob7v3...snipped
# Copy the values above into your deployment secret store (.env, Vault, etc.).
# Keep them private and rotate on a regular schedule.
```
- Pass `--derive-state` to derive the state secret from the session secret
(mirrors the default behaviour when `STATE_SIGNING_SECRET` is omitted).
- Adjust entropy with `--session-bytes=<n>` or `--state-bytes=<n>` if you need
different lengths (defaults: 48 bytes for the session secret and 32 for the
state secret).
## Routes
The package provides the following OIDC routes when loaded:
- `GET /login` - Initiates OIDC authorization flow
- `POST /oidc/callback` - Handles OIDC callback from SwissOID
- `GET /oidc/finalize` - Completes authentication and sets session (gateway subsequently mints a DAT for subgraphs)
- `GET /auth/status` - Returns current authentication status
- `POST /auth/logout` - Logs out the user
- `GET /auth/debug` - Debug endpoint to check session and cookie status
- `GET /auth/ping` - Connectivity test endpoint
## Components
The `swissoidAuthLoadDict` includes:
- **redisClient**: Redis connection for session storage
- **sessionService**: Session management service
- **cookieManager**: Cookie handling utilities
- **oidcStandardRoutes**: Express router with OIDC endpoints
- **oidcStandardRoutesMiddleware**: Middleware-compatible version for express-knifey integration
- **swissoidAppConfigMap**: AppConfig map with priority 60
## Exports
```typescript
// Main LoadDict for di-why
import { swissoidAuthLoadDict } from 'swissoid-back';
// AppConfig utilities
import { swissoidMergeAppConfigMap } from 'swissoid-back';
// Individual loaders if needed
import {
sessionService,
cookieManager,
oidcStandardRoutes,
oidcStandardRoutesMiddleware
} from 'swissoid-back';
```
## License
MIT