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.
 
 
Guillermo Pages d9f4609b80 docs: fix inconsistency with code 2 months ago
scripts feat: generate secrets 2 months ago
src fix: logout redirect loop 2 months ago
.env.example docs: add example env 3 months ago
.gitignore feat: seems migrated 3 months ago
README.md docs: fix inconsistency with code 2 months ago
REDIS_REQUIREMENTS.md feat: seems migrated 3 months ago
docker-compose.example.yml feat: seems migrated 3 months ago
package-lock.json 2.3.0 2 months ago
package.json 2.3.0 2 months ago
tsconfig.json feat: seems migrated 3 months ago

README.md

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

npm install swissoid-back

Requirements

  • Node.js >= 18
  • Redis server for session storage
  • SwissOID client credentials

Usage

swissoid-back integrates with express-knifey middleware handles so gateways/standalone services can share the same DI wiring used across Cronide:

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

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:

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):

# 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:

npm run generate:secrets

You can also invoke the packaged CLI from your own project:

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

// 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