webeid

package module
v0.11.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 21, 2026 License: MIT Imports: 18 Imported by: 0

README

go-web-eid

A native Go implementation of the Web eID authentication-token validation and eID-card signing-operations back end.

go-web-eid is wire-compatible with the unmodified Web eID client components (web-eid.js, the browser extension and the native application) and mirrors the public API of the official Java reference library, so existing RIA documentation maps onto it directly.

The library is split into:

  • a framework-agnostic core (github.com/gmb-sig/go-web-eid) that depends only on the Go standard library and golang.org/x/crypto; and
  • a thin Azugo HTTP integration (github.com/gmb-sig/go-web-eid/azugo) that exposes the four endpoints the web-eid.js flow expects.

Scope

In scope: challenge-nonce generation/storage, authentication-token parsing and validation (chain, validity, key usage, policies, OCSP, signature), and the card-operations signing flow (signing-certificate validation, algorithm/hash negotiation, digest relay, auth-certificate surfacing). As of v0.9.0 also "verified finalize" — optional signature-value verification (signing.VerifySignatureValue) + authentication↔signing identity binding (certificate.CheckSameNaturalPerson, certificate/policy.go) + an OCSP responder allowlist; /sign/finalize returns sigVerified/identityBound when given digest+signingCertificate. ECDSA signature bytes are still surfaced as raw P1363 (no DER re-encoding).

Out of scope: signature-container assembly and validation (XAdES/ASiC-E, PAdES, …). Those belong to the integrating back end, which can plug in any tool it prefers (e.g. EU DSS, DigiDoc). The library never builds or validates a container and never sees document bytes.

Installation

go get github.com/gmb-sig/go-web-eid

Quickstart — authentication-token validation (core)

import (
    webeid "github.com/gmb-sig/go-web-eid"
    "github.com/gmb-sig/go-web-eid/certificate"
)

// Load intermediate CA trust anchors (use intermediates, not roots).
cas, _ := certificate.LoadCertificatesFromDir("/etc/webeid/cacerts")

validator, _ := webeid.NewAuthTokenValidatorBuilder().
    WithSiteOrigin("https://example.org").            // https://host[:port], no trailing slash
    WithTrustedCertificateAuthorities(cas...).
    Build()                                            // OCSP on, Mobile-ID policies disallowed

// Issue a challenge nonce per request.
store := webeid.NewInMemoryStore(sessionKeyFunc, 5*time.Minute)
gen, _ := webeid.NewChallengeNonceGeneratorBuilder().
    WithChallengeNonceStore(store).
    Build()
nonce, _ := gen.GenerateAndStoreNonce(ctx)

// Later, validate the token returned by web-eid.js authenticate().
token, _ := webeid.Parse(rawTokenJSON)
stored, _ := store.GetAndRemove(ctx)                   // single-use
cert, err := validator.Validate(ctx, token, stored.Base64EncodedNonce)

The signed datagram is hash(origin) ‖ hash(challenge), hashed again by the signature algorithm (the double-hash described in the specification). ECDSA signatures are accepted in raw IEEE P1363 r ‖ s form, as emitted by the native application.

Quickstart — Azugo integration

import webeidazugo "github.com/gmb-sig/go-web-eid/azugo"

cfg := &webeidazugo.Configuration{
    Origin:                "https://example.org",
    TrustedCACertsPath:    "/etc/webeid/cacerts",
    NonceTTL:              5 * time.Minute,
    OCSPEnabled:           true,
    OCSPRequestTimeout:    5 * time.Second,
    SessionCookieName:     "WEBEID_SESSION",
    SigningHashPreference: []string{"SHA-256", "SHA-384", "SHA-512"},
}

h, _ := webeidazugo.New(cfg)
_ = h.Bind(router) // registers the endpoints below
Method & path Purpose
GET /auth/challenge issue a challenge nonce
POST /auth/login validate the authentication token, log in
POST /sign/certificate validate the signing certificate, negotiate algorithm/hash
POST /sign/finalize return the card's signed digest + auth certificate to the caller

Each route runs behind the EnsureSession pre-auth cookie middleware (HttpOnly, Secure, SameSite=Strict). Enable CSRF protection on the POST routes in your application.

Configuration (environment variables)

Variable Default Notes
WEBEID_ORIGIN https://host[:port], no trailing slash
WEBEID_TRUSTED_CA_CERTS_PATH file or directory of intermediate CA certs
WEBEID_NONCE_TTL 5m challenge-nonce lifetime
WEBEID_OCSP_ENABLED true toggle OCSP revocation checks
WEBEID_OCSP_REQUEST_TIMEOUT 5s per-request OCSP timeout
WEBEID_DESIGNATED_OCSP_URL optional designated responder URL
WEBEID_SESSION_COOKIE_NAME WEBEID_SESSION pre-auth session cookie
WEBEID_SIGNING_HASH_PREFERENCE SHA-256,SHA-384,SHA-512 ordered hash preference

Security

  • Nonce: ≥ 256-bit entropy, single-use (GetAndRemove), TTL-checked, session-bound.
  • Certificate chain is always verified to a configured intermediate CA and checked with OCSP; the unverifiedCertificate is never trusted before validation.
  • Standard-library crypto only; no cgo.
  • HTTPS-only origin; the extension also enforces this client-side.

License

See LICENSE.

Documentation

Overview

Package webeid implements the framework-agnostic core of the Web eID authentication-token validation and eID-card signing-operations back end.

It is wire-compatible with the unmodified Web eID client components (web-eid.js, the browser extension and the native application) and mirrors the public API of the official Java reference library so existing RIA documentation maps directly onto it.

The core depends only on the Go standard library and golang.org/x/crypto; the Azugo HTTP integration lives in the sub-package github.com/gmb-sig/go-web-eid/azugo.

Index

Constants

View Source
const (

	// DefaultNonceTTL is the default challenge-nonce lifetime.
	DefaultNonceTTL = 5 * time.Minute
)

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthToken

type AuthToken struct {
	// UnverifiedCertificate is the base64-encoded DER authentication
	// certificate. It is UNTRUSTED until validated.
	UnverifiedCertificate string `json:"unverifiedCertificate"`
	// Algorithm is the JWA signature algorithm: one of
	// ES256/384/512, PS256/384/512, RS256/384/512.
	Algorithm string `json:"algorithm"`
	// Signature is the base64-encoded signature over hash(origin)+hash(challenge).
	Signature string `json:"signature"`
	// Format is the token type and version, e.g. "web-eid:1.0".
	Format string `json:"format"`
	// AppVersion is the informational URL of the issuing app.
	AppVersion string `json:"appVersion"`
}

AuthToken is the Web eID authentication token as received from web-eid.js.

The certificate and claims contained in the token are UNTRUSTED until the token has been processed by AuthTokenValidator.Validate. The structure is a special-purpose JSON document and deliberately not a JWT — its fields must never be trusted on their own.

func Parse

func Parse(tokenJSON []byte) (*AuthToken, error)

Parse decodes and structurally validates an authentication-token JSON document. It rejects empty mandatory fields, unknown algorithms and unsupported format major versions, but performs no cryptographic checks — those are the responsibility of AuthTokenValidator.Validate.

Unknown JSON fields are tolerated by design: the token format's MINOR version exists so official clients can add new (ignorable) fields without a breaking change — a "web-eid:1.x" token with extra fields is spec-valid and must not be rejected. Only the known fields are validated.

type AuthTokenValidator

type AuthTokenValidator interface {
	// Validate runs the full validation pipeline against the token using the
	// expected challenge nonce. On success it returns the trusted user
	// certificate.
	//
	// The caller is responsible for retrieving currentChallengeNonce from the
	// ChallengeNonceStore (single-use GetAndRemove) and for enforcing nonce
	// expiry before calling Validate.
	Validate(ctx context.Context, token *AuthToken, currentChallengeNonce string) (*x509.Certificate, error)
}

AuthTokenValidator validates Web eID authentication tokens.

type AuthTokenValidatorBuilder

type AuthTokenValidatorBuilder struct {
	// contains filtered or unexported fields
}

AuthTokenValidatorBuilder builds an AuthTokenValidator. It mirrors the Java AuthTokenValidatorBuilder so existing RIA documentation maps onto it.

func NewAuthTokenValidatorBuilder

func NewAuthTokenValidatorBuilder() *AuthTokenValidatorBuilder

NewAuthTokenValidatorBuilder returns a builder with reference-matching defaults (OCSP enabled, Mobile-ID policies disallowed).

func (*AuthTokenValidatorBuilder) Build

Build validates configuration and constructs the validator.

func (*AuthTokenValidatorBuilder) WithAllowInsecureLocalhostOrigin

func (b *AuthTokenValidatorBuilder) WithAllowInsecureLocalhostOrigin() *AuthTokenValidatorBuilder

WithAllowInsecureLocalhostOrigin additionally accepts an http:// origin for localhost loopback hosts — development only, mirroring the official extension's localhost allowance. Never enable in production.

func (*AuthTokenValidatorBuilder) WithAllowedOcspResponderURLs

func (b *AuthTokenValidatorBuilder) WithAllowedOcspResponderURLs(urls ...string) *AuthTokenValidatorBuilder

WithAllowedOcspResponderURLs restricts AIA-derived OCSP responder URLs to an allowlist (full URL or host entries) — an SSRF guard, since the responder URL originates from the user-supplied certificate. Empty = unrestricted.

func (*AuthTokenValidatorBuilder) WithAllowedOcspResponseTimeSkew

func (b *AuthTokenValidatorBuilder) WithAllowedOcspResponseTimeSkew(d time.Duration) *AuthTokenValidatorBuilder

WithAllowedOcspResponseTimeSkew sets the allowed thisUpdate/nextUpdate skew.

func (*AuthTokenValidatorBuilder) WithDesignatedOcspServiceConfiguration

func (b *AuthTokenValidatorBuilder) WithDesignatedOcspServiceConfiguration(cfg *ocsp.DesignatedServiceConfiguration) *AuthTokenValidatorBuilder

WithDesignatedOcspServiceConfiguration sets a designated OCSP responder.

func (*AuthTokenValidatorBuilder) WithDisallowedCertificatePolicies

func (b *AuthTokenValidatorBuilder) WithDisallowedCertificatePolicies(oids ...asn1.ObjectIdentifier) *AuthTokenValidatorBuilder

WithDisallowedCertificatePolicies sets the disallowed certificate policy OIDs, replacing the default Mobile-ID set.

func (*AuthTokenValidatorBuilder) WithMaxOcspResponseThisUpdateAge

func (b *AuthTokenValidatorBuilder) WithMaxOcspResponseThisUpdateAge(d time.Duration) *AuthTokenValidatorBuilder

WithMaxOcspResponseThisUpdateAge sets the maximum thisUpdate age.

func (*AuthTokenValidatorBuilder) WithNonceDisabledOcspUrls

func (b *AuthTokenValidatorBuilder) WithNonceDisabledOcspUrls(urls ...string) *AuthTokenValidatorBuilder

WithNonceDisabledOcspUrls lists OCSP responders that lack nonce support.

func (*AuthTokenValidatorBuilder) WithOcspClient

WithOcspClient injects a custom OCSP transport.

func (*AuthTokenValidatorBuilder) WithOcspRequestTimeout

func (b *AuthTokenValidatorBuilder) WithOcspRequestTimeout(d time.Duration) *AuthTokenValidatorBuilder

WithOcspRequestTimeout sets the per-request OCSP timeout.

func (*AuthTokenValidatorBuilder) WithSiteOrigin

func (b *AuthTokenValidatorBuilder) WithSiteOrigin(origin string) *AuthTokenValidatorBuilder

WithSiteOrigin sets the origin the token is bound to, in the form https://host[:port] with no trailing slash (required).

func (*AuthTokenValidatorBuilder) WithTrustedCertificateAuthorities

func (b *AuthTokenValidatorBuilder) WithTrustedCertificateAuthorities(cas ...*x509.Certificate) *AuthTokenValidatorBuilder

WithTrustedCertificateAuthorities sets the intermediate CA trust anchors (required).

func (*AuthTokenValidatorBuilder) WithoutUserCertificateRevocationCheckWithOcsp

func (b *AuthTokenValidatorBuilder) WithoutUserCertificateRevocationCheckWithOcsp() *AuthTokenValidatorBuilder

WithoutUserCertificateRevocationCheckWithOcsp disables OCSP revocation checks.

type ChallengeNonce

type ChallengeNonce struct {
	// Base64EncodedNonce is the standard-base64 encoding of the random nonce.
	Base64EncodedNonce string
	// IssuedAt is when the nonce was generated.
	IssuedAt time.Time
}

ChallengeNonce is a generated, time-stamped challenge nonce.

func (*ChallengeNonce) Expired

func (n *ChallengeNonce) Expired(now time.Time, ttl time.Duration) bool

Expired reports whether the nonce is older than ttl relative to now.

type ChallengeNonceGenerator

type ChallengeNonceGenerator interface {
	// GenerateAndStoreNonce creates a >=256-bit nonce, stores it via the
	// configured store and returns it.
	GenerateAndStoreNonce(ctx context.Context) (*ChallengeNonce, error)
}

ChallengeNonceGenerator creates and stores challenge nonces.

type ChallengeNonceGeneratorBuilder

type ChallengeNonceGeneratorBuilder struct {
	// contains filtered or unexported fields
}

ChallengeNonceGeneratorBuilder builds a ChallengeNonceGenerator. It mirrors the Java ChallengeNonceGeneratorBuilder.

func NewChallengeNonceGeneratorBuilder

func NewChallengeNonceGeneratorBuilder() *ChallengeNonceGeneratorBuilder

NewChallengeNonceGeneratorBuilder returns a builder with default settings.

func (*ChallengeNonceGeneratorBuilder) Build

Build validates the configuration and returns the generator.

func (*ChallengeNonceGeneratorBuilder) WithChallengeNonceStore

WithChallengeNonceStore sets the store used to persist nonces (required).

func (*ChallengeNonceGeneratorBuilder) WithNonceSize

WithNonceSize overrides the nonce size in bytes. Values below 32 (256 bits) are clamped to 32.

func (*ChallengeNonceGeneratorBuilder) WithNonceTTL

WithNonceTTL sets the nonce lifetime. Expiry is enforced by the store and the login handler using this TTL; the generator only records IssuedAt.

func (*ChallengeNonceGeneratorBuilder) WithSecureRandom

WithSecureRandom overrides the entropy source (primarily for testing).

type ChallengeNonceStore

type ChallengeNonceStore interface {
	// Put stores the nonce for the current session, replacing any existing one.
	Put(ctx context.Context, nonce *ChallengeNonce) error
	// GetAndRemove returns and atomically removes the nonce for the current
	// session. It returns exceptions.ErrChallengeNonceNotFound when absent.
	GetAndRemove(ctx context.Context) (*ChallengeNonce, error)
}

ChallengeNonceStore stores challenge nonces keyed by the caller's session.

Implementations must guarantee single use: GetAndRemove atomically returns and deletes the stored nonce. The Azugo integration layer provides session-backed implementations.

type InMemoryStore

type InMemoryStore struct {
	// contains filtered or unexported fields
}

InMemoryStore is a thread-safe, in-process ChallengeNonceStore suitable for single-instance deployments and tests. Each session holds at most one nonce.

A background-free lazy sweep removes expired entries on access; callers that need bounded memory under churn should prefer a TTL-aware external store (e.g. Redis) for clustered deployments.

func NewInMemoryStore

func NewInMemoryStore(sessionKey SessionKeyFunc, ttl time.Duration) *InMemoryStore

NewInMemoryStore creates an InMemoryStore. The sessionKey function maps a request context to its session identifier; ttl bounds nonce lifetime for the lazy sweep.

func (*InMemoryStore) GetAndRemove

func (s *InMemoryStore) GetAndRemove(ctx context.Context) (*ChallengeNonce, error)

GetAndRemove returns and atomically removes the nonce for the current session.

func (*InMemoryStore) Put

func (s *InMemoryStore) Put(ctx context.Context, nonce *ChallengeNonce) error

Put stores the nonce for the current session.

type SessionKeyFunc

type SessionKeyFunc func(ctx context.Context) (string, error)

SessionKeyFunc derives the session key for the current request from the context. It allows the framework-agnostic stores to bind nonces to a browser session without depending on any particular web framework.

Directories

Path Synopsis
Package assertion implements the trust boundary between the Web eID service and the consuming Identity/Auth service.
Package assertion implements the trust boundary between the Web eID service and the consuming Identity/Auth service.
Package webeidazugo provides the Azugo HTTP integration for the go-web-eid core library: configuration, a session-backed challenge-nonce store with pre-auth cookie middleware, an authentication middleware, and the four endpoints the web-eid.js flow expects.
Package webeidazugo provides the Azugo HTTP integration for the go-web-eid core library: configuration, a session-backed challenge-nonce store with pre-auth cookie middleware, an authentication middleware, and the four endpoints the web-eid.js flow expects.
Package certificate provides X.509 helpers for the Web eID validation pipeline: trust-anchor loading and chain verification, validity / key-usage / extended-key-usage / certificate-policy checks, and subject-data extraction.
Package certificate provides X.509 helpers for the Web eID validation pipeline: trust-anchor loading and chain verification, validity / key-usage / extended-key-usage / certificate-policy checks, and subject-data extraction.
Package exceptions defines the typed error values used throughout the go-web-eid library.
Package exceptions defines the typed error values used throughout the go-web-eid library.
Package ocsp implements Web eID OCSP revocation checking: extracting the responder URL from a certificate's Authority Information Access extension, building nonce-protected OCSP requests, and validating responses (status, responder signature, and thisUpdate/nextUpdate freshness).
Package ocsp implements Web eID OCSP revocation checking: extracting the responder URL from a certificate's Authority Information Access extension, building nonce-protected OCSP requests, and validating responses (status, responder signature, and thisUpdate/nextUpdate freshness).
Package redisstore provides a Redis-backed webeid.ChallengeNonceStore for clustered Web eID deployments.
Package redisstore provides a Redis-backed webeid.ChallengeNonceStore for clustered Web eID deployments.
Package signature implements Web eID signature-algorithm mapping and authentication-token signature verification.
Package signature implements Web eID signature-algorithm mapping and authentication-token signature verification.
Package signing implements the Web eID card-operations subsystem: signing certificate validation, signature-algorithm negotiation, configuration-driven hash-function selection, and relaying a caller-supplied digest-to-sign to the card.
Package signing implements the Web eID card-operations subsystem: signing certificate validation, signature-algorithm negotiation, configuration-driven hash-function selection, and relaying a caller-supplied digest-to-sign to the card.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL