Documentation
¶
Overview ¶
Package sp implements a SAML 2.0 Service Provider.
ServiceProvider is the main entry point. Configure it with your SP's entity ID, ACS URL, and IdP settings, then use it to:
- Build AuthnRequests with ServiceProvider.BuildAuthURL or ServiceProvider.BuildAuthBodyPost
- Validate SAML responses with ServiceProvider.ValidateEncodedResponse
- Extract user attributes with ServiceProvider.RetrieveAssertionInfo
- Generate SP metadata with ServiceProvider.Metadata
- Handle single logout with the BuildLogout*/ValidateEncodedLogout* methods
Use ServiceProvider.ConfigureFromMetadata to populate IdP settings from a parsed types.EntityDescriptor.
For replay prevention, set [ServiceProvider.RequestTracker] to a MemoryRequestTracker or your own implementation.
Index ¶
- Constants
- func DecodeUnverifiedBaseResponse(encodedResponse string) (*types.UnverifiedBaseResponse, error)
- func DecodeUnverifiedLogoutResponse(encodedResponse string) (*types.LogoutResponse, error)
- type AssertionInfo
- type MemoryRequestTracker
- type ProxyRestriction
- type RequestTracker
- type ServiceProvider
- func (sp *ServiceProvider) AuthRedirect(w http.ResponseWriter, r *http.Request, relayState string) (err error)
- func (sp *ServiceProvider) BuildAuthBodyPost(relayState string) ([]byte, error)
- func (sp *ServiceProvider) BuildAuthBodyPostFromDocument(relayState string, doc *etree.Document) ([]byte, error)
- func (sp *ServiceProvider) BuildAuthRequest() (string, error)
- func (sp *ServiceProvider) BuildAuthRequestDocument() (*etree.Document, error)
- func (sp *ServiceProvider) BuildAuthRequestDocumentNoSig() (*etree.Document, error)
- func (sp *ServiceProvider) BuildAuthURL(relayState string) (string, error)
- func (sp *ServiceProvider) BuildAuthURLFromDocument(relayState string, doc *etree.Document) (string, error)
- func (sp *ServiceProvider) BuildAuthURLRedirect(relayState string, doc *etree.Document) (string, error)
- func (sp *ServiceProvider) BuildLogoutBodyPostFromDocument(relayState string, doc *etree.Document) ([]byte, error)
- func (sp *ServiceProvider) BuildLogoutRequestDocument(nameID string, sessionIndex string) (*etree.Document, error)
- func (sp *ServiceProvider) BuildLogoutRequestDocumentNoSig(nameID string, sessionIndex string) (*etree.Document, error)
- func (sp *ServiceProvider) BuildLogoutResponseBodyPostFromDocument(relayState string, doc *etree.Document) ([]byte, error)
- func (sp *ServiceProvider) BuildLogoutResponseDocument(status string, reqID string) (*etree.Document, error)
- func (sp *ServiceProvider) BuildLogoutResponseDocumentNoSig(status string, reqID string) (*etree.Document, error)
- func (sp *ServiceProvider) BuildLogoutURLRedirect(relayState string, doc *etree.Document) (string, error)
- func (sp *ServiceProvider) ConfigureFromMetadata(ed *types.EntityDescriptor) error
- func (sp *ServiceProvider) GetEncryptionCertBytes() ([]byte, error)
- func (sp *ServiceProvider) GetSigningCertBytes() ([]byte, error)
- func (sp *ServiceProvider) Metadata() (*types.EntityDescriptor, error)
- func (sp *ServiceProvider) RetrieveAssertionInfo(ctx context.Context, encodedResponse string) (*AssertionInfo, error)
- func (sp *ServiceProvider) SignAuthnRequest(el *etree.Element) (*etree.Element, error)
- func (sp *ServiceProvider) SignLogoutRequest(el *etree.Element) (*etree.Element, error)
- func (sp *ServiceProvider) SignLogoutResponse(el *etree.Element) (*etree.Element, error)
- func (sp *ServiceProvider) Signer() (*dsig.Signer, error)
- func (sp *ServiceProvider) Validate(response *types.Response) error
- func (sp *ServiceProvider) ValidateDecodedLogoutRequest(request *saml2.LogoutRequest) error
- func (sp *ServiceProvider) ValidateDecodedLogoutResponse(response *types.LogoutResponse) error
- func (sp *ServiceProvider) ValidateEncodedLogoutRequestPOST(ctx context.Context, encodedRequest string) (*saml2.LogoutRequest, error)
- func (sp *ServiceProvider) ValidateEncodedLogoutRequestRedirect(ctx context.Context, samlRequest, relayState, sigAlg, signature string) (*saml2.LogoutRequest, error)
- func (sp *ServiceProvider) ValidateEncodedLogoutResponsePOST(ctx context.Context, encodedResponse string) (*types.LogoutResponse, error)
- func (sp *ServiceProvider) ValidateEncodedLogoutResponseRedirect(ctx context.Context, samlResponse, relayState, sigAlg, signature string) (*types.LogoutResponse, error)
- func (sp *ServiceProvider) ValidateEncodedResponse(ctx context.Context, encodedResponse string) (*types.Response, error)
- type Values
Constants ¶
const (
SubjMethodBearer = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
)
Well-known methods of subject confirmation
Variables ¶
This section is empty.
Functions ¶
func DecodeUnverifiedBaseResponse ¶
func DecodeUnverifiedBaseResponse(encodedResponse string) (*types.UnverifiedBaseResponse, error)
DecodeUnverifiedBaseResponse decodes several attributes from a SAML response for the purpose of determining how to validate the response.
func DecodeUnverifiedLogoutResponse ¶
func DecodeUnverifiedLogoutResponse(encodedResponse string) (*types.LogoutResponse, error)
DecodeUnverifiedLogoutResponse decodes several attributes from a SAML Logout response, without doing any verifications.
Types ¶
type AssertionInfo ¶
type AssertionInfo struct {
NameID string
NameIDFormat string
Values Values
SessionIndex string
AuthnInstant *time.Time
SessionNotOnOrAfter *time.Time
Assertions []types.Assertion
ResponseSignatureValidated bool
OneTimeUse bool
ProxyRestriction *ProxyRestriction
}
AssertionInfo contains assertion data extracted from a SAML response.
type MemoryRequestTracker ¶
type MemoryRequestTracker struct {
// contains filtered or unexported fields
}
MemoryRequestTracker is an in-memory RequestTracker that uses lazy expiry to sweep stale entries. It requires no goroutines or Close().
func NewMemoryRequestTracker ¶
func NewMemoryRequestTracker(expiry time.Duration) *MemoryRequestTracker
NewMemoryRequestTracker creates a MemoryRequestTracker with the given expiry duration. Entries older than expiry are lazily removed on subsequent calls.
func (*MemoryRequestTracker) ConsumeRequest ¶
func (m *MemoryRequestTracker) ConsumeRequest(_ context.Context, id string) error
ConsumeRequest verifies that a request ID was previously stored and removes it. Returns a ValidationError wrapping ErrReplay if the ID is not recognized.
func (*MemoryRequestTracker) StoreRequest ¶
func (m *MemoryRequestTracker) StoreRequest(_ context.Context, id string) error
StoreRequest persists a request ID so it can be verified later.
type ProxyRestriction ¶
ProxyRestriction contains proxy restriction info from an assertion.
type RequestTracker ¶
type RequestTracker interface {
// StoreRequest persists a request ID so it can be verified later.
StoreRequest(ctx context.Context, id string) error
// ConsumeRequest verifies that a request ID was previously stored
// and removes it. Returns ErrReplay if the ID is not recognized.
ConsumeRequest(ctx context.Context, id string) error
}
RequestTracker stores and verifies SAML request IDs for InResponseTo validation, preventing replay attacks.
type ServiceProvider ¶
type ServiceProvider struct {
// Service Provider identity
EntityID string
ACSURL string
SLOURL string
// Identity Provider
IDPEntityID string
IDPSSOURL string
IDPSSOBinding string
IDPSLOURL string
IDPSLOBinding string
// Certificates and keys
IDPCertificates []*x509.Certificate
SPKeyStore *saml2.KeyStore
SPSigningKeyStore *saml2.KeyStore
// Security
InsecureSkipSignatureValidation bool
AllowSHA1 bool
ValidateEncryptionCert bool
AllowIDPInitiated bool
// Signing
SignAuthnRequests bool
SignAuthnRequestsAlgorithm string
SignAuthnRequestsCanonicalizer dsig.Canonicalizer
// Validation
ClockSkew time.Duration
AudienceURIs []string
RequestTracker RequestTracker
// Request building
RequestedAuthnContext *saml2.RequestedAuthnContext
ForceAuthn bool
IsPassive bool
NameIDFormat string
// Advanced
Clock func() time.Time
MaximumDecompressedBodySize int64
MetadataValidDuration time.Duration
// contains filtered or unexported fields
}
ServiceProvider represents a SAML 2.0 Service Provider. Configure its fields and use its methods to build AuthnRequests, validate responses, and generate SP metadata.
func (*ServiceProvider) AuthRedirect ¶
func (sp *ServiceProvider) AuthRedirect(w http.ResponseWriter, r *http.Request, relayState string) (err error)
AuthRedirect takes a ResponseWriter and Request from an http interaction and redirects to the ServiceProvider's configured IdP, including the relayState provided, if any.
func (*ServiceProvider) BuildAuthBodyPost ¶
func (sp *ServiceProvider) BuildAuthBodyPost(relayState string) ([]byte, error)
BuildAuthBodyPost builds the POST body to be sent to IDP.
func (*ServiceProvider) BuildAuthBodyPostFromDocument ¶
func (sp *ServiceProvider) BuildAuthBodyPostFromDocument(relayState string, doc *etree.Document) ([]byte, error)
BuildAuthBodyPostFromDocument builds the POST body to be sent to IDP. It takes the AuthnRequest xml as input.
func (*ServiceProvider) BuildAuthRequest ¶
func (sp *ServiceProvider) BuildAuthRequest() (string, error)
BuildAuthRequest builds <AuthnRequest> for identity provider
func (*ServiceProvider) BuildAuthRequestDocument ¶
func (sp *ServiceProvider) BuildAuthRequestDocument() (*etree.Document, error)
BuildAuthRequestDocument builds a signed AuthnRequest XML document.
func (*ServiceProvider) BuildAuthRequestDocumentNoSig ¶
func (sp *ServiceProvider) BuildAuthRequestDocumentNoSig() (*etree.Document, error)
BuildAuthRequestDocumentNoSig builds an AuthnRequest XML document without an embedded signature. Use this for the HTTP-Redirect binding, where the signature is applied to the query string instead.
func (*ServiceProvider) BuildAuthURL ¶
func (sp *ServiceProvider) BuildAuthURL(relayState string) (string, error)
BuildAuthURL builds redirect URL to be sent to principal
func (*ServiceProvider) BuildAuthURLFromDocument ¶
func (sp *ServiceProvider) BuildAuthURLFromDocument(relayState string, doc *etree.Document) (string, error)
BuildAuthURLFromDocument builds a redirect URL for the HTTP-POST binding from a pre-built AuthnRequest document.
func (*ServiceProvider) BuildAuthURLRedirect ¶
func (sp *ServiceProvider) BuildAuthURLRedirect(relayState string, doc *etree.Document) (string, error)
BuildAuthURLRedirect builds a redirect URL for the HTTP-Redirect binding from a pre-built AuthnRequest document. If SignAuthnRequests is true, the query string is signed per the SAML redirect binding specification.
func (*ServiceProvider) BuildLogoutBodyPostFromDocument ¶
func (sp *ServiceProvider) BuildLogoutBodyPostFromDocument(relayState string, doc *etree.Document) ([]byte, error)
BuildLogoutBodyPostFromDocument builds the POST body to be sent to IDP. It takes the LogoutRequest xml as input.
func (*ServiceProvider) BuildLogoutRequestDocument ¶
func (sp *ServiceProvider) BuildLogoutRequestDocument(nameID string, sessionIndex string) (*etree.Document, error)
BuildLogoutRequestDocument builds a signed LogoutRequest XML document.
func (*ServiceProvider) BuildLogoutRequestDocumentNoSig ¶
func (sp *ServiceProvider) BuildLogoutRequestDocumentNoSig(nameID string, sessionIndex string) (*etree.Document, error)
BuildLogoutRequestDocumentNoSig builds a LogoutRequest XML document without an embedded signature.
func (*ServiceProvider) BuildLogoutResponseBodyPostFromDocument ¶
func (sp *ServiceProvider) BuildLogoutResponseBodyPostFromDocument(relayState string, doc *etree.Document) ([]byte, error)
BuildLogoutResponseBodyPostFromDocument builds an HTML auto-submit POST form containing the LogoutResponse for the HTTP-POST binding.
func (*ServiceProvider) BuildLogoutResponseDocument ¶
func (sp *ServiceProvider) BuildLogoutResponseDocument(status string, reqID string) (*etree.Document, error)
BuildLogoutResponseDocument builds a signed LogoutResponse XML document with the given status code and InResponseTo value.
func (*ServiceProvider) BuildLogoutResponseDocumentNoSig ¶
func (sp *ServiceProvider) BuildLogoutResponseDocumentNoSig(status string, reqID string) (*etree.Document, error)
BuildLogoutResponseDocumentNoSig builds a LogoutResponse XML document without an embedded signature.
func (*ServiceProvider) BuildLogoutURLRedirect ¶
func (sp *ServiceProvider) BuildLogoutURLRedirect(relayState string, doc *etree.Document) (string, error)
BuildLogoutURLRedirect builds a redirect URL for the HTTP-Redirect binding from a pre-built LogoutRequest document. If signing is configured, the query string is signed.
func (*ServiceProvider) ConfigureFromMetadata ¶
func (sp *ServiceProvider) ConfigureFromMetadata(ed *types.EntityDescriptor) error
ConfigureFromMetadata populates the ServiceProvider's IdP-related fields from an EntityDescriptor. It extracts the entity ID, SSO/SLO endpoints, and signing certificates from the IDPSSODescriptor.
For SSO endpoints it prefers HTTP-POST, falling back to HTTP-Redirect. For SLO endpoints it prefers HTTP-POST, falling back to HTTP-Redirect.
func (*ServiceProvider) GetEncryptionCertBytes ¶
func (sp *ServiceProvider) GetEncryptionCertBytes() ([]byte, error)
GetEncryptionCertBytes returns the raw DER-encoded encryption certificate from SPKeyStore.
func (*ServiceProvider) GetSigningCertBytes ¶
func (sp *ServiceProvider) GetSigningCertBytes() ([]byte, error)
GetSigningCertBytes returns the raw DER-encoded signing certificate. It uses SPSigningKeyStore if set, otherwise falls back to SPKeyStore.
func (*ServiceProvider) Metadata ¶
func (sp *ServiceProvider) Metadata() (*types.EntityDescriptor, error)
Metadata generates an EntityDescriptor for this Service Provider, suitable for publishing at a metadata endpoint. It includes key descriptors for any configured signing and encryption keys, and SLO endpoints if SLOURL is set.
func (*ServiceProvider) RetrieveAssertionInfo ¶
func (sp *ServiceProvider) RetrieveAssertionInfo(ctx context.Context, encodedResponse string) (*AssertionInfo, error)
RetrieveAssertionInfo takes an encoded response and returns the AssertionInfo contained, or an error message if an error has been encountered.
func (*ServiceProvider) SignAuthnRequest ¶
SignAuthnRequest takes a document, builds a signature, creates another document and inserts the signature in it. According to the schema, the position of the signature is right after the Issuer [1] then all other children.
[1] https://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd
func (*ServiceProvider) SignLogoutRequest ¶
SignLogoutRequest signs a LogoutRequest element, placing the Signature element after the Issuer per the SAML schema.
func (*ServiceProvider) SignLogoutResponse ¶
SignLogoutResponse signs a LogoutResponse element, placing the Signature element after the Issuer per the SAML schema.
func (*ServiceProvider) Signer ¶
func (sp *ServiceProvider) Signer() (*dsig.Signer, error)
Signer returns a dsig.Signer configured for this service provider.
func (*ServiceProvider) Validate ¶
func (sp *ServiceProvider) Validate(response *types.Response) error
Validate ensures that the assertion passed is valid for the current Service Provider.
func (*ServiceProvider) ValidateDecodedLogoutRequest ¶
func (sp *ServiceProvider) ValidateDecodedLogoutRequest(request *saml2.LogoutRequest) error
ValidateDecodedLogoutRequest validates a previously decoded and signature-verified LogoutRequest, checking issuer, destination, version, and NotOnOrAfter expiry.
func (*ServiceProvider) ValidateDecodedLogoutResponse ¶
func (sp *ServiceProvider) ValidateDecodedLogoutResponse(response *types.LogoutResponse) error
ValidateDecodedLogoutResponse validates a previously decoded and signature-verified LogoutResponse, checking issuer, status, destination, and version.
func (*ServiceProvider) ValidateEncodedLogoutRequestPOST ¶
func (sp *ServiceProvider) ValidateEncodedLogoutRequestPOST(ctx context.Context, encodedRequest string) (*saml2.LogoutRequest, error)
ValidateEncodedLogoutRequestPOST decodes and validates a base64-encoded LogoutRequest received via the HTTP-POST binding. It verifies the signature (unless InsecureSkipSignatureValidation is set) and validates request attributes.
func (*ServiceProvider) ValidateEncodedLogoutRequestRedirect ¶
func (sp *ServiceProvider) ValidateEncodedLogoutRequestRedirect( ctx context.Context, samlRequest, relayState, sigAlg, signature string, ) (*saml2.LogoutRequest, error)
ValidateEncodedLogoutRequestRedirect validates a SAML LogoutRequest received via HTTP-Redirect binding.
func (*ServiceProvider) ValidateEncodedLogoutResponsePOST ¶
func (sp *ServiceProvider) ValidateEncodedLogoutResponsePOST(ctx context.Context, encodedResponse string) (*types.LogoutResponse, error)
ValidateEncodedLogoutResponsePOST decodes and validates a base64-encoded LogoutResponse received via the HTTP-POST binding. It verifies the signature (unless InsecureSkipSignatureValidation is set) and validates response attributes.
func (*ServiceProvider) ValidateEncodedLogoutResponseRedirect ¶
func (sp *ServiceProvider) ValidateEncodedLogoutResponseRedirect( ctx context.Context, samlResponse, relayState, sigAlg, signature string, ) (*types.LogoutResponse, error)
ValidateEncodedLogoutResponseRedirect validates a SAML LogoutResponse received via HTTP-Redirect binding.
func (*ServiceProvider) ValidateEncodedResponse ¶
func (sp *ServiceProvider) ValidateEncodedResponse(ctx context.Context, encodedResponse string) (*types.Response, error)
ValidateEncodedResponse both decodes and validates, based on SP configuration, an encoded, signed response.
type Values ¶
Values is a convenience wrapper for a map of strings to Attributes, which can be used for easy access to the string values of Attribute lists.
func (Values) Get ¶
Get is a safe method (nil maps will not panic) for returning the first value for an attribute at a key, or the empty string if none exists.