sso

package
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: MIT, MIT Imports: 20 Imported by: 0

README

GoModularAuth Enterprise Single Sign-On (SSO) Plugin

gomodularauth-sso provides enterprise Single Sign-On (SSO) configuration, domain discovery, and multi-tenant identity federation across OpenID Connect (OIDC) and SAML 2.0 protocols for GoModularAuth.

Installation

go get github.com/BladiCreator/go-modular-auth/plugins/sso

Quick Start

engine, err := auth.New(auth.Config{
    Adapter: adaptermem.New(),
    Cache: coreCache,
    Plugins: []auth.PluginModule{
        organizationsModule, // Optional: for JIT membership assignment
        ssoModule,
    },
})
if err != nil {
    log.Fatalf("failed to initialize auth: %v", err)
}

// Access typed capability
ssoCap, err := auth.Get[plugins.SSO](engine)
if err != nil {
    log.Fatalf("failed to resolve SSO capability: %v", err)
}

Detailed guide: doc/plugins/sso.md.

Documentation

Overview

Package sso provides enterprise Single Sign-On (SSO) configuration, domain discovery, and identity federation over OpenID Connect (OIDC) and SAML 2.0 for GoModularAuth.

Index

Constants

View Source
const (
	ModelSSOConfigs        = "sso_configs"
	ModelSSODomainMappings = "sso_domain_mappings"
	ModelSSOStates         = "sso_states"
)

Model constants for schema registration.

View Source
const (
	// EventConfigCreated is emitted when an organization SSO configuration is created.
	EventConfigCreated auth.EventName = "sso.config.created"

	// EventConfigUpdated is emitted when an organization SSO configuration is modified.
	EventConfigUpdated auth.EventName = "sso.config.updated"

	// EventConfigDeleted is emitted when an organization SSO configuration is removed.
	EventConfigDeleted auth.EventName = "sso.config.deleted"

	// EventLoginSuccess is emitted upon successful SSO authentication and session establishment.
	EventLoginSuccess auth.EventName = "sso.login.success"

	// EventLoginFailed is emitted when an SSO ceremony fails or is rejected.
	EventLoginFailed auth.EventName = "sso.login.failed"

	// EventJITProvisioned is emitted when a new Core User is auto-provisioned via SSO.
	EventJITProvisioned auth.EventName = "sso.jit.provisioned"

	// EventAccountLinked is emitted when an existing user is linked to an SSO provider.
	EventAccountLinked auth.EventName = "sso.account.linked"
)
View Source
const PluginID = "sso"

PluginID identifies this plugin in the GoModularAuth runtime.

Variables

View Source
var (
	// ErrConfigNotFound indicates that the requested SSO configuration does not exist.
	ErrConfigNotFound = errors.New("sso: configuration not found")

	// ErrConfigDisabled indicates that the target SSO configuration is currently inactive.
	ErrConfigDisabled = errors.New("sso: configuration is disabled")

	// ErrDomainNotFound indicates that no organization SSO provider claims the specified domain.
	ErrDomainNotFound = errors.New("sso: domain not registered for sso")

	// ErrDomainConflict indicates that the domain is already claimed by another organization.
	ErrDomainConflict = errors.New("sso: domain is already claimed by another organization")

	// ErrInvalidInput indicates missing or malformed required parameters.
	ErrInvalidInput = errors.New("sso: invalid input")

	// ErrInvalidProtocol indicates an unsupported federation protocol.
	ErrInvalidProtocol = errors.New("sso: invalid or unsupported protocol")

	// ErrInvalidState indicates that the returned state token does not match any in-flight session.
	ErrInvalidState = errors.New("sso: invalid state token")

	// ErrStateExpired indicates that the in-flight SSO transaction has expired.
	ErrStateExpired = errors.New("sso: state token expired")

	// ErrStateConsumed indicates that the state session was already redeemed (replay attack prevented).
	ErrStateConsumed = errors.New("sso: state token already consumed")

	// ErrCrossTenantViolation indicates an attempted cross-tenant identity injection or mismatch.
	ErrCrossTenantViolation = errors.New("sso: cross-tenant identity confusion detected")

	// ErrJITDisabled indicates that Just-In-Time provisioning is disabled and the user does not exist.
	ErrJITDisabled = errors.New("sso: just-in-time provisioning is disabled for this organization")

	// ErrAccountConflict indicates an email or identity collision where linking is disallowed.
	ErrAccountConflict = errors.New("sso: an account with this email already exists and auto-link is disabled")

	// ErrUnverifiedEmail indicates that the IdP did not assert email verification or domain mismatch.
	ErrUnverifiedEmail = errors.New("sso: unverified email or domain mismatch")

	// ErrMissingEmailAttribute indicates that no email address could be extracted from the assertion.
	ErrMissingEmailAttribute = errors.New("sso: assertion is missing required email attribute")

	// ErrIdPValidationFailed indicates that the Identity Provider configuration failed sanity checks.
	ErrIdPValidationFailed = errors.New("sso: identity provider configuration validation failed")

	// ErrSAMLResponseInvalid indicates that the SAML Response XML was malformed or missing required assertions.
	ErrSAMLResponseInvalid = errors.New("sso: malformed saml response")

	// ErrSAMLSignatureInvalid indicates that the cryptographic signature verification of the SAML assertion failed.
	ErrSAMLSignatureInvalid = errors.New("sso: saml assertion signature verification failed")

	// ErrSAMLAudienceMismatch indicates that the SAML assertion AudienceRestriction does not match SP Entity ID.
	ErrSAMLAudienceMismatch = errors.New("sso: saml audience restriction mismatch")

	// ErrSAMLExpired indicates that the SAML assertion is outside its NotBefore/NotOnOrAfter validity window.
	ErrSAMLExpired = errors.New("sso: saml assertion validity window expired")

	// ErrOIDCValidationFailed indicates that OIDC token exchange or ID Token validation failed.
	ErrOIDCValidationFailed = errors.New("sso: oidc token validation failed")
)

Functions

func RegisterSchema

func RegisterSchema(s *schema.Schema) error

RegisterSchema registers all database models required by the SSO plugin.

Types

type AttributeMapping

type AttributeMapping struct {
	EmailAttr     string            `json:"email_attr"`
	NameAttr      string            `json:"name_attr"`
	FirstNameAttr string            `json:"first_name_attr,omitempty"`
	LastNameAttr  string            `json:"last_name_attr,omitempty"`
	GroupsAttr    string            `json:"groups_attr,omitempty"`
	Custom        map[string]string `json:"custom,omitempty"`
}

AttributeMapping defines how IdP assertion attributes map to canonical user identity fields.

type Config

type Config struct {
	StateTTL      time.Duration
	Clock         func() time.Time
	HTTPClient    HTTPClient
	SPEntityID    string
	SPACSURL      string
	Organizations organizations.Organization
}

Config holds runtime configuration options for the SSO plugin.

type ConfigAuditPayload

type ConfigAuditPayload struct {
	OrganizationID string    `json:"organization_id"`
	ConfigID       string    `json:"config_id"`
	ConfigName     string    `json:"config_name"`
	Protocol       Protocol  `json:"protocol"`
	Domains        []string  `json:"domains"`
	Action         string    `json:"action"`
	Timestamp      time.Time `json:"timestamp"`
}

ConfigAuditPayload carries audit details for SSO configuration modifications.

type CreateConfigInput

type CreateConfigInput struct {
	OrganizationID   string            `json:"organization_id"`
	Name             string            `json:"name"`
	Protocol         Protocol          `json:"protocol"`
	Enabled          bool              `json:"enabled"`
	Domains          []string          `json:"domains"`
	JITEnabled       bool              `json:"jit_enabled"`
	DefaultRole      string            `json:"default_role,omitempty"`
	AutoLink         bool              `json:"auto_link"`
	OIDC             *OIDCConfig       `json:"oidc,omitempty"`
	SAML             *SAMLConfig       `json:"saml,omitempty"`
	AttributeMapping *AttributeMapping `json:"attribute_mapping,omitempty"`
}

CreateConfigInput specifies parameters for provisioning an organization SSO configuration.

type DomainDiscoveryResult

type DomainDiscoveryResult struct {
	Domain         string   `json:"domain"`
	OrganizationID string   `json:"organization_id"`
	ConfigID       string   `json:"config_id"`
	ConfigName     string   `json:"config_name"`
	Protocol       Protocol `json:"protocol"`
	SSOEndpoint    string   `json:"sso_endpoint"`
}

DomainDiscoveryResult represents the resolved tenant SSO configuration for a domain.

type DomainMapping

type DomainMapping struct {
	ID             string `json:"id"`
	Domain         string `json:"domain"`
	OrganizationID string `json:"organization_id"`
	ConfigID       string `json:"config_id"`
}

DomainMapping associates a claimed email domain with its active SSO configuration.

type HTTPClient

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPClient abstracts outbound HTTP request execution. It is satisfied by *http.Client.

type InitiateSSOInput

type InitiateSSOInput struct {
	Email          string `json:"email,omitempty"`
	OrganizationID string `json:"organization_id,omitempty"`
	ConfigID       string `json:"config_id,omitempty"`
	RedirectURI    string `json:"redirect_uri"`
	RelayState     string `json:"relay_state,omitempty"`
}

InitiateSSOInput defines parameters for starting an enterprise federated login.

type InitiateSSOResult

type InitiateSSOResult struct {
	RedirectURL    string    `json:"redirect_url"`
	State          string    `json:"state"`
	OrganizationID string    `json:"organization_id"`
	ConfigID       string    `json:"config_id"`
	Protocol       Protocol  `json:"protocol"`
	ExpiresAt      time.Time `json:"expires_at"`
}

InitiateSSOResult returns the redirect target and tracking state for the SSO ceremony.

type LinkAccountInput

type LinkAccountInput struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id"`
	ConfigID       string `json:"config_id"`
	ProviderID     string `json:"provider_id"`
	Email          string `json:"email"`
}

LinkAccountInput provides parameters to link an existing user to an SSO provider.

type LoginAuditPayload

type LoginAuditPayload struct {
	OrganizationID string    `json:"organization_id"`
	ConfigID       string    `json:"config_id"`
	UserID         string    `json:"user_id,omitempty"`
	Email          string    `json:"email,omitempty"`
	Protocol       Protocol  `json:"protocol"`
	IsNewUser      bool      `json:"is_new_user"`
	Success        bool      `json:"success"`
	ErrorReason    string    `json:"error_reason,omitempty"`
	Timestamp      time.Time `json:"timestamp"`
}

LoginAuditPayload carries audit details for an SSO authentication event.

type Module

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

Module implements auth.PluginModule and auth.SchemaProvider for enterprise Single Sign-On.

func New

func New(opts ...Option) *Module

New creates an installable SSO PluginModule with options.

func (*Module) ID

func (m *Module) ID() string

ID returns the module's unique identifier.

func (*Module) Init

func (m *Module) Init(h *auth.Host) error

Init configures infrastructure and registers the typed Capability in GoModularAuth.

func (*Module) RegisterSchema

func (m *Module) RegisterSchema(s *schema.Schema) error

RegisterSchema contributes schema models for SSO configurations, domain mappings, and states.

type OIDCConfig

type OIDCConfig = oidc.OIDCConfig

OIDCConfig contains OpenID Connect specific parameters.

type Option

type Option func(*Config)

Option modifies Config.

func WithClock

func WithClock(clock func() time.Time) Option

WithClock sets a custom time provider for deterministic testing.

func WithHTTPClient

func WithHTTPClient(client HTTPClient) Option

WithHTTPClient configures the HTTP client used for OIDC Discovery and token exchange.

func WithOrganizations

func WithOrganizations(orgs organizations.Organization) Option

WithOrganizations configures optional integration with the Organizations plugin for JIT membership assignment.

func WithSPACSURL

func WithSPACSURL(acsURL string) Option

WithSPACSURL sets the Assertion Consumer Service URL for SAML requests.

func WithSPEntityID

func WithSPEntityID(entityID string) Option

WithSPEntityID sets the Service Provider Entity ID used for SAML Audience restrictions.

func WithStateTTL

func WithStateTTL(d time.Duration) Option

WithStateTTL configures how long in-flight SSO state sessions remain valid.

type ProcessSSOCallbackInput

type ProcessSSOCallbackInput struct {
	State        string              `json:"state"`
	Code         string              `json:"code,omitempty"`
	SAMLResponse string              `json:"saml_response,omitempty"`
	RedirectURI  string              `json:"redirect_uri"`
	Session      auth.SessionOptions `json:"session"`
}

ProcessSSOCallbackInput contains tokens or assertions returned from the IdP.

type Protocol

type Protocol string

Protocol represents the federated authentication protocol used by an SSO provider.

const (
	// ProtocolOIDC designates an OpenID Connect relying-party provider.
	ProtocolOIDC Protocol = "oidc"

	// ProtocolSAML designates a SAML 2.0 Service Provider integration.
	ProtocolSAML Protocol = "saml"
)

type SAMLConfig

type SAMLConfig = saml.SAMLConfig

SAMLConfig contains SAML 2.0 specific parameters.

type SSO

type SSO interface {
	// CreateConfig provisions a new organization-scoped SSO Identity Provider configuration.
	CreateConfig(ctx context.Context, in CreateConfigInput) (*SSOConfig, error)

	// GetConfig retrieves a specific SSO configuration belonging to an organization.
	GetConfig(ctx context.Context, orgID, configID string) (*SSOConfig, error)

	// ListConfigsByOrganization returns all SSO configurations for a given organization.
	ListConfigsByOrganization(ctx context.Context, orgID string) ([]*SSOConfig, error)

	// UpdateConfig modifies an existing organization SSO configuration.
	UpdateConfig(ctx context.Context, in UpdateConfigInput) (*SSOConfig, error)

	// DeleteConfig removes an organization SSO configuration and cleans up domain mappings.
	DeleteConfig(ctx context.Context, orgID, configID string) error

	// DiscoverByEmail resolves the tenant SSO provider configured for the user's email domain.
	DiscoverByEmail(ctx context.Context, email string) (*DomainDiscoveryResult, error)

	// DiscoverByDomain looks up the tenant SSO provider configured for a raw domain.
	DiscoverByDomain(ctx context.Context, domain string) (*DomainDiscoveryResult, error)

	// InitiateSSO starts an enterprise federated login ceremony, returning redirect URL and tracking state.
	InitiateSSO(ctx context.Context, in InitiateSSOInput) (*InitiateSSOResult, error)

	// ProcessSSOCallback validates the returned IdP assertion/token and issues a Core authenticated session.
	ProcessSSOCallback(ctx context.Context, in ProcessSSOCallbackInput) (*SSOAuthResult, error)

	// LinkAccount explicitly associates an existing Core User with an enterprise SSO provider.
	LinkAccount(ctx context.Context, in LinkAccountInput) (*account.Account, error)

	// UnlinkAccount removes the federated link between a user and an organization SSO provider.
	UnlinkAccount(ctx context.Context, orgID, userID, providerID string) error

	// ListLinkedAccounts returns all federated accounts for a user within an organization.
	ListLinkedAccounts(ctx context.Context, orgID, userID string) ([]*account.Account, error)
}

SSO is the strongly typed capability provided by the gomodularauth-sso module. Applications access it via auth.Get[plugins.SSO](a) or auth.Get[sso.SSO](a).

type SSOAuthResult

type SSOAuthResult struct {
	User           *user.User        `json:"user"`
	Account        *account.Account  `json:"account"`
	Session        *session.Session  `json:"session"`
	Token          string            `json:"token"`
	IsNewUser      bool              `json:"is_new_user"`
	OrganizationID string            `json:"organization_id"`
	ConfigID       string            `json:"config_id"`
	Protocol       Protocol          `json:"protocol"`
	Attributes     map[string]string `json:"attributes"`
	RawClaims      map[string]any    `json:"raw_claims,omitempty"`
}

SSOAuthResult encapsulates the outcome of a successful SSO login transaction.

type SSOConfig

type SSOConfig struct {
	ID               string           `json:"id"`
	OrganizationID   string           `json:"organization_id"`
	Name             string           `json:"name"`
	Protocol         Protocol         `json:"protocol"`
	Enabled          bool             `json:"enabled"`
	Domains          []string         `json:"domains"`
	JITEnabled       bool             `json:"jit_enabled"`
	DefaultRole      string           `json:"default_role"`
	AutoLink         bool             `json:"auto_link"`
	OIDC             *OIDCConfig      `json:"oidc,omitempty"`
	SAML             *SAMLConfig      `json:"saml,omitempty"`
	AttributeMapping AttributeMapping `json:"attribute_mapping"`
	CreatedAt        time.Time        `json:"created_at"`
	UpdatedAt        time.Time        `json:"updated_at"`
}

SSOConfig represents an organization-scoped enterprise Identity Provider configuration.

type SSOStateSession

type SSOStateSession struct {
	State          string            `json:"state"`
	OrganizationID string            `json:"organization_id"`
	ConfigID       string            `json:"config_id"`
	Protocol       Protocol          `json:"protocol"`
	RedirectURI    string            `json:"redirect_uri"`
	RelayState     string            `json:"relay_state,omitempty"`
	Nonce          string            `json:"nonce"`
	CodeVerifier   string            `json:"code_verifier,omitempty"`
	Metadata       map[string]string `json:"metadata,omitempty"`
	ConsumedAt     *time.Time        `json:"consumed_at,omitempty"`
	ExpiresAt      time.Time         `json:"expires_at"`
	CreatedAt      time.Time         `json:"created_at"`
}

SSOStateSession stores ephemeral metadata for an in-flight SSO authentication transaction.

func (*SSOStateSession) Expired

func (s *SSOStateSession) Expired(now time.Time) bool

Expired reports whether the state session has expired relative to the given time.

func (*SSOStateSession) IsConsumed

func (s *SSOStateSession) IsConsumed() bool

IsConsumed reports whether the state session has already been redeemed.

type UpdateConfigInput

type UpdateConfigInput struct {
	OrganizationID   string            `json:"organization_id"`
	ConfigID         string            `json:"config_id"`
	Name             *string           `json:"name,omitempty"`
	Enabled          *bool             `json:"enabled,omitempty"`
	Domains          []string          `json:"domains,omitempty"`
	JITEnabled       *bool             `json:"jit_enabled,omitempty"`
	DefaultRole      *string           `json:"default_role,omitempty"`
	AutoLink         *bool             `json:"auto_link,omitempty"`
	OIDC             *OIDCConfig       `json:"oidc,omitempty"`
	SAML             *SAMLConfig       `json:"saml,omitempty"`
	AttributeMapping *AttributeMapping `json:"attribute_mapping,omitempty"`
}

UpdateConfigInput specifies fields to update in an existing SSO configuration.

Directories

Path Synopsis
Package migrations exposes embedded SQL migration assets for the SSO plugin.
Package migrations exposes embedded SQL migration assets for the SSO plugin.
Package oidc implements the OpenID Connect protocol connector for enterprise SSO.
Package oidc implements the OpenID Connect protocol connector for enterprise SSO.
Package plugins exposes capability aliases for GoModularAuth plugins.
Package plugins exposes capability aliases for GoModularAuth plugins.
Package saml implements SAML 2.0 Service Provider functionality for enterprise SSO.
Package saml implements SAML 2.0 Service Provider functionality for enterprise SSO.

Jump to

Keyboard shortcuts

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