package module
Version: v0.8.1 Latest Latest

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

Go to latest
Published: Sep 21, 2022 License: Apache-2.0 Imports: 20 Imported by: 95



Build Status GoDoc

SAML 2.0 implemementation for Service Providers based on etree and goxmldsig, a pure Go implementation of XML digital signatures.


Install gosaml2 into your $GOPATH using go get:

go get


See demo.go.

Supported Identity Providers

This library is meant to be a generic SAML implementation. If you find a standards compliant identity provider that it doesn't work with please submit a bug or pull request.

The following identity providers have been tested:

  • Okta
  • Auth0
  • Shibboleth
  • Ipsilon
  • OneLogin




View Source
const (
	ReasonUnsupported = "Unsupported"
	ReasonExpired     = "Expired"

Oft-used messages

View Source
const (
	ResponseTag                = "Response"
	AssertionTag               = "Assertion"
	EncryptedAssertionTag      = "EncryptedAssertion"
	SubjectTag                 = "Subject"
	NameIdTag                  = "NameID"
	SubjectConfirmationTag     = "SubjectConfirmation"
	SubjectConfirmationDataTag = "SubjectConfirmationData"
	AttributeStatementTag      = "AttributeStatement"
	AttributeValueTag          = "AttributeValue"
	ConditionsTag              = "Conditions"
	AudienceRestrictionTag     = "AudienceRestriction"
	AudienceTag                = "Audience"
	OneTimeUseTag              = "OneTimeUse"
	ProxyRestrictionTag        = "ProxyRestriction"
	IssuerTag                  = "Issuer"
	StatusTag                  = "Status"
	StatusCodeTag              = "StatusCode"
View Source
const (
	DestinationAttr  = "Destination"
	VersionAttr      = "Version"
	IdAttr           = "ID"
	MethodAttr       = "Method"
	RecipientAttr    = "Recipient"
	NameAttr         = "Name"
	NotBeforeAttr    = "NotBefore"
	NotOnOrAfterAttr = "NotOnOrAfter"
	CountAttr        = "Count"
View Source
const (
	NameIdFormatPersistent      = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
	NameIdFormatTransient       = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
	NameIdFormatEmailAddress    = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
	NameIdFormatUnspecified     = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
	NameIdFormatX509SubjectName = "urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName"

	AuthnContextPasswordProtectedTransport = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"

	AuthnPolicyMatchExact   = "exact"
	AuthnPolicyMatchMinimum = "minimum"
	AuthnPolicyMatchMaximum = "maximum"
	AuthnPolicyMatchBetter  = "better"

	StatusCodeSuccess          = "urn:oasis:names:tc:SAML:2.0:status:Success"
	StatusCodePartialLogout    = "urn:oasis:names:tc:SAML:2.0:status:PartialLogout"
	StatusCodeUnknownPrincipal = "urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal"

	BindingHttpPost     = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
	BindingHttpRedirect = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
View Source
const (
	SAMLAssertionNamespace = "urn:oasis:names:tc:SAML:2.0:assertion"
	SAMLProtocolNamespace  = "urn:oasis:names:tc:SAML:2.0:protocol"
View Source
const (
	SubjMethodBearer = "urn:oasis:names:tc:SAML:2.0:cm:bearer"

Well-known methods of subject confirmation


View Source
var (
	ErrMissingAssertion = ErrMissingElement{Tag: AssertionTag}

ErrMissingAssertion indicates that an appropriate assertion element could not be found in the SAML Response


func DecodeUnverifiedBaseResponse added in v0.3.0

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. This is useful for Service Providers which expose a single Assertion Consumer Service URL but consume Responses from many IdPs.

func DecodeUnverifiedLogoutResponse added in v0.4.0

func DecodeUnverifiedLogoutResponse(encodedResponse string) (*types.LogoutResponse, error)

DecodeUnverifiedLogoutResponse decodes several attributes from a SAML Logout response, without doing any verifications.


type AssertionInfo

type AssertionInfo struct {
	NameID                     string
	Values                     Values
	WarningInfo                *WarningInfo
	SessionIndex               string
	AuthnInstant               *time.Time
	SessionNotOnOrAfter        *time.Time
	Assertions                 []types.Assertion
	ResponseSignatureValidated bool

type AuthNRequest

type AuthNRequest struct {
	ID                          string `xml:",attr"`
	Version                     string `xml:",attr"`
	ProtocolBinding             string `xml:",attr"`
	AssertionConsumerServiceURL string `xml:",attr"`

	IssueInstant time.Time `xml:",attr"`

	Destination string `xml:",attr"`
	Issuer      string

AuthNRequest is the go struct representation of an authentication request

type ErrInvalidValue

type ErrInvalidValue struct {
	Key, Expected, Actual string
	Reason                string

ErrInvalidValue indicates that the expected value did not match the received value.

func (ErrInvalidValue) Error

func (e ErrInvalidValue) Error() string

type ErrMissingElement

type ErrMissingElement struct {
	Tag, Attribute string

ErrMissingElement is the error type that indicates an element and/or attribute is missing. It provides a structured error that can be more appropriately acted upon.

func (ErrMissingElement) Error

func (e ErrMissingElement) Error() string

type ErrParsing

type ErrParsing struct {
	Tag, Value, Type string

ErrParsing indicates that the value present in an assertion could not be parsed. It can be inspected for the specific tag name, the contents, and the intended type.

func (ErrParsing) Error

func (ep ErrParsing) Error() string

type ErrSaml

type ErrSaml struct {
	Message string
	System  error

func (ErrSaml) Error

func (serr ErrSaml) Error() string

type ErrVerification

type ErrVerification struct {
	Cause error

func (ErrVerification) Error

func (e ErrVerification) Error() string

type LogoutRequest added in v0.4.0

type LogoutRequest struct {
	XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol LogoutRequest"`
	ID      string   `xml:"ID,attr"`
	Version string   `xml:"Version,attr"`

	IssueInstant time.Time `xml:"IssueInstant,attr"`

	Destination string        `xml:"Destination,attr"`
	Issuer      *types.Issuer `xml:"Issuer"`

	NameID             *types.NameID `xml:"NameID"`
	SignatureValidated bool          `xml:"-"` // not read, not dumped

LogoutRequest is the go struct representation of a logout request

type ProxyRestriction

type ProxyRestriction struct {
	Count    int
	Audience []string

type RequestedAuthnContext

type RequestedAuthnContext struct {
	// The RequestedAuthnContext comparison policy to use. See the section
	// of the SAML 2.0 specification for details. Constants named AuthnPolicyMatch*
	// contain standardized values.
	Comparison string

	// Contexts will be passed as AuthnContextClassRefs. For example, to force password
	// authentication on some identity providers, Contexts should have a value of
	// []string{AuthnContextPasswordProtectedTransport}, and Comparison should have a
	// value of AuthnPolicyMatchExact.
	Contexts []string

RequestedAuthnContext controls which authentication mechanisms are requested of the identity provider. It is generally sufficient to omit this and let the identity provider select an authentication mechansim.

type SAMLServiceProvider

type SAMLServiceProvider struct {
	IdentityProviderSSOURL     string
	IdentityProviderSSOBinding string
	IdentityProviderSLOURL     string
	IdentityProviderSLOBinding string
	IdentityProviderIssuer     string

	AssertionConsumerServiceURL string
	ServiceProviderSLOURL       string
	ServiceProviderIssuer       string

	SignAuthnRequests              bool
	SignAuthnRequestsAlgorithm     string
	SignAuthnRequestsCanonicalizer dsig.Canonicalizer

	// ForceAuthn attribute in authentication request forces the identity provider to
	// re-authenticate the presenter directly rather than rely on a previous security context.
	// NOTE: If both ForceAuthn and IsPassive are "true", the identity provider MUST NOT freshly
	// authenticate the presenter unless the constraints of IsPassive can be met.
	ForceAuthn bool
	// IsPassive attribute in authentication request requires that the identity provider and the
	// user agent itself MUST NOT visibly take control of the user interface from the requester
	// and interact with the presenter in a noticeable fashion.
	IsPassive bool
	// RequestedAuthnContext allows service providers to require that the identity
	// provider use specific authentication mechanisms. Leaving this unset will
	// permit the identity provider to choose the auth method. To maximize compatibility
	// with identity providers it is recommended to leave this unset.
	RequestedAuthnContext   *RequestedAuthnContext
	AudienceURI             string
	IDPCertificateStore     dsig.X509CertificateStore
	SPKeyStore              dsig.X509KeyStore // Required encryption key, default signing key
	SPSigningKeyStore       dsig.X509KeyStore // Optional signing key
	NameIdFormat            string
	ValidateEncryptionCert  bool
	SkipSignatureValidation bool
	AllowMissingAttributes  bool
	Clock                   *dsig.Clock
	// contains filtered or unexported fields

func (*SAMLServiceProvider) AuthRedirect

func (sp *SAMLServiceProvider) 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 SAMLServiceProvider's configured IdP, including the relayState provided, if any.

func (*SAMLServiceProvider) BuildAuthBodyPost added in v0.4.0

func (sp *SAMLServiceProvider) BuildAuthBodyPost(relayState string) ([]byte, error)

BuildAuthBodyPost builds the POST body to be sent to IDP.

func (*SAMLServiceProvider) BuildAuthBodyPostFromDocument added in v0.4.0

func (sp *SAMLServiceProvider) 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 (*SAMLServiceProvider) BuildAuthRequest

func (sp *SAMLServiceProvider) BuildAuthRequest() (string, error)

BuildAuthRequest builds <AuthnRequest> for identity provider

func (*SAMLServiceProvider) BuildAuthRequestDocument

func (sp *SAMLServiceProvider) BuildAuthRequestDocument() (*etree.Document, error)

func (*SAMLServiceProvider) BuildAuthRequestDocumentNoSig

func (sp *SAMLServiceProvider) BuildAuthRequestDocumentNoSig() (*etree.Document, error)

func (*SAMLServiceProvider) BuildAuthURL

func (sp *SAMLServiceProvider) BuildAuthURL(relayState string) (string, error)

BuildAuthURL builds redirect URL to be sent to principal

func (*SAMLServiceProvider) BuildAuthURLFromDocument

func (sp *SAMLServiceProvider) BuildAuthURLFromDocument(relayState string, doc *etree.Document) (string, error)

func (*SAMLServiceProvider) BuildAuthURLRedirect

func (sp *SAMLServiceProvider) BuildAuthURLRedirect(relayState string, doc *etree.Document) (string, error)

func (*SAMLServiceProvider) BuildLogoutBodyPostFromDocument added in v0.4.0

func (sp *SAMLServiceProvider) 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 (*SAMLServiceProvider) BuildLogoutRequestDocument added in v0.4.0

func (sp *SAMLServiceProvider) BuildLogoutRequestDocument(nameID string, sessionIndex string) (*etree.Document, error)

func (*SAMLServiceProvider) BuildLogoutRequestDocumentNoSig added in v0.4.0

func (sp *SAMLServiceProvider) BuildLogoutRequestDocumentNoSig(nameID string, sessionIndex string) (*etree.Document, error)

func (*SAMLServiceProvider) BuildLogoutResponseBodyPostFromDocument added in v0.4.0

func (sp *SAMLServiceProvider) BuildLogoutResponseBodyPostFromDocument(relayState string, doc *etree.Document) ([]byte, error)

func (*SAMLServiceProvider) BuildLogoutResponseDocument added in v0.4.0

func (sp *SAMLServiceProvider) BuildLogoutResponseDocument(status string, reqID string) (*etree.Document, error)

func (*SAMLServiceProvider) BuildLogoutResponseDocumentNoSig added in v0.4.0

func (sp *SAMLServiceProvider) BuildLogoutResponseDocumentNoSig(status string, reqID string) (*etree.Document, error)

func (*SAMLServiceProvider) BuildLogoutURLRedirect added in v0.4.0

func (sp *SAMLServiceProvider) BuildLogoutURLRedirect(relayState string, doc *etree.Document) (string, error)

func (*SAMLServiceProvider) GetEncryptionCertBytes

func (sp *SAMLServiceProvider) GetEncryptionCertBytes() ([]byte, error)

func (*SAMLServiceProvider) GetEncryptionKey

func (sp *SAMLServiceProvider) GetEncryptionKey() dsig.X509KeyStore

func (*SAMLServiceProvider) GetSigningCertBytes

func (sp *SAMLServiceProvider) GetSigningCertBytes() ([]byte, error)

func (*SAMLServiceProvider) GetSigningKey

func (sp *SAMLServiceProvider) GetSigningKey() dsig.X509KeyStore

func (*SAMLServiceProvider) Metadata

func (sp *SAMLServiceProvider) Metadata() (*types.EntityDescriptor, error)

func (*SAMLServiceProvider) MetadataWithSLO added in v0.4.0

func (sp *SAMLServiceProvider) MetadataWithSLO(validityHours int64) (*types.EntityDescriptor, error)

func (*SAMLServiceProvider) RetrieveAssertionInfo

func (sp *SAMLServiceProvider) RetrieveAssertionInfo(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 (*SAMLServiceProvider) SignAuthnRequest

func (sp *SAMLServiceProvider) SignAuthnRequest(el *etree.Element) (*etree.Element, error)

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.


func (*SAMLServiceProvider) SignLogoutRequest added in v0.4.0

func (sp *SAMLServiceProvider) SignLogoutRequest(el *etree.Element) (*etree.Element, error)

func (*SAMLServiceProvider) SignLogoutResponse added in v0.4.0

func (sp *SAMLServiceProvider) SignLogoutResponse(el *etree.Element) (*etree.Element, error)

func (*SAMLServiceProvider) SigningContext

func (sp *SAMLServiceProvider) SigningContext() *dsig.SigningContext

func (*SAMLServiceProvider) Validate

func (sp *SAMLServiceProvider) Validate(response *types.Response) error

Validate ensures that the assertion passed is valid for the current Service Provider.

func (*SAMLServiceProvider) ValidateDecodedLogoutRequest added in v0.4.0

func (sp *SAMLServiceProvider) ValidateDecodedLogoutRequest(request *LogoutRequest) error

func (*SAMLServiceProvider) ValidateDecodedLogoutResponse added in v0.4.0

func (sp *SAMLServiceProvider) ValidateDecodedLogoutResponse(response *types.LogoutResponse) error

func (*SAMLServiceProvider) ValidateEncodedLogoutRequestPOST added in v0.4.0

func (sp *SAMLServiceProvider) ValidateEncodedLogoutRequestPOST(encodedRequest string) (*LogoutRequest, error)

func (*SAMLServiceProvider) ValidateEncodedLogoutResponsePOST added in v0.4.0

func (sp *SAMLServiceProvider) ValidateEncodedLogoutResponsePOST(encodedResponse string) (*types.LogoutResponse, error)

func (*SAMLServiceProvider) ValidateEncodedResponse

func (sp *SAMLServiceProvider) ValidateEncodedResponse(encodedResponse string) (*types.Response, error)

ValidateEncodedResponse both decodes and validates, based on SP configuration, an encoded, signed response. It will also appropriately decrypt a response if the assertion was encrypted

func (*SAMLServiceProvider) VerifyAssertionConditions

func (sp *SAMLServiceProvider) VerifyAssertionConditions(assertion *types.Assertion) (*WarningInfo, error)

VerifyAssertionConditions inspects an assertion element and makes sure that all SAML2 contracts are upheld.

type Values

type Values map[string]types.Attribute

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

func (vals Values) Get(k string) string

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.

func (Values) GetAll added in v0.4.0

func (vals Values) GetAll(k string) []string

GetAll returns all the values for an attribute at a key. Returns an empty slice in case of error of if key is not found.

func (Values) GetSize added in v0.4.0

func (vals Values) GetSize(k string) int

GetSize returns the number of values for an attribute at a key. Returns '0' in case of error or if key is not found.

type WarningInfo

type WarningInfo struct {
	OneTimeUse       bool
	ProxyRestriction *ProxyRestriction
	NotInAudience    bool
	InvalidTime      bool


Path Synopsis

Jump to

Keyboard shortcuts

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