Documentation
¶
Overview ¶
Package saml contains a partial implementation of the SAML standard in golang. SAML is a standard for identity federation, i.e. either allowing a third party to authenticate your users or allowing third parties to rely on us to authenticate their users.
Introduction ¶
In SAML parlance an Identity Provider (IDP) is a service that knows how to authenticate users. A Service Provider (SP) is a service that delegates authentication to an IDP. If you are building a service where users log in with someone else's credentials, then you are a Service Provider. This package supports implementing both service providers and identity providers.
The core package contains the implementation of SAML. The package samlsp provides helper middleware suitable for use in Service Provider applications. The package samlidp provides a rudimentary IDP service that is useful for testing or as a starting point for other integrations.
Breaking Changes ¶
Version 0.4.0 introduces a few breaking changes to the _samlsp_ package in order to make the package more extensible, and to clean up the interfaces a bit. The default behavior remains the same, but you can now provide interface implementations of _RequestTracker_ (which tracks pending requests), _Session_ (which handles maintaining a session) and _OnError_ which handles reporting errors.
Public fields of _samlsp.Middleware_ have changed, so some usages may require adjustment. See [issue 231](https://github.com/crewjam/saml/issues/231) for details.
The option to provide an IDP metadata URL has been deprecated. Instead, we recommend that you use the `FetchMetadata()` function, or fetch the metadata yourself and use the new `ParseMetadata()` function, and pass the metadata in _samlsp.Options.IDPMetadata_.
Similarly, the _HTTPClient_ field is now deprecated because it was only used for fetching metdata, which is no longer directly implemented.
The fields that manage how cookies are set are deprecated as well. To customize how cookies are managed, provide custom implementation of _RequestTracker_ and/or _Session_, perhaps by extending the default implementations.
The deprecated fields have not been removed from the Options structure, but will be in future.
In particular we have deprecated the following fields in _samlsp.Options_:
- `Logger` - This was used to emit errors while validating, which is an anti-pattern. - `IDPMetadataURL` - Instead use `FetchMetadata()` - `HTTPClient` - Instead pass httpClient to FetchMetadata - `CookieMaxAge` - Instead set MaxAge on both the CookieSessionProvider and its JWTSessionCodec (see "Customizing the session lifetime" below) - `CookieName` - Instead assign a custom CookieRequestTracker or CookieSessionProvider - `CookieDomain` - Instead assign a custom CookieRequestTracker or CookieSessionProvider
Customizing the session lifetime ¶
Sessions last one hour by default. To change that, set the MaxAge of both the session cookie and the JWT it holds, then assign the provider to the middleware:
sessionMaxAge := 12 * time.Hour codec := samlsp.DefaultSessionCodec(opts) codec.MaxAge = sessionMaxAge sessionProvider := samlsp.DefaultSessionProvider(opts) sessionProvider.MaxAge = sessionMaxAge sessionProvider.Codec = codec middleware, _ := samlsp.New(opts) middleware.Session = sessionProvider
Setting only the cookie's MaxAge is not enough: the browser keeps the cookie, but the token in it is rejected once the JWT expires.
Getting Started as a Service Provider ¶
Let us assume we have a simple web application to protect. We'll modify this application so it uses SAML to authenticate users.
```golang package main
import (
"fmt" "net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
app := http.HandlerFunc(hello)
http.Handle("/hello", app)
http.ListenAndServe(":8000", nil)
}
```
Each service provider must have an self-signed X.509 key pair established. You can generate your own with something like this:
openssl req -x509 -newkey rsa:2048 -keyout myservice.key -out myservice.cert -days 365 -nodes -subj "/CN=myservice.example.com"
We will use `samlsp.Middleware` to wrap the endpoint we want to protect. Middleware provides both an `http.Handler` to serve the SAML specific URLs and a set of wrappers to require the user to be logged in. We also provide the URL where the service provider can fetch the metadata from the IDP at startup. In our case, we'll use [samltest.dev](https://www.samltest.dev/), an identity provider designed for testing.
samltest.dev gives each app its own IDP, so first create an app with at least one test user. You can do this on the website or with the [API](https://www.samltest.dev/#api):
curl -X POST https://www.samltest.dev/api/apps \
-H "Content-Type: application/json" \
-d '{"users":[{"email":"john@example.com","firstName":"John","lastName":"Doe"}]}'
The response contains the app's ID (for example `app_01kg2nmcmp9gey67b0kxpqm643`). The IDP metadata URL for the app is `https://www.samltest.dev/apps/<APP_ID>/metadata`.
```golang package main
import (
"crypto/rsa" "crypto/tls" "crypto/x509" "fmt" "net/http" "net/url" "github.com/crewjam/saml/samlsp"
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", samlsp.Token(r.Context()).Attributes.Get("cn"))
}
func main() {
keyPair, err := tls.LoadX509KeyPair("myservice.cert", "myservice.key")
if err != nil {
panic(err) // TODO handle error
}
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
if err != nil {
panic(err) // TODO handle error
}
idpMetadataURL, err := url.Parse("https://www.samltest.dev/apps/<APP_ID>/metadata")
if err != nil {
panic(err) // TODO handle error
}
rootURL, err := url.Parse("http://localhost:8000")
if err != nil {
panic(err) // TODO handle error
}
samlSP, _ := samlsp.New(samlsp.Options{
URL: *rootURL,
Key: keyPair.PrivateKey.(*rsa.PrivateKey),
Certificate: keyPair.Leaf,
IDPMetadataURL: idpMetadataURL,
})
app := http.HandlerFunc(hello)
http.Handle("/hello", samlSP.RequireAccount(app))
http.Handle("/saml/", samlSP)
http.ListenAndServe(":8000", nil)
}
```
Next we'll have to register our service provider with the identity provider to establish trust from the service provider to the IDP. samltest.dev doesn't take an uploaded metadata file. Instead, set the app's SP ACS URL and SP Entity ID, either under "SAML SP Settings" on `https://www.samltest.dev/apps/<APP_ID>` or with the API:
curl -X PUT https://www.samltest.dev/api/apps/<APP_ID> \
-H "Content-Type: application/json" \
-d '{"users":[{"email":"john@example.com","firstName":"John","lastName":"Doe"}],
"spAcsUrl":"http://localhost:8000/saml/acs",
"spEntityId":"http://localhost:8000/saml/metadata"}'
By default `samlsp` uses `<root URL>/saml/acs` as the ACS URL and `<root URL>/saml/metadata` as the entity ID. You can view the service provider's metadata at `localhost:8000/saml/metadata`.
Now you should be able to authenticate. The flow should look like this:
1. You browse to `localhost:8000/hello`
1. The middleware redirects you to `https://www.samltest.dev/apps/<APP_ID>/login`
1. samltest.dev asks which of the app's test users you want to log in as. There is no password.
1. samltest.dev returns you an HTML document which contains an HTML form setup to POST to `localhost:8000/saml/acs`. The form is automatically submitted if you have javascript enabled.
1. The local service validates the response, issues a session cookie, and redirects you to the original URL, `localhost:8000/hello`.
1. This time when `localhost:8000/hello` is requested there is a valid session and so the main content is served.
Getting Started as an Identity Provider ¶
Please see `example/idp/` for a substantially complete example of how to use the library and helpers to be an identity provider.
Support ¶
The SAML standard is huge and complex with many dark corners and strange, unused features. This package implements the most commonly used subset of these features required to provide a single sign on experience. The package supports at least the subset of SAML known as [interoperable SAML](http://saml2int.org).
This package supports the Web SSO profile. Message flows from the service provider to the IDP are supported using the HTTP Redirect binding and the HTTP POST binding. Message flows from the IDP to the service provider are supported via the HTTP POST binding.
Both directions also support the HTTP POST SimpleSign binding (sstc-saml-binding-simplesign-cs-01), which signs the posted message with a detached signature in the SigAlg and Signature form fields. See HTTPPostSimpleSignBinding.
The package can produce signed SAML assertions, and can validate both signed and encrypted SAML assertions.
RelayState ¶
The _RelayState_ parameter allows you to pass user state information across the authentication flow. The most common use for this is to allow a user to request a deep link into your site, be redirected through the SAML login flow, and upon successful completion, be directed to the originally requested link, rather than the root.
Unfortunately, _RelayState_ is less useful than it could be. Firstly, it is not authenticated, so anything you supply must be signed to avoid XSS or CSRF. Secondly, it is limited to 80 bytes in length, which precludes signing. (See section 3.6.3.1 of SAMLProfiles.)
References ¶
The SAML specification is a collection of PDFs (sadly):
- [SAMLCore](http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf) defines data types.
- [SAMLBindings](http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf) defines the details of the HTTP requests in play.
- [SAMLProfiles](http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf) describes data flows.
- [SAMLConformance](http://docs.oasis-open.org/security/saml/v2.0/saml-conformance-2.0-os.pdf) includes a support matrix for various parts of the protocol.
[SAMLTest](https://www.samltest.dev/) is a free SAML identity provider and SCIM directory for testing SAML service providers.
Security Issues ¶
Please do not report security issues in the issue tracker. Rather, please contact me directly at ross@kndr.org ([PGP Key `78B6038B3B9DFB88`](https://keybase.io/crewjam)).
Index ¶
- Constants
- Variables
- func DefaultAuthnContextClassStrengths() map[string]int
- func GetSigningContext(sp *ServiceProvider) (*dsig.SigningContext, error)
- func IsSOAPRequest(r *http.Request) bool
- func VerifyMetadataSignature(data []byte, certs []*x509.Certificate) ([]byte, error)
- func WriteSOAPFault(w http.ResponseWriter, faultString string) error
- func WriteSOAPLogoutResponse(w http.ResponseWriter, resp *LogoutResponse) error
- type AdditionalMetadataLocation
- type AffiliationDescriptor
- type ArtifactResolve
- type ArtifactResponse
- type Assertion
- type AssertionAttribute
- type AssertionAttributes
- type AssertionMaker
- type AssertionReplayCache
- type Attribute
- type AttributeAuthorityDescriptor
- type AttributeConsumingService
- type AttributeQuery
- type AttributeQueryResult
- type AttributeStatement
- type AttributeValue
- type Audience
- type AudienceRestriction
- type AuthenticatingAuthority
- type AuthnAuthorityDescriptor
- type AuthnContext
- type AuthnContextClassRef
- type AuthnRequest
- func (r *AuthnRequest) Element() *etree.Element
- func (r *AuthnRequest) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
- func (r *AuthnRequest) Post(relayState string) []byte
- func (r *AuthnRequest) PostWithNonce(relayState, nonce string) []byte
- func (r *AuthnRequest) Redirect(relayState string, sp *ServiceProvider) (*url.URL, error)
- func (r *AuthnRequest) SimpleSign(relayState string, sp *ServiceProvider) ([]byte, error)
- func (r *AuthnRequest) SimpleSignWithNonce(relayState, nonce string, sp *ServiceProvider) ([]byte, error)
- func (r *AuthnRequest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
- type AuthnStatement
- type Conditions
- type ContactPerson
- type DefaultAssertionMaker
- type DefaultResponseWriter
- type DigestMethod
- type Duration
- type EncryptionMethod
- type Endpoint
- type EntitiesDescriptor
- type EntityDescriptor
- type ErrBadStatus
- type ExtensionElement
- type Extensions
- type IDPEntry
- type IDPList
- type IDPSSODescriptor
- type IdentityProvider
- func (idp *IdentityProvider) DefaultOnError(w http.ResponseWriter, _ *http.Request, status int, err error)
- func (idp *IdentityProvider) Handler() http.Handler
- func (idp *IdentityProvider) Metadata() *EntityDescriptor
- func (idp *IdentityProvider) NewIdpInitiatedRequest(r *http.Request, serviceProviderID string, relayState string) (*IdpAuthnRequest, error)
- func (idp *IdentityProvider) SendErrorResponse(w http.ResponseWriter, req *IdpAuthnRequest, statusErr *StatusError) error
- func (idp *IdentityProvider) ServeIDPInitiated(w http.ResponseWriter, r *http.Request, serviceProviderID string, ...)
- func (idp *IdentityProvider) ServeMetadata(w http.ResponseWriter, r *http.Request)
- func (idp *IdentityProvider) ServeSLO(w http.ResponseWriter, r *http.Request)
- func (idp *IdentityProvider) ServeSSO(w http.ResponseWriter, r *http.Request)
- func (idp *IdentityProvider) SignedMetadata() (*etree.Element, error)
- func (idp *IdentityProvider) StartLogout(w http.ResponseWriter, r *http.Request, session *Session, returnURL string)
- type IdpAuthnRequest
- func (req *IdpAuthnRequest) CheckRequestSubject() error
- func (req *IdpAuthnRequest) MakeAssertionEl() error
- func (req *IdpAuthnRequest) MakeErrorResponse(topLevel, secondLevel, message string) error
- func (req *IdpAuthnRequest) MakeResponse() error
- func (req *IdpAuthnRequest) PostBinding() (IdpAuthnRequestForm, error)
- func (req *IdpAuthnRequest) SimpleSignBinding() (IdpAuthnRequestSimpleSignForm, error)
- func (req *IdpAuthnRequest) Validate() error
- func (req *IdpAuthnRequest) WriteResponse(w http.ResponseWriter) error
- type IdpAuthnRequestForm
- type IdpAuthnRequestSimpleSignForm
- type IdpLogoutRequest
- type IndexedEndpoint
- type InvalidResponseError
- type Issuer
- type KeyDescriptor
- type KeyInfo
- type LocalizedName
- type LocalizedURI
- type LogoutRequest
- func (r *LogoutRequest) AllSessionIndexes() []SessionIndex
- func (r *LogoutRequest) Bytes() ([]byte, error)
- func (r *LogoutRequest) Deflate() ([]byte, error)
- func (r *LogoutRequest) Element() *etree.Element
- func (r *LogoutRequest) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
- func (r *LogoutRequest) Post(relayState string) []byte
- func (r *LogoutRequest) PostWithNonce(relayState, nonce string) []byte
- func (r *LogoutRequest) Redirect(relayState string) *url.URL
- func (r *LogoutRequest) SimpleSign(relayState string, sp *ServiceProvider) ([]byte, error)
- func (r *LogoutRequest) SimpleSignWithNonce(relayState, nonce string, sp *ServiceProvider) ([]byte, error)
- func (r *LogoutRequest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
- type LogoutRequestOption
- type LogoutResponse
- func (r *LogoutResponse) Element() *etree.Element
- func (r *LogoutResponse) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
- func (r *LogoutResponse) Post(relayState string) []byte
- func (r *LogoutResponse) PostWithNonce(relayState, nonce string) []byte
- func (r *LogoutResponse) Redirect(relayState string) *url.URL
- func (r *LogoutResponse) SimpleSign(relayState string, sp *ServiceProvider) ([]byte, error)
- func (r *LogoutResponse) SimpleSignWithNonce(relayState, nonce string, sp *ServiceProvider) ([]byte, error)
- func (r *LogoutResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
- type NameID
- type NameIDFormat
- type NameIDPolicy
- type OneTimeUse
- type Organization
- type PDPDescriptor
- type ProxyRestriction
- type RelaxedTime
- type RequestedAttribute
- type RequestedAuthnContext
- type Response
- type ResponseWriter
- type RoleDescriptor
- type SPSSODescriptor
- type SSODescriptor
- type Scoping
- type ServiceProvider
- func (sp *ServiceProvider) EncryptLogoutRequestNameID(req *LogoutRequest) error
- func (sp *ServiceProvider) GetArtifactBindingLocation(binding string) string
- func (sp *ServiceProvider) GetAttributeServiceLocation(binding string) string
- func (sp *ServiceProvider) GetSLOBindingLocation(binding string) string
- func (sp *ServiceProvider) GetSSOBindingLocation(binding string) string
- func (sp *ServiceProvider) MakeArtifactResolveRequest(artifactID string) (*ArtifactResolve, error)
- func (sp *ServiceProvider) MakeAttributeQuery(nameID NameID, attributes ...Attribute) (*AttributeQuery, error)
- func (sp *ServiceProvider) MakeAuthenticationRequest(idpURL string, binding string, resultBinding string) (*AuthnRequest, error)
- func (sp *ServiceProvider) MakeLogoutRequest(idpURL, nameID string, opts ...LogoutRequestOption) (*LogoutRequest, error)
- func (sp *ServiceProvider) MakeLogoutResponse(idpURL, logoutRequestID string) (*LogoutResponse, error)
- func (sp *ServiceProvider) MakePostAuthenticationRequest(relayState string) ([]byte, error)
- func (sp *ServiceProvider) MakePostLogoutRequest(nameID, relayState string, opts ...LogoutRequestOption) ([]byte, error)
- func (sp *ServiceProvider) MakePostLogoutResponse(logoutRequestID, relayState string) ([]byte, error)
- func (sp *ServiceProvider) MakeRedirectAuthenticationRequest(relayState string) (*url.URL, error)
- func (sp *ServiceProvider) MakeRedirectLogoutRequest(nameID, relayState string, opts ...LogoutRequestOption) (*url.URL, error)
- func (sp *ServiceProvider) MakeRedirectLogoutResponse(logoutRequestID, relayState string) (*url.URL, error)
- func (sp *ServiceProvider) MakeSOAPLogoutRequest(nameID NameID, opts ...LogoutRequestOption) (*LogoutRequest, error)
- func (sp *ServiceProvider) MakeSOAPLogoutResponse(logoutRequestID string, status Status) (*LogoutResponse, error)
- func (sp *ServiceProvider) MakeSimpleSignAuthenticationRequest(relayState string) ([]byte, error)
- func (sp *ServiceProvider) MakeSimpleSignLogoutRequest(nameID, relayState string, opts ...LogoutRequestOption) ([]byte, error)
- func (sp *ServiceProvider) MakeSimpleSignLogoutResponse(logoutRequestID, relayState string) ([]byte, error)
- func (sp *ServiceProvider) Metadata() *EntityDescriptor
- func (sp *ServiceProvider) ParseLogoutResponse(req *http.Request, possibleRequestIDs []string) (*LogoutResponse, error)
- func (sp *ServiceProvider) ParseResponse(req *http.Request, possibleRequestIDs []string) (*Assertion, error)
- func (sp *ServiceProvider) ParseXMLArtifactResponse(soapResponseXML []byte, possibleRequestIDs []string, artifactRequestID string, ...) (*Assertion, error)
- func (sp *ServiceProvider) ParseXMLAttributeQueryResponse(soapResponseXML []byte, query *AttributeQuery) (*AttributeQueryResult, error)
- func (sp *ServiceProvider) ParseXMLResponse(decodedResponseXML []byte, possibleRequestIDs []string, currentURL url.URL) (*Assertion, error)
- func (sp *ServiceProvider) ParseXMLSOAPLogoutRequest(soapRequestXML []byte) (*LogoutRequest, error)
- func (sp *ServiceProvider) ParseXMLSOAPLogoutResponse(soapResponseXML []byte, req *LogoutRequest) (*LogoutResponse, error)
- func (sp *ServiceProvider) QueryAttributes(ctx context.Context, nameID NameID, attributes ...Attribute) (*AttributeQueryResult, error)
- func (sp *ServiceProvider) RedirectLogoutRequestURL(req *LogoutRequest, relayState string) (*url.URL, error)
- func (sp *ServiceProvider) SendSOAPLogoutRequest(ctx context.Context, req *LogoutRequest) (*LogoutResponse, error)
- func (sp *ServiceProvider) SignArtifactResolve(req *ArtifactResolve) error
- func (sp *ServiceProvider) SignAttributeQuery(req *AttributeQuery) error
- func (sp *ServiceProvider) SignAuthnRequest(req *AuthnRequest) error
- func (sp *ServiceProvider) SignLogoutRequest(req *LogoutRequest) error
- func (sp *ServiceProvider) SignLogoutResponse(resp *LogoutResponse) error
- func (sp *ServiceProvider) SignedMetadata() (*etree.Element, error)
- func (sp *ServiceProvider) ValidateLogoutRequest(req *http.Request) (*LogoutRequest, error)
- func (sp *ServiceProvider) ValidateLogoutRequestForm(postFormData string) (*LogoutRequest, error)
- func (sp *ServiceProvider) ValidateLogoutResponseForm(postFormData string) errordeprecated
- func (sp *ServiceProvider) ValidateLogoutResponseRedirect(queryParameterData string) errordeprecated
- func (sp *ServiceProvider) ValidateLogoutResponseRequest(req *http.Request) errordeprecated
- func (sp *ServiceProvider) ValidateSOAPLogoutRequest(r *http.Request) (*LogoutRequest, error)
- type ServiceProviderProvider
- type Session
- type SessionIndex
- type SessionInvalidator
- type SessionParticipant
- type SessionParticipantTracker
- type SessionProvider
- type ShibbolethScope
- type SignatureVerifier
- type SignedElementVerifier
- type SigningMethod
- type Status
- type StatusCode
- type StatusDetail
- type StatusError
- type StatusMessage
- type Subject
- type SubjectConfirmation
- type SubjectConfirmationData
- type SubjectLocality
- type X509Certificate
- type X509Data
Constants ¶
const ( // StatusRequester means the request could not be performed due to an error on the part of the requester. StatusRequester = "urn:oasis:names:tc:SAML:2.0:status:Requester" // StatusResponder means the request could not be performed due to an error on the part of the SAML responder or SAML authority. StatusResponder = "urn:oasis:names:tc:SAML:2.0:status:Responder" // StatusVersionMismatch means the SAML responder could not process the request because the version of the request message was incorrect. StatusVersionMismatch = "urn:oasis:names:tc:SAML:2.0:status:VersionMismatch" // StatusAuthnFailed means the responding provider was unable to successfully authenticate the principal. StatusAuthnFailed = "urn:oasis:names:tc:SAML:2.0:status:AuthnFailed" // StatusInvalidAttrNameOrValue means Unexpected or invalid content was encountered within a <saml:Attribute> or <saml:AttributeValue> element. StatusInvalidAttrNameOrValue = "urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue" // StatusInvalidNameIDPolicy means the responding provider cannot or will not support the requested name identifier policy. StatusInvalidNameIDPolicy = "urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy" // StatusNoAuthnContext means the specified authentication context requirements cannot be met by the responder. StatusNoAuthnContext = "urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext" // StatusNoAvailableIDP is used by an intermediary to indicate that none of the supported identity provider <Loc> elements in an <IDPList> can be resolved or that none of the supported identity providers are available. StatusNoAvailableIDP = "urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP" // StatusNoPassive means Indicates the responding provider cannot authenticate the principal passively, as has been requested. StatusNoPassive = "urn:oasis:names:tc:SAML:2.0:status:NoPassive" //nolint:gosec // StatusNoSupportedIDP is used by an intermediary to indicate that none of the identity providers in an <IDPList> are supported by the intermediary. StatusNoSupportedIDP = "urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP" // StatusPartialLogout is used by a session authority to indicate to a session participant that it was not able to propagate logout to all other session participants. StatusPartialLogout = "urn:oasis:names:tc:SAML:2.0:status:PartialLogout" // StatusProxyCountExceeded means Indicates that a responding provider cannot authenticate the principal directly and is not permitted to proxy the request further. StatusProxyCountExceeded = "urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded" // StatusRequestDenied means the SAML responder or SAML authority is able to process the request but has chosen not to respond. This status code MAY be used when there is concern about the security context of the request message or the sequence of request messages received from a particular requester. StatusRequestDenied = "urn:oasis:names:tc:SAML:2.0:status:RequestDenied" // StatusRequestUnsupported means the SAML responder or SAML authority does not support the request. StatusRequestUnsupported = "urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported" // StatusRequestVersionDeprecated means the SAML responder cannot process any requests with the protocol version specified in the request. StatusRequestVersionDeprecated = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated" //nolint:gosec // StatusRequestVersionTooHigh means the SAML responder cannot process the request because the protocol version specified in the request message is a major upgrade from the highest protocol version supported by the responder. StatusRequestVersionTooHigh = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh" // StatusRequestVersionTooLow means the SAML responder cannot process the request because the protocol version specified in the request message is too low. StatusRequestVersionTooLow = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow" // StatusResourceNotRecognized means the resource value provided in the request message is invalid or unrecognized. StatusResourceNotRecognized = "urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized" // StatusTooManyResponses means the response message would contain more elements than the SAML responder is able to return. StatusTooManyResponses = "urn:oasis:names:tc:SAML:2.0:status:TooManyResponses" // StatusUnknownAttrProfile means an entity that has no knowledge of a particular attribute profile has been presented with an attribute means drawn from that profile. StatusUnknownAttrProfile = "urn:oasis:names:tc:SAML:2.0:status:UnknownAttrProfile" // StatusUnknownPrincipal means the responding provider does not recognize the principal specified or implied by the request. StatusUnknownPrincipal = "urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal" // StatusUnsupportedBinding means the SAML responder cannot properly fulfill the request using the protocol binding specified in the request. StatusUnsupportedBinding = "urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding" )
const AlgSupportNamespace = "urn:oasis:names:tc:SAML:metadata:algsupport"
AlgSupportNamespace is the namespace of the SAML V2.0 Metadata Profile for Algorithm Support.
See https://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-algsupport-v1.0-cs01.html
const DefaultCacheDuration = time.Hour * 24 * 1
DefaultCacheDuration is how long we ask the IDP to cache the SP metadata.
const DefaultValidDuration = time.Hour * 24 * 2
DefaultValidDuration is how long we assert that the SP metadata is valid.
const HTTPArtifactBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
HTTPArtifactBinding is the official URN for the HTTP-Artifact binding (transport)
const HTTPPostBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
HTTPPostBinding is the official URN for the HTTP-POST binding (transport)
const HTTPPostSimpleSignBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
HTTPPostSimpleSignBinding is the official URN for the HTTP-POST-SimpleSign binding (transport), defined in sstc-saml-binding-simplesign-cs-01. It carries messages in an HTML form like HTTP-POST, but signs them with a detached signature over the message XML, the RelayState and the SigAlg instead of (or as well as) an XML signature.
The service provider can send authentication requests and logout messages with it (MakeSimpleSignAuthenticationRequest, MakeSimpleSignLogoutRequest, MakeSimpleSignLogoutResponse), and accepts it at the ACS (ParseResponse) and in the logout validation functions. The identity provider accepts authentication requests sent with it and uses it for responses to an AssertionConsumerService endpoint with this binding.
const HTTPRedirectBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
HTTPRedirectBinding is the official URN for the HTTP-Redirect binding (transport)
const MaxRelayStateLength = 80
MaxRelayStateLength is the longest RelayState, in bytes, that a SAML message may carry with the HTTP-Redirect, HTTP-POST and HTTP-POST-SimpleSign bindings: "The value MUST NOT exceed 80 bytes in length" (saml-bindings-2.0-os §3.4.3 and §3.5.3).
const SOAPBinding = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
SOAPBinding is the official URN for the SOAP binding (transport)
const SOAPBindingV1 = "urn:oasis:names:tc:SAML:1.0:bindings:SOAP-binding"
SOAPBindingV1 is the URN for the SOAP binding in SAML 1.0
const ShibbolethMetadataNamespace = "urn:mace:shibboleth:metadata:1.0"
ShibbolethMetadataNamespace is the namespace of the Shibboleth metadata extensions, such as shibmd:Scope.
const X500AttributeNamespace = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
X500AttributeNamespace is the namespace of the x500:Encoding XML attribute defined by the X.500/LDAP attribute profile (saml-profiles §8.2.4).
const X500EncodingLDAP = "LDAP"
X500EncodingLDAP is the x500:Encoding value the X.500/LDAP attribute profile requires (saml-profiles §8.2.4).
Variables ¶
var ( // ErrInvalidSignature is attached to every failure to validate the XML // signature on a Response, Assertion or ArtifactResponse. The more // specific errors below are attached in addition to it. It is also // attached when ServiceProvider.RequireSignedResponseForCBC refuses a // CBC-encrypted assertion because the Response carrying it is not // signed. ErrInvalidSignature = errors.New("saml: invalid signature") // ErrUntrustedCertificate is attached when the element is signed with a // certificate that is not one of the trusted IdP certificates (from the // IdP metadata, ServiceProvider.IDPCertificate, or the configured // fingerprint). This commonly means the IdP rotated its signing // certificate and the IdP metadata held by the SP needs to be updated. ErrUntrustedCertificate = errors.New("saml: signing certificate is not trusted") // ErrCertificateNotValidNow is attached when the element is signed with // a trusted certificate that is expired or not yet valid. See // ServiceProvider.IgnoreCertificateExpiry. ErrCertificateNotValidNow = errors.New("saml: signing certificate is expired or not yet valid") )
Errors that the ServiceProvider attaches to signature validation failures, so that callers can tell them apart with errors.Is instead of matching error strings. They are reachable through the *InvalidResponseError that ParseResponse and ParseXMLResponse return:
assertion, err := sp.ParseResponse(r, requestIDs)
if errors.Is(err, saml.ErrUntrustedCertificate) {
// the IdP signed with a certificate that is not in its metadata;
// the metadata may be out of date
}
The message of the error returned is unchanged by this classification.
var ( // ErrMalformedMessage is attached when a message cannot be decoded or // parsed: bad base64, deflate or form encoding, invalid XML, a missing root // element, an element that cannot be unmarshalled, or more instances of // an element than allowed. ErrMalformedMessage = errors.New("saml: malformed message") // ErrMissingElement is attached when a required element or value is // absent: no Assertion, an Assertion with no Subject, Conditions, ID, // AuthnStatement, SubjectConfirmationData or bearer SubjectConfirmation, // a LogoutRequest with no NameID, an AuthnRequest with no Issuer or ID, // or another required child element. ErrMissingElement = errors.New("saml: required element is missing") // ErrExpired is attached when a message or assertion is no longer valid: // its IssueInstant is older than MaxIssueDelay, or a NotOnOrAfter // (allowing MaxClockSkew) has passed. Check the clocks of the IdP and // SP if this happens for fresh logins. ErrExpired = errors.New("saml: expired") // ErrNotYetValid is attached when a message or assertion is not valid // yet: a Conditions or SubjectConfirmationData NotBefore (allowing // MaxClockSkew) or a LogoutRequest IssueInstant in the future. This usually means the IdP and SP clocks // disagree. ErrNotYetValid = errors.New("saml: not yet valid") // ErrIssuerMismatch is attached when the Issuer of a message or // assertion is not the EntityID in the IdP metadata. ErrIssuerMismatch = errors.New("saml: issuer does not match the IdP metadata") // ErrDestinationMismatch is attached when a message was not addressed to // its recipient. At the SP: a Destination that is neither the requested // URL nor AcsURL (or SloURL, for logout messages), or a // SubjectConfirmationData Recipient that is not AcsURL. At the IdP: an // AuthnRequest Destination that is not IdentityProvider.SSOURL. ErrDestinationMismatch = errors.New("saml: destination does not match the recipient") // ErrRequestIDMismatch is attached when an InResponseTo does not name // one of the requests this SP made (possibleRequestIDs), or the artifact // request ID for an ArtifactResponse. ErrRequestIDMismatch = errors.New("saml: InResponseTo does not match a request ID") // ErrAudienceMismatch is attached when the assertion is not restricted // to this SP's audience, or ServiceProvider.ValidateAudienceRestriction // rejects it. ErrAudienceMismatch = errors.New("saml: audience restriction does not match this service provider") // ErrAuthnContextMismatch is attached when // ServiceProvider.ValidateAuthnContextClassRef is set and none of the // assertion's AuthnContextClassRefs is one of those in // ServiceProvider.RequestedAuthnContext (or, for a Comparison other than // "exact", none is accepted by AuthnContextClassRefComparator): the user // did not authenticate the way the SP asked. ErrAuthnContextMismatch = errors.New("saml: authentication context does not match the requested one") // ErrDecryptionFailed is attached when an EncryptedAssertion or // EncryptedID cannot be decrypted with the SP's keys. ErrDecryptionFailed = errors.New("saml: cannot decrypt") // ErrArtifactResolution is attached when resolving an artifact with the // IdP fails: building the request, the HTTP exchange, or a non-200 // status. ErrArtifactResolution = errors.New("saml: artifact resolution failed") // ErrUnknownServiceProvider is attached when an AuthnRequest's Issuer is // not a service provider the IdP knows: its ServiceProviderProvider // returned os.ErrNotExist, which the error also matches. ErrUnknownServiceProvider = errors.New("saml: unknown service provider") // ErrUnknownAssertionConsumerService is attached when the // AssertionConsumerServiceURL or AssertionConsumerServiceIndex of an // AuthnRequest is not in the service provider's metadata, or the // metadata has no usable assertion consumer service. The SP metadata the // IdP holds may be out of date. ErrUnknownAssertionConsumerService = errors.New("saml: unknown assertion consumer service") // ErrUnsupported is attached when something is used that is not // implemented. At the IdP: an HTTP method other than GET or POST, a SAML // version other than 2.0, signed AuthnRequests (WantAuthnRequestsSigned), // or an assertion consumer service binding other than HTTP-POST. At the // SP: a Response, ArtifactResponse, assertion, LogoutRequest or // LogoutResponse whose Version is not 2.0, a RequestedAuthnContext // Comparison other than "exact" when // ValidateAuthnContextClassRef is set and AuthnContextClassRefComparator // is not, or, with RejectUnknownConditions, an assertion whose Conditions // has a condition this package does not understand. ErrUnsupported = errors.New("saml: not supported") // ErrRelayStateTooLong is returned, when ServiceProvider or // IdentityProvider LimitRelayStateLength is set, for a message this // package starts that would carry a RelayState longer than // MaxRelayStateLength: an AuthnRequest or LogoutRequest the SP sends, a // RelayState a samlsp RelayStateFunc returns, or the RelayState of an // IdP-initiated Response (ServeIDPInitiated answers HTTP 400). ErrRelayStateTooLong = errors.New("saml: RelayState too long") // ErrInvalidCertificate is attached when a certificate cannot be base64 // decoded or parsed: an IdP signing certificate in the IdP metadata or // ServiceProvider.IDPCertificate, the certificate embedded in a // signature when checking ServiceProvider.IDPCertificateFingerprint, or // an SP encryption certificate in the SP metadata the IdP holds. At the // SP the error also matches ErrInvalidSignature. ErrInvalidCertificate = errors.New("saml: invalid certificate") )
Errors attached to the other reasons a message is rejected: by the ServiceProvider for a Response, Assertion, ArtifactResponse, LogoutResponse or LogoutRequest, and by the IdentityProvider for an AuthnRequest (from NewIdpAuthnRequest and IdpAuthnRequest.Validate). Like the signature errors above, they are matched with errors.Is, through *InvalidResponseError where one is returned, and leave the message of the error unchanged.
A rejected logout response whose status is not success also matches ErrBadStatus with errors.As, as a rejected Response already does.
var Clock *dsig.Clock
Clock is assigned to dsig validation and signing contexts if it is not nil, otherwise the default clock is used.
var ErrAssertionReplayed = errors.New("assertion has already been used")
ErrAssertionReplayed is returned by an AssertionReplayCache for an assertion ID it has already recorded.
var ErrInsecureSOAPEndpoint = errors.New("the SOAP endpoint is not an https URL")
ErrInsecureSOAPEndpoint is returned when a SAML SOAP message would be sent to an endpoint whose Location is not an https URL. SOAP messages go server to server and carry the user's NameID, attributes or a whole assertion. The SOAP binding itself does nothing against an eavesdropper, or against someone who changes the messages in transit: saml-bindings §3.1.2 leaves confidentiality and integrity to the environment of use, typically TLS in the substrate protocol (and §3.6.5.2 does the same for the artifact resolution exchange). IdentityProvider and ServiceProvider choose TLS by default, and refuse http endpoints for the SOAP binding unless AllowInsecureSOAPEndpoints is set.
var ErrNoAttributeService = errors.New("the IdP metadata has no AttributeAuthorityDescriptor with a SOAP AttributeService")
ErrNoAttributeService is returned when the IdP metadata does not publish an AttributeService endpoint (in an AttributeAuthorityDescriptor) with the SAML SOAP binding, so there is nowhere to send an attribute query.
var ErrNoSOAPSingleLogoutService = errors.New("the IdP metadata has no SingleLogoutService with the SOAP binding")
ErrNoSOAPSingleLogoutService is returned by MakeSOAPLogoutRequest when the IdP metadata publishes no SingleLogoutService with the SAML SOAP binding.
var LogoutStateLifetime = 15 * time.Minute
LogoutStateLifetime is how long a single logout that the IdP propagates to several service providers may take, from its start to the last LogoutResponse.
var MaxArtifactResponseSize int64 = 10 << 20
MaxArtifactResponseSize is the largest SOAP response body, in bytes, that the service provider reads from the IDP's ArtifactResolutionService when it resolves an artifact received with the HTTP-Artifact binding. A larger response is rejected without being parsed.
var MaxAttributeQueryResponseSize int64 = 10 << 20
MaxAttributeQueryResponseSize is the largest SOAP response body, in bytes, that QueryAttributes reads from the attribute authority. A larger response is rejected without being parsed.
var MaxClockSkew = time.Second * 180
MaxClockSkew allows for leeway for clock skew between the IDP and SP when validating assertions. It defaults to 180 seconds (matches shibboleth).
var MaxIssueDelay = time.Second * 90
MaxIssueDelay is the longest allowed time between when a SAML assertion is issued by the IDP and the time it is received by ParseResponse. This is used to prevent old responses from being replayed (while allowing for some clock drift between the SP and IDP).
var MaxSOAPLogoutMessageSize int64 = 1 << 20
MaxSOAPLogoutMessageSize is the largest SOAP message body, in bytes, that is read for single logout over the SOAP binding: a LogoutRequest an IdentityProvider or a ServiceProvider receives, and the LogoutResponse either of them receives to its own LogoutRequest. A larger body is rejected without being parsed. Logout messages are small, so the default is far above what a legitimate message needs.
var Metadata = struct{}{}
Metadata as been renamed to EntityDescriptor
This change was made to be consistent with the rest of the API which uses names from the SAML specification for types.
This is a tombstone to help you discover this fact. You should update references to saml.Metadata to be saml.EntityDescriptor.
var RandReader = rand.Reader
RandReader is the io.Reader that produces cryptographically random bytes when they are need by the library. The default value is rand.Reader, but it can be replaced for testing.
var StatusSuccess = "urn:oasis:names:tc:SAML:2.0:status:Success"
StatusSuccess means the request succeeded. Additional information MAY be returned in the <StatusMessage> and/or <StatusDetail> elements.
TODO(ross): this value is mostly constant, but is mutated in tests. Fix the hacky test so this can be const.
var TimeNow = func() time.Time { return time.Now().UTC() }
TimeNow is a function that returns the current time. The default value is time.Now, but it can be replaced for testing.
Functions ¶
func DefaultAuthnContextClassStrengths ¶ added in v0.6.2
DefaultAuthnContextClassStrengths returns the ranking of authentication context classes the IdP uses for the "minimum", "maximum" and "better" Comparisons of a RequestedAuthnContext when IdentityProvider.AuthnContextClassStrengths is nil. A higher number is stronger, and classes with the same number are equally strong:
- InternetProtocol
- InternetProtocolPassword, Password
- PasswordProtectedTransport, SecureRemotePassword
- Kerberos, PGP, SPKI, XMLDSig, TLSClient, X509, Smartcard, TimeSyncToken
- SmartcardPKI
All are classes of saml-authn-context-2.0-os. Any other class, such as unspecified or PreviousSession, is not ranked, and only satisfies a request for it by name. The ranking is a reasonable default, not part of the SAML specification, which leaves the ordering to the responder. The map returned is a new copy, which callers may extend and set as IdentityProvider.AuthnContextClassStrengths.
func GetSigningContext ¶ added in v0.4.6
func GetSigningContext(sp *ServiceProvider) (*dsig.SigningContext, error)
GetSigningContext returns a dsig.SigningContext initialized based on the Service Provider's configuration
func IsSOAPRequest ¶ added in v0.6.2
IsSOAPRequest reports whether r is a message sent with the SAML SOAP binding: a POST whose Content-Type is text/xml (SOAP 1.1 over HTTP, saml-bindings §3.2.3.1). Browser bindings post forms instead.
func VerifyMetadataSignature ¶ added in v0.6.1
func VerifyMetadataSignature(data []byte, certs []*x509.Certificate) ([]byte, error)
VerifyMetadataSignature checks that the root element of the SAML metadata in data, an EntityDescriptor or an EntitiesDescriptor, carries a valid enveloped XML signature made with one of certs (saml-metadata-2.0-os §3). It returns the metadata the signature covers: the root element without its Signature, in the canonical form that was digested.
Parse the returned bytes, not data. Anything data holds that the signature does not cover, such as namespace declarations that exclusive canonicalization leaves out, is not in them.
Only a signature on the root element counts: in an aggregate, signatures on the EntityDescriptors inside are not checked. The certificates' validity periods are not checked, as for other certificates taken from metadata, and neither are the metadata's validUntil and cacheDuration.
func WriteSOAPFault ¶ added in v0.6.2
func WriteSOAPFault(w http.ResponseWriter, faultString string) error
WriteSOAPFault writes a SOAP 1.1 Fault with the faultcode Client and faultString to w, with HTTP status 500 (SOAP 1.1 §4.4 and §6.2). Use it to refuse a message received with the SOAP binding that is not valid, such as one ValidateSOAPLogoutRequest rejects. faultString is sent to the requester, so it should not say more than that the message was refused.
func WriteSOAPLogoutResponse ¶ added in v0.6.2
func WriteSOAPLogoutResponse(w http.ResponseWriter, resp *LogoutResponse) error
WriteSOAPLogoutResponse writes resp to w in a SOAP 1.1 envelope, as the answer to a LogoutRequest received with the SOAP binding.
Types ¶
type AdditionalMetadataLocation ¶ added in v0.6.2
type AdditionalMetadataLocation struct {
Namespace string `xml:"namespace,attr"`
Value string `xml:",chardata"`
}
AdditionalMetadataLocation represents the SAML element AdditionalMetadataLocation: the location of other metadata for the entity, and the namespace of the root element of the metadata found there.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.3.2.3
type AffiliationDescriptor ¶
type AffiliationDescriptor struct {
AffiliationOwnerID string `xml:"affiliationOwnerID,attr"`
ID string `xml:",attr,omitempty"`
ValidUntil time.Time `xml:"validUntil,attr,omitempty"`
CacheDuration time.Duration `xml:"cacheDuration,attr"`
Signature *etree.Element
Extensions *Extensions `xml:"urn:oasis:names:tc:SAML:2.0:metadata Extensions,omitempty"`
AffiliateMembers []string `xml:"AffiliateMember"`
KeyDescriptors []KeyDescriptor `xml:"KeyDescriptor"`
}
AffiliationDescriptor represents the SAML AffiliationDescriptor object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.5
func (AffiliationDescriptor) MarshalXML ¶ added in v0.6.0
func (m AffiliationDescriptor) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler, writing Signature as XML, cacheDuration as an xsd:duration and validUntil as a RelaxedTime. A zero ValidUntil or CacheDuration is omitted.
func (*AffiliationDescriptor) UnmarshalXML ¶ added in v0.6.0
func (m *AffiliationDescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler, reading Signature as XML, cacheDuration as an xsd:duration and validUntil as a RelaxedTime.
type ArtifactResolve ¶ added in v0.4.6
type ArtifactResolve struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol ArtifactResolve"`
ID string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
Artifact string `xml:"urn:oasis:names:tc:SAML:2.0:protocol Artifact"`
}
ArtifactResolve represents the SAML object of the same name.
func (*ArtifactResolve) Element ¶ added in v0.4.6
func (r *ArtifactResolve) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*ArtifactResolve) MarshalXML ¶ added in v0.4.6
func (r *ArtifactResolve) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*ArtifactResolve) SoapRequest ¶ added in v0.4.6
func (r *ArtifactResolve) SoapRequest() *etree.Element
SoapRequest returns a SOAP Envelope contining the ArtifactResolve request
func (*ArtifactResolve) UnmarshalXML ¶ added in v0.4.6
func (r *ArtifactResolve) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type ArtifactResponse ¶ added in v0.4.6
type ArtifactResponse struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol ArtifactResponse"`
ID string `xml:",attr"`
InResponseTo string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
Status Status `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"`
Response Response `xml:"urn:oasis:names:tc:SAML:2.0:protocol Response"`
}
ArtifactResponse represents the SAML object of the same name.
func (*ArtifactResponse) Element ¶ added in v0.4.6
func (r *ArtifactResponse) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*ArtifactResponse) MarshalXML ¶ added in v0.4.6
func (r *ArtifactResponse) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*ArtifactResponse) UnmarshalXML ¶ added in v0.4.6
func (r *ArtifactResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type Assertion ¶
type Assertion struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion Assertion"`
ID string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
Version string `xml:",attr"`
Issuer Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
Subject *Subject
Conditions *Conditions `xml:"urn:oasis:names:tc:SAML:2.0:assertion Conditions"`
// Advice *Advice
// Statements []Statement
AuthnStatements []AuthnStatement `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthnStatement"`
// AuthzDecisionStatements []AuthzDecisionStatement
AttributeStatements []AttributeStatement `xml:"urn:oasis:names:tc:SAML:2.0:assertion AttributeStatement"`
}
Assertion represents the SAML element Assertion.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.3.3
func (*Assertion) MarshalXML ¶ added in v0.6.0
MarshalXML implements xml.Marshaler
func (*Assertion) UnmarshalXML ¶
UnmarshalXML implements xml.Unmarshaler
type AssertionAttribute ¶
AssertionAttribute represents an attribute of the user extracted from a SAML Assertion.
type AssertionAttributes ¶
type AssertionAttributes []AssertionAttribute
AssertionAttributes is a list of AssertionAttribute
func (AssertionAttributes) Get
deprecated
func (aa AssertionAttributes) Get(name string) *AssertionAttribute
Get returns the assertion attribute whose Name or FriendlyName matches name, or nil if no matching attribute is found.
FriendlyName "MUST NOT be used as a basis for formally identifying SAML attributes" (saml-core §2.7.3.1): an attribute's FriendlyName can equal another attribute's Name.
Deprecated: Get can return an attribute whose FriendlyName equals the Name asked for, in place of the attribute with that Name. Use GetByName.
func (AssertionAttributes) GetByName ¶ added in v0.6.2
func (aa AssertionAttributes) GetByName(name string) *AssertionAttribute
GetByName returns the assertion attribute whose Name is name, or nil if there is none. Unlike Get, it never matches a FriendlyName.
type AssertionMaker ¶
type AssertionMaker interface {
// MakeAssertion constructs an assertion from session and the request and
// assigns it to req.Assertion.
MakeAssertion(req *IdpAuthnRequest, session *Session) error
}
AssertionMaker is an interface used by IdentityProvider to construct the assertion for a request. The default implementation is DefaultAssertionMaker, which is used if not AssertionMaker is specified.
type AssertionReplayCache ¶ added in v0.6.0
type AssertionReplayCache interface {
// Consume atomically records assertionID as used until expiresAt, after
// which the ServiceProvider no longer accepts the assertion; then the
// record may be dropped. It returns ErrAssertionReplayed if
// assertionID is already recorded, and any other error if it cannot
// record it. Any error refuses the assertion.
Consume(assertionID string, expiresAt time.Time) error
}
AssertionReplayCache records the IDs of accepted assertions, so that each is accepted only once. Implementations must be safe for concurrent use, and should be shared by every server that accepts assertions for the same service provider.
ServiceProvider.ReplayCache and IdentityProvider.ReplayCache also record the IDs of accepted LogoutRequests in it, under keys prefixed with "LogoutRequest:", and ServiceProvider.ReplayCache records the artifacts it resolves under keys prefixed with "Artifact:".
type Attribute ¶
type Attribute struct {
FriendlyName string `xml:",attr"`
Name string `xml:",attr"`
NameFormat string `xml:",attr"`
Values []AttributeValue `xml:"urn:oasis:names:tc:SAML:2.0:assertion AttributeValue"`
}
Attribute represents the SAML element Attribute.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.3.1
type AttributeAuthorityDescriptor ¶
type AttributeAuthorityDescriptor struct {
RoleDescriptor
AttributeServices []Endpoint `xml:"AttributeService"`
AssertionIDRequestServices []Endpoint `xml:"AssertionIDRequestService"`
NameIDFormats []NameIDFormat `xml:"NameIDFormat"`
AttributeProfiles []string `xml:"AttributeProfile"`
Attributes []Attribute `xml:"Attribute"`
}
AttributeAuthorityDescriptor represents the SAML AttributeAuthorityDescriptor object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.7
func (AttributeAuthorityDescriptor) MarshalXML ¶ added in v0.6.0
func (m AttributeAuthorityDescriptor) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*AttributeAuthorityDescriptor) UnmarshalXML ¶ added in v0.6.0
func (m *AttributeAuthorityDescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type AttributeConsumingService ¶
type AttributeConsumingService struct {
Index int `xml:"index,attr"`
IsDefault *bool `xml:"isDefault,attr"`
ServiceNames []LocalizedName `xml:"ServiceName"`
ServiceDescriptions []LocalizedName `xml:"ServiceDescription"`
RequestedAttributes []RequestedAttribute `xml:"RequestedAttribute"`
}
AttributeConsumingService represents the SAML AttributeConsumingService object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.4.1
type AttributeQuery ¶ added in v0.6.1
type AttributeQuery struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol AttributeQuery"`
ID string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
Destination string `xml:",attr"`
Consent string `xml:",attr"`
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
// Subject names the principal whose attributes are requested.
Subject *Subject `xml:"urn:oasis:names:tc:SAML:2.0:assertion Subject"`
// Attributes, if any, names the attributes requested. An Attribute
// with Values asks only for those values. If empty, the attribute
// authority returns every attribute the requester may see.
Attributes []Attribute `xml:"urn:oasis:names:tc:SAML:2.0:assertion Attribute"`
}
AttributeQuery represents the SAML object of the same name, a request from a service provider to an attribute authority for attributes of a subject (saml-core §3.3.2.3).
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*AttributeQuery) Element ¶ added in v0.6.1
func (r *AttributeQuery) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*AttributeQuery) MarshalXML ¶ added in v0.6.1
func (r *AttributeQuery) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*AttributeQuery) SoapRequest ¶ added in v0.6.1
func (r *AttributeQuery) SoapRequest() *etree.Element
SoapRequest returns a SOAP 1.1 Envelope containing the AttributeQuery, as the SAML SOAP binding sends it (saml-bindings §3.2).
func (*AttributeQuery) UnmarshalXML ¶ added in v0.6.1
func (r *AttributeQuery) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type AttributeQueryResult ¶ added in v0.6.1
type AttributeQueryResult struct {
// Assertions are the validated assertions of the response, decrypted
// where they were encrypted.
Assertions []Assertion
// Attributes are the attributes of every AttributeStatement of every
// assertion, in document order.
Attributes []Attribute
}
AttributeQueryResult holds what an attribute authority returned for an attribute query, after it has been validated.
It describes the subject named in the query. It is not evidence that the subject is present or authenticated, and must never be used to start a session.
type AttributeStatement ¶
type AttributeStatement struct {
Attributes []Attribute `xml:"urn:oasis:names:tc:SAML:2.0:assertion Attribute"`
}
AttributeStatement represents the SAML element AttributeStatement.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.3
func (*AttributeStatement) Element ¶
func (a *AttributeStatement) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type AttributeValue ¶
type AttributeValue struct {
Type string `xml:"http://www.w3.org/2001/XMLSchema-instance type,attr"`
// Nil reports that the value is a SAML "null" value, carried as
// xsi:nil="true" (or "1") on an empty element (saml-core §2.7.3.1.1).
// It distinguishes a null value from an empty string. When Nil is set,
// Element writes xsi:nil="true" and omits Value and NameID.
Nil bool `xml:"http://www.w3.org/2001/XMLSchema-instance nil,attr,omitempty"`
// Encoding is the x500:Encoding XML attribute (namespace X500AttributeNamespace)
// that the X.500/LDAP attribute profile requires on each value, with the
// value "LDAP" (saml-profiles §8.2.4). It is written only when set.
Encoding string `xml:"urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500 Encoding,attr,omitempty"`
Value string `xml:",chardata"`
NameID *NameID `xml:"urn:oasis:names:tc:SAML:2.0:assertion NameID"`
}
AttributeValue represents the SAML element AttributeValue.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.3.1.1
func (*AttributeValue) Element ¶
func (a *AttributeValue) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type Audience ¶
type Audience struct {
Value string `xml:",chardata"`
}
Audience represents the SAML element Audience.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.5.1.4
type AudienceRestriction ¶
type AudienceRestriction struct {
Audience Audience `xml:"urn:oasis:names:tc:SAML:2.0:assertion Audience"`
AdditionalAudiences []Audience `xml:"-"`
}
AudienceRestriction represents the SAML element AudienceRestriction.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.5.1.4
An AudienceRestriction lists one or more audiences, and is satisfied when the relying party is any one of them. Audience holds the first one, and AdditionalAudiences holds the rest, in document order.
func (*AudienceRestriction) AllAudiences ¶ added in v0.6.0
func (a *AudienceRestriction) AllAudiences() []Audience
AllAudiences returns every audience in the restriction: Audience followed by AdditionalAudiences.
func (*AudienceRestriction) Element ¶
func (a *AudienceRestriction) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*AudienceRestriction) MarshalXML ¶ added in v0.6.0
func (a *AudienceRestriction) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*AudienceRestriction) UnmarshalXML ¶ added in v0.6.0
func (a *AudienceRestriction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type AuthenticatingAuthority ¶ added in v0.6.0
type AuthenticatingAuthority struct {
Value string `xml:",chardata"`
}
AuthenticatingAuthority represents the SAML element AuthenticatingAuthority.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.2.2
func (*AuthenticatingAuthority) Element ¶ added in v0.6.0
func (a *AuthenticatingAuthority) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type AuthnAuthorityDescriptor ¶
type AuthnAuthorityDescriptor struct {
RoleDescriptor
AuthnQueryServices []Endpoint `xml:"AuthnQueryService"`
AssertionIDRequestServices []Endpoint `xml:"AssertionIDRequestService"`
NameIDFormats []NameIDFormat `xml:"NameIDFormat"`
}
AuthnAuthorityDescriptor represents the SAML AuthnAuthorityDescriptor object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.5
func (AuthnAuthorityDescriptor) MarshalXML ¶ added in v0.6.0
func (m AuthnAuthorityDescriptor) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*AuthnAuthorityDescriptor) UnmarshalXML ¶ added in v0.6.0
func (m *AuthnAuthorityDescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type AuthnContext ¶
type AuthnContext struct {
AuthnContextClassRef *AuthnContextClassRef `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthnContextClassRef"`
AuthenticatingAuthorities []AuthenticatingAuthority `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthenticatingAuthority"`
}
AuthnContext represents the SAML element AuthnContext.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.2.2
func (*AuthnContext) Element ¶
func (a *AuthnContext) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type AuthnContextClassRef ¶
type AuthnContextClassRef struct {
Value string `xml:",chardata"`
}
AuthnContextClassRef represents the SAML element AuthnContextClassRef.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.2.2
func (*AuthnContextClassRef) Element ¶
func (a *AuthnContextClassRef) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type AuthnRequest ¶
type AuthnRequest struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol AuthnRequest"`
ID string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
Destination string `xml:",attr"`
Consent string `xml:",attr"`
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
Subject *Subject
NameIDPolicy *NameIDPolicy `xml:"urn:oasis:names:tc:SAML:2.0:protocol NameIDPolicy"`
Conditions *Conditions `xml:"urn:oasis:names:tc:SAML:2.0:assertion Conditions"`
RequestedAuthnContext *RequestedAuthnContext
Scoping *Scoping `xml:"urn:oasis:names:tc:SAML:2.0:protocol Scoping"`
ForceAuthn *bool `xml:",attr"`
IsPassive *bool `xml:",attr"`
AssertionConsumerServiceIndex string `xml:",attr"`
AssertionConsumerServiceURL string `xml:",attr"`
ProtocolBinding string `xml:",attr"`
AttributeConsumingServiceIndex string `xml:",attr"`
ProviderName string `xml:",attr"`
}
AuthnRequest represents the SAML object of the same name, a request from a service provider to authenticate a user.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*AuthnRequest) Element ¶
func (r *AuthnRequest) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*AuthnRequest) MarshalXML ¶
func (r *AuthnRequest) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*AuthnRequest) Post ¶
func (r *AuthnRequest) Post(relayState string) []byte
Post returns an HTML form suitable for using the HTTP-POST binding with the request
func (*AuthnRequest) PostWithNonce ¶ added in v0.6.0
func (r *AuthnRequest) PostWithNonce(relayState, nonce string) []byte
PostWithNonce is like Post, but if nonce is not empty it is set as the nonce attribute of the form's auto-submit <script> element, so that the form can be served under a Content-Security-Policy that allows scripts by nonce.
func (*AuthnRequest) Redirect ¶
func (r *AuthnRequest) Redirect(relayState string, sp *ServiceProvider) (*url.URL, error)
Redirect returns a URL suitable for using the redirect binding with the request. If sp.SignatureMethod is set, the query string is signed as described in saml-bindings-2.0-os section 3.4.4.1. Any enveloped XML signature is omitted, as required by the HTTP-Redirect binding.
func (*AuthnRequest) SimpleSign ¶ added in v0.6.0
func (r *AuthnRequest) SimpleSign(relayState string, sp *ServiceProvider) ([]byte, error)
SimpleSign returns an auto-submitting HTML form that sends the request to its Destination with the HTTP-POST-SimpleSign binding, signed with sp's Key and SignatureMethod, which must be set. An XML signature the request already carries is kept.
func (*AuthnRequest) SimpleSignWithNonce ¶ added in v0.6.0
func (r *AuthnRequest) SimpleSignWithNonce(relayState, nonce string, sp *ServiceProvider) ([]byte, error)
SimpleSignWithNonce is like SimpleSign, but if nonce is not empty it is set as the nonce attribute of the form's auto-submit <script> element, as PostWithNonce does.
func (*AuthnRequest) UnmarshalXML ¶
func (r *AuthnRequest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type AuthnStatement ¶
type AuthnStatement struct {
AuthnInstant time.Time `xml:",attr"`
SessionIndex string `xml:",attr"`
SessionNotOnOrAfter *time.Time `xml:",attr,omitempty"`
SubjectLocality *SubjectLocality `xml:"urn:oasis:names:tc:SAML:2.0:assertion SubjectLocality"`
AuthnContext AuthnContext `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthnContext"`
}
AuthnStatement represents the SAML element AuthnStatement.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.2
func (*AuthnStatement) Element ¶
func (a *AuthnStatement) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*AuthnStatement) MarshalXML ¶
func (a *AuthnStatement) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*AuthnStatement) UnmarshalXML ¶
func (a *AuthnStatement) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type Conditions ¶
type Conditions struct {
NotBefore time.Time `xml:",attr"`
NotOnOrAfter time.Time `xml:",attr"`
AudienceRestrictions []AudienceRestriction `xml:"urn:oasis:names:tc:SAML:2.0:assertion AudienceRestriction"`
OneTimeUse *OneTimeUse `xml:"urn:oasis:names:tc:SAML:2.0:assertion OneTimeUse"`
ProxyRestriction *ProxyRestriction `xml:"urn:oasis:names:tc:SAML:2.0:assertion ProxyRestriction"`
// UnknownConditions holds, in document order, the names of the child
// elements of an unmarshalled Conditions that this package does not
// understand: anything but AudienceRestriction, OneTimeUse and
// ProxyRestriction, including a saml:Condition extended with xsi:type.
// saml-core §2.5.1.1 makes such an assertion Indeterminate, so the
// ServiceProvider rejects it if RejectUnknownConditions is set (or
// ValidateUnknownConditions refuses it); otherwise they are ignored.
// Element and MarshalXML do not reproduce these elements.
UnknownConditions []xml.Name `xml:"-"`
}
Conditions represents the SAML element Conditions.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.5.1
func (*Conditions) Element ¶
func (c *Conditions) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*Conditions) MarshalXML ¶
func (c *Conditions) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*Conditions) UnmarshalXML ¶
func (c *Conditions) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type ContactPerson ¶
type ContactPerson struct {
ContactType string `xml:"contactType,attr"`
Company string `xml:",omitempty"`
GivenName string `xml:",omitempty"`
SurName string `xml:",omitempty"`
EmailAddresses []string `xml:"EmailAddress"`
TelephoneNumbers []string `xml:"TelephoneNumber"`
}
ContactPerson represents the SAML element ContactPerson.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.3.2.2
type DefaultAssertionMaker ¶
type DefaultAssertionMaker struct {
}
DefaultAssertionMaker produces a SAML assertion for the given request and assigns it to req.Assertion.
func (DefaultAssertionMaker) MakeAssertion ¶
func (DefaultAssertionMaker) MakeAssertion(req *IdpAuthnRequest, session *Session) error
MakeAssertion implements AssertionMaker. It produces a SAML assertion from the given request and assigns it to req.Assertion.
type DefaultResponseWriter ¶ added in v0.6.0
type DefaultResponseWriter struct{}
DefaultResponseWriter is the default ResponseWriter. It calls req.WriteResponse, which writes an auto-submitting HTML form (see IdentityProvider.ResponseFormTemplate) that posts the response to the service provider using the HTTP-POST binding, or, when the ACS endpoint uses the HTTP-POST-SimpleSign binding, using that binding (see IdentityProvider.SimpleSignResponseFormTemplate).
func (DefaultResponseWriter) WriteResponse ¶ added in v0.6.0
func (DefaultResponseWriter) WriteResponse(w http.ResponseWriter, req *IdpAuthnRequest) error
WriteResponse implements ResponseWriter.
type DigestMethod ¶ added in v0.6.0
type DigestMethod struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:metadata:algsupport DigestMethod"`
Algorithm string `xml:"Algorithm,attr"`
}
DigestMethod represents the alg:DigestMethod element: an XML Signature digest algorithm the entity supports.
See https://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-algsupport-v1.0-cs01.html §2.3
type Duration ¶
Duration is a time.Duration that uses the xsd:duration format for text marshalling and unmarshalling.
func (Duration) MarshalText ¶
MarshalText implements the encoding.TextMarshaler interface.
func (*Duration) UnmarshalText ¶
UnmarshalText implements the encoding.TextUnmarshaler interface.
type EncryptionMethod ¶
type EncryptionMethod struct {
Algorithm string `xml:"Algorithm,attr"`
// KeySize is the optional xenc:KeySize child, which states the key size
// in bits for algorithms that allow more than one.
KeySize *int `xml:"http://www.w3.org/2001/04/xmlenc# KeySize,omitempty"`
}
EncryptionMethod represents the XMLSEC object of the same name
type Endpoint ¶
type Endpoint struct {
Binding string `xml:"Binding,attr"`
Location string `xml:"Location,attr"`
ResponseLocation string `xml:"ResponseLocation,attr,omitempty"`
}
Endpoint represents the SAML EndpointType object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.2.2
func (*Endpoint) UnmarshalXML ¶ added in v0.4.14
UnmarshalXML implements xml.Unmarshaler
type EntitiesDescriptor ¶
type EntitiesDescriptor struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntitiesDescriptor"`
ID *string `xml:",attr,omitempty"`
ValidUntil *time.Time `xml:"validUntil,attr,omitempty"`
CacheDuration *time.Duration `xml:"cacheDuration,attr,omitempty"`
Name *string `xml:",attr,omitempty"`
Signature *etree.Element
Extensions *Extensions `xml:"urn:oasis:names:tc:SAML:2.0:metadata Extensions,omitempty"`
EntitiesDescriptors []EntitiesDescriptor `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntitiesDescriptor"`
EntityDescriptors []EntityDescriptor `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntityDescriptor"`
}
EntitiesDescriptor represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.3.1
func (EntitiesDescriptor) MarshalXML ¶ added in v0.5.0
func (m EntitiesDescriptor) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*EntitiesDescriptor) UnmarshalXML ¶ added in v0.5.0
func (m *EntitiesDescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type EntityDescriptor ¶
type EntityDescriptor struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntityDescriptor"`
EntityID string `xml:"entityID,attr"`
ID string `xml:",attr,omitempty"`
ValidUntil time.Time `xml:"validUntil,attr,omitempty"`
CacheDuration time.Duration `xml:"cacheDuration,attr,omitempty"`
Signature *etree.Element
Extensions *Extensions `xml:"urn:oasis:names:tc:SAML:2.0:metadata Extensions,omitempty"`
RoleDescriptors []RoleDescriptor `xml:"RoleDescriptor"`
IDPSSODescriptors []IDPSSODescriptor `xml:"IDPSSODescriptor"`
SPSSODescriptors []SPSSODescriptor `xml:"SPSSODescriptor"`
AuthnAuthorityDescriptors []AuthnAuthorityDescriptor `xml:"AuthnAuthorityDescriptor"`
AttributeAuthorityDescriptors []AttributeAuthorityDescriptor `xml:"AttributeAuthorityDescriptor"`
PDPDescriptors []PDPDescriptor `xml:"PDPDescriptor"`
AffiliationDescriptor *AffiliationDescriptor
Organization *Organization
// ContactPerson is the first contact person of the entity.
//
// Deprecated: an entity may have any number of contact persons
// (saml-metadata-2.0-os §2.3.2). Use ContactPersons. When metadata is
// parsed, ContactPerson is set to point to the first element of
// ContactPersons. When metadata is written, a non-nil ContactPerson
// replaces the first element of ContactPersons, or is the only contact
// person if ContactPersons is empty.
ContactPerson *ContactPerson `xml:"-"`
// ContactPersons are the md:ContactPerson elements of the entity.
ContactPersons []ContactPerson `xml:"ContactPerson"`
// AdditionalMetadataLocations are the locations of the
// md:AdditionalMetadataLocation elements.
//
// Deprecated: it loses the required namespace attribute
// (saml-metadata-2.0-os §2.3.2.3). Use AdditionalMetadataLocationElements.
// When metadata is parsed, it is set to the locations of
// AdditionalMetadataLocationElements. When metadata is written, it is
// used only if AdditionalMetadataLocationElements is empty, and the
// elements it produces have an empty namespace attribute.
AdditionalMetadataLocations []string `xml:"-"`
// AdditionalMetadataLocationElements are the md:AdditionalMetadataLocation
// elements of the entity.
AdditionalMetadataLocationElements []AdditionalMetadataLocation `xml:"AdditionalMetadataLocation"`
}
EntityDescriptor represents the SAML EntityDescriptor object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.3.2
func (EntityDescriptor) MarshalXML ¶
func (m EntityDescriptor) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*EntityDescriptor) UnmarshalXML ¶
func (m *EntityDescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type ErrBadStatus ¶ added in v0.3.1
type ErrBadStatus struct {
Status string
}
ErrBadStatus is returned when the assertion provided is valid but the status code is not "urn:oasis:names:tc:SAML:2.0:status:Success".
func (ErrBadStatus) Error ¶ added in v0.3.1
func (e ErrBadStatus) Error() string
type ExtensionElement ¶ added in v0.6.0
type ExtensionElement struct {
XMLName xml.Name
Attrs []xml.Attr `xml:",any,attr"`
CharData string `xml:",chardata"`
Children []ExtensionElement `xml:",any"`
}
ExtensionElement is a generic XML element, used for extension elements that this package does not model. Names are kept with their namespace URIs rather than their prefixes, so the element can be written out again with its namespaces intact. Character data is kept, but its position relative to child elements (mixed content) is not.
func (*ExtensionElement) UnmarshalXML ¶ added in v0.6.0
func (m *ExtensionElement) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type Extensions ¶ added in v0.6.0
type Extensions struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:metadata Extensions"`
// SigningMethods and DigestMethods are the alg:SigningMethod and
// alg:DigestMethod elements of the Metadata Profile for Algorithm Support.
SigningMethods []SigningMethod `xml:"urn:oasis:names:tc:SAML:metadata:algsupport SigningMethod"`
DigestMethods []DigestMethod `xml:"urn:oasis:names:tc:SAML:metadata:algsupport DigestMethod"`
// ShibbolethScopes are the shibmd:Scope elements an identity provider
// publishes in its IDPSSODescriptor or AttributeAuthorityDescriptor.
ShibbolethScopes []ShibbolethScope `xml:"urn:mace:shibboleth:metadata:1.0 Scope"`
// Other holds the extension elements that have no field of their own.
Other []ExtensionElement `xml:",any"`
}
Extensions represents the SAML metadata element md:Extensions, which holds extension elements from namespaces other than the SAML metadata namespace.
Elements this package knows are decoded into their own fields. Any other element is kept in Other, so that it is not lost when metadata is parsed and then written out again. Elements are written in field order, so the order of elements in Other relative to the known elements is not preserved.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.3.1
type IDPEntry ¶ added in v0.6.0
type IDPEntry struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol IDPEntry"`
ProviderID string `xml:",attr"`
Name string `xml:",attr,omitempty"`
Loc string `xml:",attr,omitempty"`
}
IDPEntry represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf § 3.4.1.3.1
type IDPList ¶ added in v0.6.0
type IDPList struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol IDPList"`
IDPEntries []IDPEntry `xml:"urn:oasis:names:tc:SAML:2.0:protocol IDPEntry"`
GetComplete string `xml:"urn:oasis:names:tc:SAML:2.0:protocol GetComplete,omitempty"`
}
IDPList represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf § 3.4.1.3
type IDPSSODescriptor ¶
type IDPSSODescriptor struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:metadata IDPSSODescriptor"`
SSODescriptor
WantAuthnRequestsSigned *bool `xml:",attr"`
SingleSignOnServices []Endpoint `xml:"SingleSignOnService"`
// ArtifactResolutionServices are the md:ArtifactResolutionService
// endpoints of the identity provider, without their index and isDefault
// attributes.
//
// Deprecated: ArtifactResolutionService is an indexed endpoint
// (saml-metadata-2.0-os §2.4.2). Use
// SSODescriptor.ArtifactResolutionServices, which this field hides. When
// metadata is parsed, this field is set to the endpoints of
// SSODescriptor.ArtifactResolutionServices. When metadata is written, it
// is used only if SSODescriptor.ArtifactResolutionServices is empty, and
// its endpoints are given the indexes 1, 2, ...
ArtifactResolutionServices []Endpoint `xml:"-"`
NameIDMappingServices []Endpoint `xml:"NameIDMappingService"`
AssertionIDRequestServices []Endpoint `xml:"AssertionIDRequestService"`
AttributeProfiles []string `xml:"AttributeProfile"`
Attributes []Attribute `xml:"Attribute"`
}
IDPSSODescriptor represents the SAML IDPSSODescriptorType object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.3
func (IDPSSODescriptor) MarshalXML ¶ added in v0.6.0
func (m IDPSSODescriptor) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*IDPSSODescriptor) UnmarshalXML ¶ added in v0.6.0
func (m *IDPSSODescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type IdentityProvider ¶
type IdentityProvider struct {
Key crypto.PrivateKey
Signer crypto.Signer
Logger logger.Interface
Certificate *x509.Certificate
Intermediates []*x509.Certificate
MetadataURL url.URL
SSOURL url.URL
LoginURL url.URL
LogoutURL url.URL
ServiceProviderProvider ServiceProviderProvider
SessionProvider SessionProvider
AssertionMaker AssertionMaker
SignatureMethod string
ValidDuration *time.Duration
ResponseFormTemplate *template.Template
// SimpleSignResponseFormTemplate, if set, replaces the default
// auto-submitting HTML form used to send responses to ACS endpoints with
// the HTTP-POST-SimpleSign binding. It is executed with an
// IdpAuthnRequestSimpleSignForm and must post its SAMLResponse, SigAlg
// and Signature fields, and RelayState when it is not empty (an empty
// RelayState field would be included in the signed content).
SimpleSignResponseFormTemplate *template.Template
// AdvertiseSimpleSignSSO, if true, adds an HTTP-POST-SimpleSign
// SingleSignOnService endpoint at SSOURL to the metadata. ServeSSO
// accepts SimpleSign authentication requests whether or not this is set.
AdvertiseSimpleSignSSO bool
// ResponseWriter, if set, writes the HTTP response carrying the SAML
// response in ServeSSO and ServeIDPInitiated. If nil,
// DefaultResponseWriter is used, which posts the response with the
// HTML form from ResponseFormTemplate.
ResponseWriter ResponseWriter
// OnError, if non-nil, is called when ServeSSO, ServeIDPInitiated or
// ServeMetadata cannot complete a request, in place of DefaultOnError,
// which logs err to Logger and responds with status. status is the HTTP
// status the IdentityProvider would respond with: StatusBadRequest for a
// request that cannot be parsed or is invalid, StatusNotFound for an
// IdP-initiated request for an unknown service provider, and
// StatusInternalServerError otherwise. err can be matched with errors.Is
// against the error values of this package, such as
// ErrUnknownServiceProvider or ErrInvalidCertificate.
//
// OnError must write the response. When writing the SAML response or
// the metadata failed part way, some of it may already have been
// written to w.
OnError func(w http.ResponseWriter, r *http.Request, status int, err error)
// ExtraCertificates are additional certificates published in the IdP
// metadata as signing keys, after Certificate. They are never used to
// sign anything. Use them to announce a new signing certificate before
// switching Certificate (and Key or Signer) to it, so that service
// providers that refresh their copy of the metadata already trust the
// new key when the rollover happens, or to keep publishing the old
// certificate for a while afterwards.
ExtraCertificates []*x509.Certificate
// NameIDFormats are the NameID formats advertised in the IdP metadata.
// When empty it defaults to the transient format for backwards compatibility.
NameIDFormats []NameIDFormat
// MetadataScopes are published in the IdP metadata as Shibboleth
// shibmd:Scope extension elements, which tell service providers the
// scopes the IdP is authoritative for, i.e. the parts after the "@" in
// scoped attribute values such as eduPersonScopedAffiliation. When
// empty, no scopes are published.
MetadataScopes []ShibbolethScope
// AssertionEncrypter, if set, encrypts assertions for service providers
// that publish an encryption certificate. It is passed the SP's
// *x509.Certificate as the key. Use it to select the key transport,
// digest and block cipher, for example:
//
// enc := xmlenc.OAEP_SHA256() // XML Encryption 1.1 RSA-OAEP
// enc.BlockCipher = xmlenc.AES256GCM
// idp.AssertionEncrypter = enc
//
// The service provider must support the algorithms chosen; those it
// supports are usually listed in its metadata.
//
// When nil, assertions are encrypted with RSA-OAEP-MGF1P using a SHA-1
// digest and AES-128-CBC, for compatibility with existing service
// providers.
AssertionEncrypter xmlenc.Encrypter
// SignMetadata, if true, causes ServeMetadata to publish metadata that
// carries an enveloped XML signature made with the IdP's key. See
// SignedMetadata.
SignMetadata bool
// RejectSHA1Signatures, if true, refuses messages from service
// providers that are signed with a SHA-1 based algorithm: an XML
// signature whose SignatureMethod or any DigestMethod is SHA-1 based
// (rsa-sha1, ecdsa-sha1, dsa-sha1, hmac-sha1 or sha1), and an
// HTTP-Redirect or HTTP-POST-SimpleSign signature whose SigAlg is. It
// applies to the signatures the IdP verifies: those of LogoutRequests
// and of LogoutResponses to the IdP's own LogoutRequests (ServeSLO),
// and of AuthnRequests sent with the HTTP-POST-SimpleSign binding. The error matches ErrUnsupported. If false, SHA-1 is
// accepted.
RejectSHA1Signatures bool
// LogoutBindings are the bindings advertised in the IdP metadata for the
// SingleLogoutService at LogoutURL. When empty, only HTTP-Redirect is
// advertised, as before. ServeSLO accepts LogoutRequests with both the
// HTTP-Redirect and the HTTP-POST binding, so set it to
// []string{HTTPRedirectBinding, HTTPPostBinding} when LogoutURL is served
// by ServeSLO.
//
// Include SOAPBinding to advertise a SOAP SingleLogoutService as well,
// and have ServeSLO accept LogoutRequests sent server to server with the
// SOAP binding. ServeSLO accepts them only then. Do so only if the
// SessionProvider's SessionInvalidator can end sessions without the
// browser's cookies (see SessionInvalidator), since such a request
// carries none.
LogoutBindings []string
// EncryptionCertificate, if set, is published in the IdP metadata as the
// IdP's encryption key in place of Certificate. Service providers encrypt
// to it, for example the EncryptedID of a LogoutRequest. Its private key
// must be Key or one of DecryptionKeys. Set it when Key cannot decrypt,
// such as when the IdP signs with a Signer held in an HSM or KMS, or to
// encrypt with a key other than the signing key.
EncryptionCertificate *x509.Certificate
// DecryptionKeys are further private keys that decrypt what service
// providers encrypt to the IdP, such as the EncryptedID of a
// LogoutRequest. They are tried in order after Key, if Key is an
// *rsa.PrivateKey. Set them while rotating the IdP encryption key, so
// that messages encrypted to the previous certificate by service
// providers that have not yet refreshed the IdP metadata can still be
// decrypted, or when Key cannot decrypt (see EncryptionCertificate).
DecryptionKeys []*rsa.PrivateKey
// LimitRelayStateLength, if true, makes NewIdpInitiatedRequest refuse a
// RelayState longer than MaxRelayStateLength (80 bytes), as the SAML
// bindings require of senders (saml-bindings-2.0-os §3.5.3), with an
// error matching ErrRelayStateTooLong; ServeIDPInitiated then answers
// HTTP 400. It is off by default. A RelayState the IdP echoes in a
// Response or LogoutResponse is never checked.
LimitRelayStateLength bool
// AcceptLogoutRequestBaseID, if true, lets ServeSLO and
// IdpLogoutRequest.Validate accept a LogoutRequest whose principal is a
// saml:BaseID (in the clear, or in an EncryptedID) rather than a NameID.
// Request.BaseID then holds the element and Request.NameID is nil, so
// MatchesSession matches no session; the SessionInvalidator must
// interpret the BaseID itself. If false, such a request is refused with
// an error matching ErrUnsupported.
AcceptLogoutRequestBaseID bool
// EncryptLogoutNameID, if true, makes the LogoutRequests the IdP sends
// to service providers (see StartLogout and SessionParticipantTracker)
// identify the principal with a saml:EncryptedID instead of a NameID,
// encrypted to the service provider's encryption certificate. As with
// assertions, a service provider whose metadata publishes no encryption
// certificate cannot decrypt, so it is sent the NameID in the clear.
EncryptLogoutNameID bool
// LogoutNameIDEncrypter, if set, encrypts the NameID of the
// LogoutRequests the IdP sends (see EncryptLogoutNameID). It is passed
// the service provider's *x509.Certificate as the key. When nil,
// RSA-OAEP-MGF1P with a SHA-1 digest is used with the strongest block
// cipher that the service provider's metadata lists in the
// EncryptionMethods of its encryption key: AES-GCM (256, 128 then 192
// bit keys) before AES-CBC, or AES-256-GCM if it lists none of them.
LogoutNameIDEncrypter xmlenc.Encrypter
// ReplayCache, if set, records the ID of each LogoutRequest that
// IdpLogoutRequest.Validate (and so ServeSLO) accepts, and refuses a
// LogoutRequest whose ID it has already recorded, so that a captured
// request cannot be replayed while it is still current. IDs are recorded
// under the key "LogoutRequest:" followed by the ID, until the last
// moment the request would be accepted. If nil, LogoutRequests are not
// checked for replay.
ReplayCache AssertionReplayCache
// HTTPClient is the client the IdP sends back-channel messages with:
// the LogoutRequests it sends over the SOAP binding to the session
// participants whose metadata lists a SOAP SingleLogoutService (see
// StartLogout and ServeSLO). If nil, a client that gives up after 10
// seconds and does not follow redirects is used.
HTTPClient *http.Client
// AllowInsecureSOAPEndpoints lets the IdP send SOAP messages to http
// endpoints. By default a SOAP SingleLogoutService whose Location is not
// https is ignored, as if the service provider metadata did not list it
// (see ErrInsecureSOAPEndpoint), so that a LogoutRequest carrying the
// user's NameID never crosses the network in the clear; the participant
// is then logged out through the browser if it can be. Set it only for
// tests and development setups.
AllowInsecureSOAPEndpoints bool
// ReportPartialLogoutWithoutTracker, if true, makes ServeSLO answer a
// LogoutRequest with the second-level status StatusPartialLogout under
// StatusSuccess when the SessionProvider does not implement
// SessionParticipantTracker. The IdP then cannot know which other
// service providers the session was used for, nor contact them, and
// saml-core-2.0-os §3.7.3.2 requires a session authority that cannot
// contact all the session participants to say so with PartialLogout. If
// false, such a logout is answered with a plain StatusSuccess, as
// before. It has no effect when the SessionProvider tracks session
// participants: the second-level status then reports whether they were
// all logged out.
ReportPartialLogoutWithoutTracker bool
// SendErrorResponses makes ServeSSO answer an AuthnRequest that is
// expired (ErrExpired) or not SAML 2.0 with a SAML error <Response> sent
// to the service provider's assertion consumer service, as saml-core
// §3.4.1.4 and saml-bindings §3.4.6 and §3.5.6 ask, instead of an HTTP
// 400 error. The Response is only sent when the request otherwise
// identifies a known service provider and an assertion consumer service
// in its metadata, so it never goes to a location the request alone
// names; other invalid requests still get HTTP 400. An expired request
// gets a Requester status, a request with another version a
// VersionMismatch status (saml-core §4.1.3.2).
//
// Whether or not it is set, an AssertionMaker that returns a
// *StatusError gets an error Response, in ServeSSO and
// ServeIDPInitiated.
SendErrorResponses bool
// EnforceNameIDPolicy, if true, makes DefaultAssertionMaker enforce the
// NameIDPolicy of the AuthnRequest, as saml-core §3.4.1.1 requires.
// A request whose NameIDPolicy Format is neither unspecified nor
// encrypted, and is not the format the IdP issues (Session.NameIDFormat,
// or transient if that is empty), is answered with an error Response
// with the status Requester and InvalidNameIDPolicy, and no assertion.
// A NameIDPolicy SPNameQualifier is put in the NameID instead of the
// service provider's entity ID (it is left out of an entity format
// NameID). Whether the service provider may ask for that qualifier, and
// what identifier to give under it, is up to the SessionProvider, which
// can read the policy from IdpAuthnRequest.Request.
//
// If false, the NameIDPolicy is ignored, as before.
EnforceNameIDPolicy bool
// StrictACSBinding makes the IdP match the ProtocolBinding of an
// AuthnRequest, as well as its AssertionConsumerServiceURL, against the
// service provider's assertion consumer services (saml-core §3.4.1:
// ProtocolBinding "identifies a SAML protocol binding to be used when
// returning the <Response> message"). If no endpoint at that URL has
// that binding, or the matching endpoint has a binding the IdP cannot
// send a Response with, ServeSSO answers with a Requester error Response
// with the second-level status UnsupportedBinding, sent to the service
// provider's default assertion consumer service from its metadata (or
// with HTTP 400 if it has none the IdP can send to).
//
// When false, an endpoint is matched on its Location as before, so a
// request that names, say, HTTP-Artifact or HTTP-Redirect at the URL of
// an HTTP-POST endpoint still gets an HTTP-POST Response. Set it only if
// the service providers send a correct ProtocolBinding.
//
// Whether or not it is set, when ResponseWriter is not set (or is
// DefaultResponseWriter) and the endpoint a request names (by URL or
// index) has a binding other than HTTP-POST and HTTP-POST-SimpleSign,
// ServeSSO answers with that UnsupportedBinding error Response before
// asking the SessionProvider for a session, instead of failing with
// HTTP 500 once the user has logged in. A custom ResponseWriter is
// given such an endpoint, since it may support other bindings.
StrictACSBinding bool
// EnforceRequestedAuthnContext, if true, makes DefaultAssertionMaker
// check the AuthnContextClassRef it asserts (Session.AuthnContextClassRef,
// or PasswordProtectedTransport when that is empty) against the
// RequestedAuthnContext of the AuthnRequest, with the "exact" (or
// omitted), "minimum", "maximum" and "better" Comparisons of saml-core
// §3.3.2.2.1 as amended by errata E65. When it does not satisfy any of
// the requested classes, MakeAssertion returns a *StatusError, and
// ServeSSO answers with a Response with the status Responder and the
// second-level status NoAuthnContext and no assertion. An unknown
// Comparison is answered with Requester. Only AuthnContextClassRefs are
// evaluated; a request that names none is always satisfied.
//
// If false, the default, the RequestedAuthnContext is ignored and the
// assertion is made whatever the service provider asked for, as before.
EnforceRequestedAuthnContext bool
// AuthnContextClassStrengths ranks authentication context classes for
// the "minimum", "maximum" and "better" Comparisons, when
// EnforceRequestedAuthnContext is set: a higher number is stronger, and
// classes with the same number are equally strong. A class that is not
// in the map is not ranked, and only satisfies a request that names it.
// If nil, DefaultAuthnContextClassStrengths is used.
AuthnContextClassStrengths map[string]int
}
IdentityProvider implements the SAML Identity Provider role (IDP).
An identity provider receives SAML assertion requests and responds with SAML Assertions.
You must provide a keypair that is used to sign assertions.
You must provide an implementation of ServiceProviderProvider which returns
You must provide an implementation of the SessionProvider which handles the actual authentication (i.e. prompting for a username and password).
func (*IdentityProvider) DefaultOnError ¶ added in v0.6.0
func (idp *IdentityProvider) DefaultOnError(w http.ResponseWriter, _ *http.Request, status int, err error)
DefaultOnError is how ServeSSO, ServeIDPInitiated and ServeMetadata report an error when OnError is nil: it logs err to Logger and responds with status. An OnError can call it for the errors it does not handle itself.
func (*IdentityProvider) Handler ¶
func (idp *IdentityProvider) Handler() http.Handler
Handler returns an http.Handler that serves the metadata and SSO URLs, and the single logout URL (see ServeSLO) if LogoutURL is set and its path differs from the others.
func (*IdentityProvider) Metadata ¶
func (idp *IdentityProvider) Metadata() *EntityDescriptor
Metadata returns the metadata structure for this identity provider.
func (*IdentityProvider) NewIdpInitiatedRequest ¶ added in v0.6.0
func (idp *IdentityProvider) NewIdpInitiatedRequest(r *http.Request, serviceProviderID string, relayState string) (*IdpAuthnRequest, error)
NewIdpInitiatedRequest returns the IdpAuthnRequest for an IdP-initiated login to the service provider serviceProviderID, with its metadata and its default assertion consumer service resolved: the default endpoint, by the saml-metadata §2.2.3 rule, among those with the HTTP-POST or HTTP-POST-SimpleSign binding. It is the part of ServeIDPInitiated that runs before the SessionProvider is asked for a session.
It returns an error matching ErrUnknownServiceProvider (and os.ErrNotExist) if the ServiceProviderProvider does not know serviceProviderID, ErrUnknownAssertionConsumerService if the service provider has no HTTP-POST or HTTP-POST-SimpleSign assertion consumer service, and otherwise the ServiceProviderProvider's error, wrapped.
func (*IdentityProvider) SendErrorResponse ¶ added in v0.6.2
func (idp *IdentityProvider) SendErrorResponse(w http.ResponseWriter, req *IdpAuthnRequest, statusErr *StatusError) error
SendErrorResponse makes the error Response statusErr describes for req with req.MakeErrorResponse and writes it with the ResponseWriter, as ServeSSO does when the AssertionMaker returns a *StatusError. A SessionProvider can call it to answer a request it will not prompt the user for, such as an IsPassive one, and then return nil from GetSession.
req must have been validated: the Response goes to req.ACSEndpoint, which must come from the service provider's metadata. If it returns an error, nothing has been written to w unless the ResponseWriter failed part way.
func (*IdentityProvider) ServeIDPInitiated ¶
func (idp *IdentityProvider) ServeIDPInitiated(w http.ResponseWriter, r *http.Request, serviceProviderID string, relayState string)
ServeIDPInitiated handes an IDP-initiated authorization request. Requests of this type require us to know a registered service provider and (optionally) the RelayState that will be passed to the application.
It responds with StatusNotFound if the service provider is unknown, and with StatusInternalServerError if the service provider cannot be looked up or has no usable assertion consumer service, or the assertion cannot be created or returned. If the AssertionMaker returns a *StatusError, an unsolicited SAML Response with that status and no assertion is sent to the assertion consumer service instead. Set OnError to handle these failures differently, or build a handler from NewIdpInitiatedRequest.
func (*IdentityProvider) ServeMetadata ¶
func (idp *IdentityProvider) ServeMetadata(w http.ResponseWriter, r *http.Request)
ServeMetadata is an http.HandlerFunc that serves the IDP metadata. If SignMetadata is set, the metadata is signed.
If the metadata cannot be signed, serialized or written, a StatusInternalServerError response is sent. Set OnError to handle these failures differently.
func (*IdentityProvider) ServeSLO ¶ added in v0.6.1
func (idp *IdentityProvider) ServeSLO(w http.ResponseWriter, r *http.Request)
ServeSLO handles SAML LogoutRequests sent by service providers (SP-initiated single logout, saml-profiles-2.0-os §4.4) with the HTTP-Redirect or the HTTP-POST binding. Serve it at LogoutURL. It also handles the LogoutResponses of service providers to the LogoutRequests the IdP sends while it propagates a logout (see StartLogout and SessionParticipantTracker).
The request must be signed by the service provider and is validated as described in IdpLogoutRequest.Validate. An invalid request, or one already recorded in ReplayCache, is answered with HTTP 400 and no LogoutResponse.
For a valid request, the IdP session is terminated by calling InvalidateSession if the SessionProvider implements SessionInvalidator. Then a signed LogoutResponse is sent to the service provider's SingleLogoutService endpoint, preferring the binding the request came with. Its status is StatusSuccess if the session was terminated, and StatusResponder if InvalidateSession failed or the SessionProvider does not implement SessionInvalidator, as the IdP session was then not ended.
If the SessionProvider implements SessionParticipantTracker and the session was terminated, the logout is first propagated to the other service providers the ended sessions were used for (saml-profiles-2.0-os §4.4.4.2), as StartLogout does: over the SOAP binding to those whose metadata lists a SOAP SingleLogoutService, and otherwise by sending the browser to each with a LogoutRequest, one at a time. Only then is the LogoutResponse sent to the service provider that asked. If some of them could not be logged out, its status is StatusSuccess with the second-level status StatusPartialLogout (saml-core-2.0-os §3.7.3.2). Without a SessionParticipantTracker, the logout is not propagated, and the status is a plain StatusSuccess unless ReportPartialLogoutWithoutTracker is set, in which case it carries StatusPartialLogout, as the other participants could not be contacted.
If LogoutBindings includes SOAPBinding, ServeSLO also accepts a LogoutRequest sent server to server with the SOAP binding (saml-bindings-2.0-os §3.2): a POST whose Content-Type is text/xml and whose body, of at most MaxSOAPLogoutMessageSize bytes, is a SOAP 1.1 envelope holding the LogoutRequest. No browser takes part, so:
- the request must carry an enveloped XML signature by the service provider (the IdP does not authenticate it by TLS client certificate); its Destination may be absent;
- the SessionInvalidator is called with no session cookie of the user, and must find the sessions with req.MatchesSession (see SessionInvalidator);
- the logout is propagated only to the participants whose metadata lists a SOAP SingleLogoutService. The others cannot be reached without a browser and count as not logged out (StatusPartialLogout);
- the signed LogoutResponse is the HTTP response, in a SOAP envelope. A request that is authenticated but invalid (for example expired, replayed, or with an EncryptedID that cannot be decrypted) is answered with StatusRequester. A request that cannot be read or authenticated is answered with a SOAP Client fault and HTTP 500 (SOAP 1.1 §6.2), with no LogoutResponse.
func (*IdentityProvider) ServeSSO ¶
func (idp *IdentityProvider) ServeSSO(w http.ResponseWriter, r *http.Request)
ServeSSO handles SAML auth requests.
When it gets a request for a user that does not have a valid session, then it prompts the user via XXX.
If the session already exists, then it produces a SAML assertion and returns an HTTP response according to the specified binding. The only supported binding right now is the HTTP-POST binding which returns an HTML form in the appropriate format with Javascript to automatically submit that form the to service provider's Assertion Customer Service endpoint.
If the SAML request is invalid or cannot be verified a simple StatusBadRequest response is sent, unless SendErrorResponses is set and the request can be answered with a SAML error Response (see SendErrorResponses).
A request that names an assertion consumer service whose binding the default ResponseWriter cannot send a Response with (anything but HTTP-POST and HTTP-POST-SimpleSign), or, with StrictACSBinding, whose URL has no endpoint with the requested ProtocolBinding, gets an error Response with the status Requester and UnsupportedBinding, sent to the service provider's default assertion consumer service from its metadata, before the SessionProvider is asked for a session.
If the AssertionMaker returns a *StatusError, a SAML Response with that status and no assertion is sent to the assertion consumer service instead (see SendErrorResponse). So is one when the request has a <saml:Subject> that the assertion's Subject does not strongly match, as saml-core §3.4.1.4 requires (see CheckRequestSubject). If the assertion cannot otherwise be created or returned, a StatusInternalServerError response is sent.
Set OnError to handle these failures differently.
func (*IdentityProvider) SignedMetadata ¶ added in v0.6.0
func (idp *IdentityProvider) SignedMetadata() (*etree.Element, error)
SignedMetadata returns the IdP metadata as an XML element carrying an enveloped signature made with the IdP's key (saml-metadata-2.0-os §3).
The signature references the EntityDescriptor by its ID attribute; one is generated if the metadata does not have one. The returned element must be serialized as-is: re-indenting it changes the signed content.
func (*IdentityProvider) StartLogout ¶ added in v0.6.2
func (idp *IdentityProvider) StartLogout(w http.ResponseWriter, r *http.Request, session *Session, returnURL string)
StartLogout starts IdP-initiated single logout (saml-profiles-2.0-os §4.4.3.3) of session. Each service provider the session was used for (see SessionParticipantTracker) is sent a signed LogoutRequest, one at a time.
A service provider whose metadata lists a SingleLogoutService with the SOAP binding is sent it server to server, over the SOAP binding, with HTTPClient; the browser does not leave the IdP. Its LogoutResponse must be signed by the service provider and is checked as one that comes back through the browser is, except that it may omit its Destination. If that fails (the service provider cannot be reached, its response is invalid or its status is not Success), the service provider is tried again through the browser, as below, if its metadata lists a front-channel endpoint: the browser may reach a service provider the IdP cannot, and logging the user's browser out there is better than not at all.
Otherwise the browser is sent to the service provider with the LogoutRequest, using the HTTP-Redirect binding if the service provider's metadata lists a SingleLogoutService with it and HTTP-POST otherwise. It answers with a LogoutResponse to LogoutURL, which ServeSLO handles. The progress of the logout is kept in a cookie signed with the IdP's key and scoped to LogoutURL.
Once every service provider has answered, or could not be contacted, the browser is redirected to returnURL, or, if returnURL is empty, shown a page that says the user is logged out, and which service providers could not log the user out. returnURL is only ever set by the caller, never taken from the request.
StartLogout does not end the IdP session itself. As it writes the response, set any header that ends it (such as an expired session cookie) before calling it, and delete the session afterwards: the SessionParticipantTracker must still know the session when StartLogout asks it for the participants. session.ID identifies the session.
If the SessionProvider does not implement SessionParticipantTracker, or the session has no participants, the logout finishes at once.
type IdpAuthnRequest ¶
type IdpAuthnRequest struct {
IDP *IdentityProvider
HTTPRequest *http.Request
RelayState string
RequestBuffer []byte
Request AuthnRequest
ServiceProviderMetadata *EntityDescriptor
SPSSODescriptor *SPSSODescriptor
ACSEndpoint *IndexedEndpoint
Assertion *Assertion
AssertionEl *etree.Element
ResponseEl *etree.Element
Now time.Time
// contains filtered or unexported fields
}
IdpAuthnRequest is used by IdentityProvider to handle a single authentication request.
func NewIdpAuthnRequest ¶
func NewIdpAuthnRequest(idp *IdentityProvider, r *http.Request) (*IdpAuthnRequest, error)
NewIdpAuthnRequest returns a new IdpAuthnRequest for the given HTTP request to the authorization service.
A GET request carries the request with the HTTP-Redirect binding and a POST request with the HTTP-POST binding, or with the HTTP-POST-SimpleSign binding when the form has a SigAlg or Signature field. The SimpleSign form is checked for duplicated or missing fields here; its signature is checked by Validate, once the service provider is known.
func (*IdpAuthnRequest) CheckRequestSubject ¶ added in v0.6.2
func (req *IdpAuthnRequest) CheckRequestSubject() error
CheckRequestSubject checks that the assertion the AssertionMaker put in req.Assertion is about the principal the AuthnRequest names in its <saml:Subject>, if it names one. saml-core §3.4.1.4 requires the resulting assertion's Subject to strongly match the request's (saml-core §3.3.4), and errata E75 and saml-profiles §4.1.4.1 require an identity provider that cannot or will not produce such an assertion to answer with an error <Status> and no assertion.
It returns nil when the request has no Subject or there is no assertion yet, and otherwise a *StatusError, with the second-level status StatusUnknownPrincipal unless noted, when:
- the request Subject has no identifier, only SubjectConfirmation elements: StatusRequester, since saml-core §3.3.4 requires an identifier to match and the request is malformed for this profile;
- the request Subject identifies the principal with a BaseID or an EncryptedID, which this package cannot compare, or the assertion's Subject has no NameID to compare with: StatusResponder, since the limitation is the identity provider's;
- the NameID values differ, or the request gives a Format (other than unspecified), NameQualifier, SPNameQualifier or SPProvidedID that the assertion's NameID does not have: StatusRequester, since the service provider asked about a principal other than the one the identity provider has authenticated, and the same request cannot succeed in this session;
- the request Subject has SubjectConfirmation elements and the assertion has none with any of their Methods: StatusResponder with the second-level status StatusRequestUnsupported, since the identity provider does not issue that kind of confirmation.
ServeSSO calls it after the AssertionMaker and sends the error Response itself. A handler that calls the AssertionMaker directly should call it too, and send any error with IdentityProvider.SendErrorResponse.
func (*IdpAuthnRequest) MakeAssertionEl ¶
func (req *IdpAuthnRequest) MakeAssertionEl() error
MakeAssertionEl sets `AssertionEl` to a signed, possibly encrypted, version of `Assertion`.
func (*IdpAuthnRequest) MakeErrorResponse ¶ added in v0.6.2
func (req *IdpAuthnRequest) MakeErrorResponse(topLevel, secondLevel, message string) error
MakeErrorResponse sets ResponseEl to a signed SAML <Response> to the request with an error <Status> and no assertion: topLevel is the top-level status code, which must be StatusRequester, StatusResponder or StatusVersionMismatch; secondLevel, if not empty, the second-level status code nested in it; and message, if not empty, the <StatusMessage>. The Response has the same Issuer, InResponseTo and Destination as the one MakeResponse makes, so the request must have an ACSEndpoint, as it does once Validate has succeeded or NewIdpInitiatedRequest has returned it.
Assertion and AssertionEl are set to nil, so that a ResponseWriter sees there is no assertion. Write the Response with WriteResponse or a ResponseWriter, as for a successful Response, or use IdentityProvider.SendErrorResponse to do both.
func (*IdpAuthnRequest) MakeResponse ¶
func (req *IdpAuthnRequest) MakeResponse() error
MakeResponse creates and assigns a new SAML response in ResponseEl. `Assertion` must be non-nil. If MakeAssertionEl() has not been called, this function calls it for you.
func (*IdpAuthnRequest) PostBinding ¶ added in v0.4.11
func (req *IdpAuthnRequest) PostBinding() (IdpAuthnRequestForm, error)
PostBinding creates the HTTP POST form information for this `IdpAuthnRequest`. If `Response` is not already set, it calls MakeResponse to produce it.
func (*IdpAuthnRequest) SimpleSignBinding ¶ added in v0.6.0
func (req *IdpAuthnRequest) SimpleSignBinding() (IdpAuthnRequestSimpleSignForm, error)
SimpleSignBinding creates the HTTP-POST-SimpleSign form information for this IdpAuthnRequest, which must have an ACS endpoint with that binding. If ResponseEl is not already set, it calls MakeResponse to produce it.
The Response and its Assertion keep the enveloped XML signatures MakeResponse gives them (sstc-saml-binding-simplesign-cs-01 §2.4 says such signatures MUST remain intact), so a service provider that ignores the SimpleSign signature can still check them. The SimpleSign signature is made with the IdP's key and SignatureMethod (by default SHA-256 for the key type). The relay state is signed, and sent, only when it is not empty.
func (*IdpAuthnRequest) Validate ¶
func (req *IdpAuthnRequest) Validate() error
Validate checks that the authentication request is valid and assigns the AuthnRequest and Metadata properties. Returns a non-nil error if the request is not valid.
Signatures on requests sent with the HTTP-Redirect or HTTP-POST binding are not checked. A request sent with the HTTP-POST-SimpleSign binding must carry a valid SimpleSign signature made with a signing certificate from the service provider's metadata (its validity period is not checked), and a Destination equal to SSOURL; it is rejected otherwise. Any other request that carries a signature, enveloped or in the SigAlg and Signature query parameters, must also have a Destination equal to SSOURL, as saml-bindings-2.0-os §3.4.5.2 and §3.5.5.2 require of signed messages.
func (*IdpAuthnRequest) WriteResponse ¶
func (req *IdpAuthnRequest) WriteResponse(w http.ResponseWriter) error
WriteResponse writes the `Response` to the http.ResponseWriter. If `Response` is not already set, it calls MakeResponse to produce it.
If the ACS endpoint uses the HTTP-POST-SimpleSign binding, the form is the one SimpleSignBinding describes, rendered with IdentityProvider.SimpleSignResponseFormTemplate. Otherwise it is the HTTP-POST form PostBinding describes, rendered with ResponseFormTemplate.
type IdpAuthnRequestForm ¶ added in v0.4.11
IdpAuthnRequestForm contans HTML form information to be submitted to the SAML HTTP POST binding ACS.
type IdpAuthnRequestSimpleSignForm ¶ added in v0.6.0
type IdpAuthnRequestSimpleSignForm struct {
URL string
SAMLResponse string
RelayState string
// SigAlg and Signature are the SimpleSign signature algorithm and the
// base64 encoded signature over the response XML, RelayState (when not
// empty) and SigAlg.
SigAlg string
Signature string
}
IdpAuthnRequestSimpleSignForm contains the HTML form information to be submitted to an ACS endpoint with the HTTP-POST-SimpleSign binding.
type IdpLogoutRequest ¶ added in v0.6.1
type IdpLogoutRequest struct {
IDP *IdentityProvider
HTTPRequest *http.Request
// Binding is the binding the request was received with,
// HTTPRedirectBinding, HTTPPostBinding or SOAPBinding. A request
// received with SOAPBinding comes from the service provider's server,
// not through the browser: HTTPRequest carries no cookie of the user.
Binding string
RelayState string
RequestBuffer []byte
Request LogoutRequest
// ServiceProviderMetadata is the metadata of the service provider that
// issued the request, and SLOEndpoint is the SingleLogoutService endpoint
// of that service provider the LogoutResponse is sent to. Both are set by
// Validate. For a request received with the SOAP binding, the response
// is returned in the HTTP response, so SLOEndpoint has the SOAP binding
// and no Location.
ServiceProviderMetadata *EntityDescriptor
SLOEndpoint *Endpoint
Now time.Time
// contains filtered or unexported fields
}
IdpLogoutRequest is used by IdentityProvider to handle a single logout request (saml-core-2.0-os §3.7) sent by a service provider.
func NewIdpLogoutRequest ¶ added in v0.6.1
func NewIdpLogoutRequest(idp *IdentityProvider, r *http.Request) (*IdpLogoutRequest, error)
NewIdpLogoutRequest returns a new IdpLogoutRequest for the given HTTP request to the single logout service. A GET request is decoded as an HTTP-Redirect binding message, a POST request as an HTTP-POST binding message, and a POST request whose Content-Type is text/xml as a SOAP binding message (a SOAP 1.1 envelope whose Body holds the LogoutRequest) if LogoutBindings includes SOAPBinding. The request is not validated; call Validate for that.
func (*IdpLogoutRequest) MakeLogoutResponse ¶ added in v0.6.1
func (req *IdpLogoutRequest) MakeLogoutResponse(statusCode string) *LogoutResponse
MakeLogoutResponse returns an unsigned LogoutResponse to the request with the given top-level status code (for example StatusSuccess or StatusResponder), addressed to SLOEndpoint. Validate must have succeeded.
func (*IdpLogoutRequest) MatchesSession ¶ added in v0.6.1
func (req *IdpLogoutRequest) MatchesSession(session *Session) bool
MatchesSession reports whether session is one that the logout request asks to terminate: its NameID must be the request's NameID and, if the request carries any SessionIndex, its Index must be equal to one of them (saml-core-2.0-os §3.7.1). Call it only after Validate has succeeded.
func (*IdpLogoutRequest) Validate ¶ added in v0.6.1
func (req *IdpLogoutRequest) Validate() error
Validate checks that the logout request is well formed, was issued by a known service provider, is signed by that service provider, and is addressed to this IdP and still current. It assigns Request, ServiceProviderMetadata and SLOEndpoint. It returns a non-nil error if the request is not valid.
The principal is identified by a NameID or an EncryptedID, or by a BaseID if the IdP's AcceptLogoutRequestBaseID is set. An EncryptedID is decrypted with the IdP's Key, if it is an *rsa.PrivateKey, then with each of its DecryptionKeys; Request.NameID (or Request.BaseID) is then set to the identifier it holds.
The request must be signed: with the HTTP-Redirect binding, with a query string signature (SigAlg and Signature) or an enveloped XML signature; with the HTTP-POST binding, with an enveloped XML signature. The signature is checked against the signing certificates in the service provider's metadata (saml-profiles-2.0-os §4.4.4.1). As is usual for keys distributed in metadata, the certificates' validity periods are not checked.
If IdentityProvider.ReplayCache is set, the request's ID is recorded in it once the request is otherwise valid, and a request whose ID is already recorded is refused, so Validate accepts a given request only once.
func (*IdpLogoutRequest) WriteLogoutResponse ¶ added in v0.6.1
func (req *IdpLogoutRequest) WriteLogoutResponse(w http.ResponseWriter, resp *LogoutResponse) error
WriteLogoutResponse signs resp with the IdP's key and sends it to the browser using the binding of SLOEndpoint: with HTTP-Redirect, a redirect whose query carries a SigAlg and Signature (saml-bindings-2.0-os §3.4.4.1); with HTTP-POST, an auto-submitting form (see IdentityProvider.ResponseFormTemplate) carrying the response with an enveloped XML signature. The request's RelayState is passed back. With the SOAP binding, the response, with an enveloped XML signature, is written in a SOAP envelope as the answer to the service provider's HTTP request.
It returns errors before it starts writing to w.
type IndexedEndpoint ¶
type IndexedEndpoint struct {
Binding string `xml:"Binding,attr"`
Location string `xml:"Location,attr"`
ResponseLocation *string `xml:"ResponseLocation,attr,omitempty"`
Index int `xml:"index,attr"`
IsDefault *bool `xml:"isDefault,attr"`
}
IndexedEndpoint represents the SAML IndexedEndpointType object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.2.3
func (*IndexedEndpoint) UnmarshalXML ¶ added in v0.4.14
func (m *IndexedEndpoint) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type InvalidResponseError ¶
InvalidResponseError is the error produced by ParseResponse when it fails. The underlying error is in PrivateErr. Response is the response as it was known at the time validation failed. Now is the time that was used to validate time-dependent parts of the assertion.
func (*InvalidResponseError) Error ¶
func (ivr *InvalidResponseError) Error() string
func (*InvalidResponseError) Unwrap ¶ added in v0.6.0
func (ivr *InvalidResponseError) Unwrap() error
Unwrap returns PrivateErr, so that errors.Is and errors.As can inspect the reason a response was rejected.
type Issuer ¶
type Issuer struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
NameQualifier string `xml:",attr"`
SPNameQualifier string `xml:",attr"`
Format string `xml:",attr"`
SPProvidedID string `xml:",attr"`
Value string `xml:",chardata"`
}
Issuer represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
type KeyDescriptor ¶
type KeyDescriptor struct {
// Use is "signing", "encryption", or empty, which means the key is used
// for both (saml-metadata-2.0-os §2.4.1.1).
Use string `xml:"use,attr,omitempty"`
KeyInfo KeyInfo `xml:"http://www.w3.org/2000/09/xmldsig# KeyInfo"`
EncryptionMethods []EncryptionMethod `xml:"EncryptionMethod"`
}
KeyDescriptor represents the XMLSEC object of the same name
type KeyInfo ¶
type KeyInfo struct {
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# KeyInfo"`
X509Data X509Data `xml:"X509Data"`
}
KeyInfo represents the XMLSEC object of the same name
type LocalizedName ¶
type LocalizedName struct {
Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr"`
Value string `xml:",chardata"`
}
LocalizedName represents the SAML type localizedNameType.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.2.4
type LocalizedURI ¶
type LocalizedURI struct {
Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr"`
Value string `xml:",chardata"`
}
LocalizedURI represents the SAML type localizedURIType.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.2.5
type LogoutRequest ¶
type LogoutRequest struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol LogoutRequest"`
ID string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
NotOnOrAfter *time.Time `xml:",attr"`
Destination string `xml:",attr"`
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
NameID *NameID `xml:"urn:oasis:names:tc:SAML:2.0:assertion NameID"`
Signature *etree.Element
// EncryptedID is the saml:EncryptedID element that identifies the
// principal instead of NameID (saml-core-2.0-os §2.2.4 and §3.7.1), or
// nil. IdpLogoutRequest.Validate and ServiceProvider.ValidateLogoutRequest
// decrypt it and set NameID to the result, or BaseID if it holds a
// saml:BaseID.
EncryptedID *etree.Element `xml:"urn:oasis:names:tc:SAML:2.0:assertion EncryptedID"`
// BaseID is the saml:BaseID element that identifies the principal
// instead of NameID (saml-core-2.0-os §2.2.3 and §3.7.1), or nil. It is
// kept as an element because the content of a BaseID is defined by its
// xsi:type extension, which this package does not interpret. It is set
// either as read, or by decrypting an EncryptedID. A request identified
// by a BaseID is refused unless IdentityProvider.AcceptLogoutRequestBaseID
// or ServiceProvider.AcceptLogoutRequestBaseID is set.
BaseID *etree.Element `xml:"urn:oasis:names:tc:SAML:2.0:assertion BaseID"`
// A LogoutRequest carries zero or more SessionIndex elements
// (saml-core-2.0-os §3.7.1). SessionIndex holds the first one, and
// AdditionalSessionIndexes holds the rest, in document order. Use
// AllSessionIndexes to read all of them.
SessionIndex *SessionIndex `xml:"SessionIndex"`
AdditionalSessionIndexes []SessionIndex `xml:"-"`
}
LogoutRequest represents the SAML object of the same name, a request from an IDP to destroy a user's session.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*LogoutRequest) AllSessionIndexes ¶ added in v0.6.2
func (r *LogoutRequest) AllSessionIndexes() []SessionIndex
AllSessionIndexes returns every SessionIndex of the request: SessionIndex, if set, followed by AdditionalSessionIndexes.
func (*LogoutRequest) Bytes ¶ added in v0.4.0
func (r *LogoutRequest) Bytes() ([]byte, error)
Bytes returns a byte array representation of the LogoutRequest
func (*LogoutRequest) Deflate ¶ added in v0.4.0
func (r *LogoutRequest) Deflate() ([]byte, error)
Deflate returns a compressed byte array of the LogoutRequest
func (*LogoutRequest) Element ¶
func (r *LogoutRequest) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*LogoutRequest) MarshalXML ¶
func (r *LogoutRequest) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*LogoutRequest) Post ¶ added in v0.4.1
func (r *LogoutRequest) Post(relayState string) []byte
Post returns an HTML form suitable for using the HTTP-POST binding with the request
func (*LogoutRequest) PostWithNonce ¶ added in v0.6.0
func (r *LogoutRequest) PostWithNonce(relayState, nonce string) []byte
PostWithNonce is like Post, but if nonce is not empty it is set as the nonce attribute of the form's auto-submit <script> element, so that the form can be served under a Content-Security-Policy that allows scripts by nonce.
func (*LogoutRequest) Redirect ¶ added in v0.4.1
func (r *LogoutRequest) Redirect(relayState string) *url.URL
Redirect returns a URL suitable for using the redirect binding with the request. The URL carries no query string signature; use ServiceProvider.MakeRedirectLogoutRequest to produce a signed one. Any enveloped XML signature is omitted, as required by the HTTP-Redirect binding.
func (*LogoutRequest) SimpleSign ¶ added in v0.6.0
func (r *LogoutRequest) SimpleSign(relayState string, sp *ServiceProvider) ([]byte, error)
SimpleSign returns an auto-submitting HTML form that sends the request to its Destination with the HTTP-POST-SimpleSign binding, signed with sp's Key and SignatureMethod, which must be set. An XML signature the request already carries is kept.
func (*LogoutRequest) SimpleSignWithNonce ¶ added in v0.6.0
func (r *LogoutRequest) SimpleSignWithNonce(relayState, nonce string, sp *ServiceProvider) ([]byte, error)
SimpleSignWithNonce is like SimpleSign, but if nonce is not empty it is set as the nonce attribute of the form's auto-submit <script> element.
func (*LogoutRequest) UnmarshalXML ¶
func (r *LogoutRequest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type LogoutRequestOption ¶ added in v0.6.0
type LogoutRequestOption func(*LogoutRequest)
LogoutRequestOption customizes a LogoutRequest produced by MakeLogoutRequest, MakeRedirectLogoutRequest or MakePostLogoutRequest. The option is applied before the request is signed.
func WithSessionIndex ¶ added in v0.6.0
func WithSessionIndex(sessionIndex string) LogoutRequestOption
WithSessionIndex sets the SessionIndex element of a LogoutRequest, which identifies the session at the IDP to terminate (saml-core-2.0-os section 3.7.1). The value is typically the SessionIndex attribute of the AuthnStatement in the assertion the IDP issued at login. Some IDPs require it to perform single logout. An empty value leaves SessionIndex unset.
func WithSessionIndexes ¶ added in v0.6.2
func WithSessionIndexes(sessionIndexes ...string) LogoutRequestOption
WithSessionIndexes sets the SessionIndex elements of a LogoutRequest, one for each non-empty value, in order (saml-core-2.0-os section 3.7.1). Use it instead of WithSessionIndex to end several sessions of the principal at the IDP with one request. Without any non-empty value, the request carries no SessionIndex.
type LogoutResponse ¶
type LogoutResponse struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol LogoutResponse"`
ID string `xml:",attr"`
InResponseTo string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
Destination string `xml:",attr"`
Consent string `xml:",attr"`
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
Status Status `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"`
}
LogoutResponse represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*LogoutResponse) Element ¶
func (r *LogoutResponse) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*LogoutResponse) MarshalXML ¶
func (r *LogoutResponse) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*LogoutResponse) Post ¶ added in v0.4.5
func (r *LogoutResponse) Post(relayState string) []byte
Post returns an HTML form suitable for using the HTTP-POST binding with the LogoutResponse.
func (*LogoutResponse) PostWithNonce ¶ added in v0.6.0
func (r *LogoutResponse) PostWithNonce(relayState, nonce string) []byte
PostWithNonce is like Post, but if nonce is not empty it is set as the nonce attribute of the form's auto-submit <script> element, so that the form can be served under a Content-Security-Policy that allows scripts by nonce.
func (*LogoutResponse) Redirect ¶ added in v0.4.5
func (r *LogoutResponse) Redirect(relayState string) *url.URL
Redirect returns a URL suitable for using the redirect binding with the LogoutResponse. The URL carries no query string signature; use ServiceProvider.MakeRedirectLogoutResponse to produce a signed one. Any enveloped XML signature is omitted, as required by the HTTP-Redirect binding.
func (*LogoutResponse) SimpleSign ¶ added in v0.6.0
func (r *LogoutResponse) SimpleSign(relayState string, sp *ServiceProvider) ([]byte, error)
SimpleSign returns an auto-submitting HTML form that sends the response to its Destination with the HTTP-POST-SimpleSign binding, signed with sp's Key and SignatureMethod, which must be set. An XML signature the response already carries is kept.
func (*LogoutResponse) SimpleSignWithNonce ¶ added in v0.6.0
func (r *LogoutResponse) SimpleSignWithNonce(relayState, nonce string, sp *ServiceProvider) ([]byte, error)
SimpleSignWithNonce is like SimpleSign, but if nonce is not empty it is set as the nonce attribute of the form's auto-submit <script> element.
func (*LogoutResponse) UnmarshalXML ¶
func (r *LogoutResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type NameID ¶
type NameID struct {
NameQualifier string `xml:",attr"`
SPNameQualifier string `xml:",attr"`
Format string `xml:",attr"`
SPProvidedID string `xml:",attr"`
Value string `xml:",chardata"`
}
NameID represents the SAML element NameID.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.2.3
type NameIDFormat ¶
type NameIDFormat string
NameIDFormat is the format of the id
const ( UnspecifiedNameIDFormat NameIDFormat = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" TransientNameIDFormat NameIDFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient" EmailAddressNameIDFormat NameIDFormat = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" PersistentNameIDFormat NameIDFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" )
Name ID formats
func (NameIDFormat) Element ¶
func (n NameIDFormat) Element() *etree.Element
Element returns an XML element representation of n.
type NameIDPolicy ¶
type NameIDPolicy struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol NameIDPolicy"`
Format *string `xml:",attr"`
SPNameQualifier *string `xml:",attr"`
AllowCreate *bool `xml:",attr"`
}
NameIDPolicy represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*NameIDPolicy) Element ¶
func (a *NameIDPolicy) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type OneTimeUse ¶
type OneTimeUse struct{}
OneTimeUse represents the SAML element OneTimeUse.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.5.1.5
func (*OneTimeUse) Element ¶
func (a *OneTimeUse) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type Organization ¶
type Organization struct {
OrganizationNames []LocalizedName `xml:"OrganizationName"`
OrganizationDisplayNames []LocalizedName `xml:"OrganizationDisplayName"`
OrganizationURLs []LocalizedURI `xml:"OrganizationURL"`
}
Organization represents the SAML Organization object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.3.2.1
type PDPDescriptor ¶
type PDPDescriptor struct {
RoleDescriptor
AuthzServices []Endpoint `xml:"AuthzService"`
AssertionIDRequestServices []Endpoint `xml:"AssertionIDRequestService"`
NameIDFormats []NameIDFormat `xml:"NameIDFormat"`
}
PDPDescriptor represents the SAML PDPDescriptor object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.6
func (PDPDescriptor) MarshalXML ¶ added in v0.6.0
func (m PDPDescriptor) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*PDPDescriptor) UnmarshalXML ¶ added in v0.6.0
func (m *PDPDescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type ProxyRestriction ¶
type ProxyRestriction struct {
Count *int `xml:",attr,omitempty"`
Audiences []Audience `xml:"urn:oasis:names:tc:SAML:2.0:assertion Audience"`
}
ProxyRestriction represents the SAML element ProxyRestriction.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.5.1.6
func (*ProxyRestriction) Element ¶
func (a *ProxyRestriction) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type RelaxedTime ¶
RelaxedTime is a version of time.Time that supports the time format found in SAML documents.
func (RelaxedTime) MarshalText ¶
func (m RelaxedTime) MarshalText() ([]byte, error)
MarshalText implements encoding.TextMarshaler
func (RelaxedTime) String ¶
func (m RelaxedTime) String() string
func (*RelaxedTime) UnmarshalText ¶
func (m *RelaxedTime) UnmarshalText(text []byte) error
UnmarshalText implements encoding.TextUnmarshaler
type RequestedAttribute ¶
RequestedAttribute represents the SAML RequestedAttribute object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.4.2
type RequestedAuthnContext ¶ added in v0.4.7
type RequestedAuthnContext struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol RequestedAuthnContext"`
Comparison string `xml:",attr"`
// AuthnContextClassRefs lists the requested authentication context
// classes, in order of preference. When parsing, it holds every
// AuthnContextClassRef element in the request.
AuthnContextClassRefs []string `xml:"-"`
// AuthnContextClassRef is a single requested authentication context
// class. When marshaling it is used only if AuthnContextClassRefs is
// empty. When parsing it is set to the first AuthnContextClassRef
// element.
//
// Deprecated: use AuthnContextClassRefs, which can carry more than one
// value.
AuthnContextClassRef string `xml:"-"`
}
RequestedAuthnContext represents the SAML object of the same name, an indication of the requirements on the authentication process.
The SAML schema allows one or more AuthnContextClassRef elements (saml-core section 3.3.2.2.1).
func (*RequestedAuthnContext) ClassRefs ¶ added in v0.6.0
func (r *RequestedAuthnContext) ClassRefs() []string
ClassRefs returns the requested authentication context classes: the values of AuthnContextClassRefs if it is set, otherwise AuthnContextClassRef, if that is set.
func (*RequestedAuthnContext) Element ¶ added in v0.4.7
func (r *RequestedAuthnContext) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (RequestedAuthnContext) MarshalXML ¶ added in v0.6.0
func (r RequestedAuthnContext) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler.
func (*RequestedAuthnContext) UnmarshalXML ¶ added in v0.6.0
func (r *RequestedAuthnContext) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler.
type Response ¶
type Response struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol Response"`
ID string `xml:",attr"`
InResponseTo string `xml:",attr"`
Version string `xml:",attr"`
IssueInstant time.Time `xml:",attr"`
Destination string `xml:",attr"`
Consent string `xml:",attr"`
Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
Signature *etree.Element
Status Status `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"`
// TODO(ross): more than one EncryptedAssertion is allowed
EncryptedAssertion *etree.Element `xml:"urn:oasis:names:tc:SAML:2.0:assertion EncryptedAssertion"`
// TODO(ross): more than one Assertion is allowed
Assertion *Assertion `xml:"urn:oasis:names:tc:SAML:2.0:assertion Assertion"`
}
Response represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*Response) MarshalXML ¶
MarshalXML implements xml.Marshaler
func (*Response) UnmarshalXML ¶
UnmarshalXML implements xml.Unmarshaler
type ResponseWriter ¶ added in v0.6.0
type ResponseWriter interface {
// WriteResponse writes the HTTP response carrying the SAML response for
// req. req.ResponseEl is nil until req.MakeResponse (or req.PostBinding,
// which calls it) has been called. For an error Response it has been
// set by req.MakeErrorResponse, and req.Assertion is nil. If it returns
// an error, the caller logs it and replies with an HTTP 500 error, so an
// implementation should return errors before it starts writing to w.
WriteResponse(w http.ResponseWriter, req *IdpAuthnRequest) error
}
ResponseWriter is an interface used by IdentityProvider to send the SAML response for a request to the browser, once the assertion has been made. The default implementation is DefaultResponseWriter, which is used if IdentityProvider.ResponseWriter is not set.
Implement it to control the whole HTTP response, for example to set headers, to render the response inside the embedding application's own pages, or to support a binding other than HTTP-POST. To only change the markup of the default auto-submitting HTML form, set IdentityProvider.ResponseFormTemplate instead.
type RoleDescriptor ¶
type RoleDescriptor struct {
ID string `xml:",attr,omitempty"`
ValidUntil *time.Time `xml:"validUntil,attr,omitempty"`
CacheDuration time.Duration `xml:"cacheDuration,attr,omitempty"`
ProtocolSupportEnumeration string `xml:"protocolSupportEnumeration,attr"`
ErrorURL string `xml:"errorURL,attr,omitempty"`
Signature *etree.Element
Extensions *Extensions `xml:"urn:oasis:names:tc:SAML:2.0:metadata Extensions,omitempty"`
KeyDescriptors []KeyDescriptor `xml:"KeyDescriptor,omitempty"`
Organization *Organization `xml:"Organization,omitempty"`
ContactPeople []ContactPerson `xml:"ContactPerson,omitempty"`
// XSIType is the xsi:type of a md:RoleDescriptor element. RoleDescriptor
// is an abstract type (saml-metadata-2.0-os §2.4.1), so such an element
// names its concrete type, for example
// {Space: "http://docs.oasis-open.org/wsfed/federation/200706", Local:
// "SecurityTokenServiceType"}. It is read and written only for the
// elements of EntityDescriptor.RoleDescriptors, not for the concrete
// descriptor types that embed RoleDescriptor.
//
// The prefix in the attribute value is resolved with the namespace
// declarations of the RoleDescriptor, EntityDescriptor and
// EntitiesDescriptor elements. If it cannot be resolved, Space is empty
// and Local is the attribute value as written.
XSIType xml.Name `xml:"-"`
}
RoleDescriptor represents the SAML element RoleDescriptor.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.1
type SPSSODescriptor ¶
type SPSSODescriptor struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:metadata SPSSODescriptor"`
SSODescriptor
AuthnRequestsSigned *bool `xml:",attr"`
WantAssertionsSigned *bool `xml:",attr"`
AssertionConsumerServices []IndexedEndpoint `xml:"AssertionConsumerService"`
AttributeConsumingServices []AttributeConsumingService `xml:"AttributeConsumingService"`
}
SPSSODescriptor represents the SAML SPSSODescriptorType object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.2
func (SPSSODescriptor) MarshalXML ¶ added in v0.6.0
func (m SPSSODescriptor) MarshalXML(e *xml.Encoder, _ xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*SPSSODescriptor) UnmarshalXML ¶ added in v0.6.0
func (m *SPSSODescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type SSODescriptor ¶
type SSODescriptor struct {
RoleDescriptor
ArtifactResolutionServices []IndexedEndpoint `xml:"ArtifactResolutionService"`
SingleLogoutServices []Endpoint `xml:"SingleLogoutService"`
ManageNameIDServices []Endpoint `xml:"ManageNameIDService"`
NameIDFormats []NameIDFormat `xml:"NameIDFormat"`
}
SSODescriptor represents the SAML complex type SSODescriptor
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.2
type Scoping ¶ added in v0.6.0
type Scoping struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol Scoping"`
ProxyCount *int `xml:",attr"`
IDPList *IDPList `xml:"urn:oasis:names:tc:SAML:2.0:protocol IDPList"`
RequesterIDs []string `xml:"urn:oasis:names:tc:SAML:2.0:protocol RequesterID"`
}
Scoping represents the SAML object of the same name. It lets a requester specify the identity providers it trusts to authenticate the presenter, which proxying identity providers (gateways) use to pick a delegate IDP.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf § 3.4.1.2
type ServiceProvider ¶
type ServiceProvider struct {
// Entity ID is optional - if not specified then MetadataURL will be used
EntityID string
// Key is the private key we use to sign requests. Its public key must be
// an *rsa.PublicKey or an *ecdsa.PublicKey. Any crypto.Signer works for
// signing, including keys held in a KMS or HSM. Unless EncryptionKey is
// set, Key is also used to decrypt encrypted assertions, which only works
// when Key is an *rsa.PrivateKey.
Key crypto.Signer
// Certificate is the public part of Key.
Certificate *x509.Certificate
Intermediates []*x509.Certificate
// EncryptionKey, if set, is the private key used to decrypt encrypted
// assertions, instead of Key. Use it to keep separate signing and
// encryption keys, for example when Key is an ECDSA key, which cannot be
// used for XML encryption.
EncryptionKey *rsa.PrivateKey
// EncryptionCertificate is the public part of EncryptionKey. It is
// advertised in the metadata as the encryption key. If it is nil, the
// metadata advertises Certificate for encryption, but only when its public
// key is an RSA key.
EncryptionCertificate *x509.Certificate
// DecryptionKeys are further private keys that decrypt encrypted
// assertions, tried in order after EncryptionKey (or Key, if
// EncryptionKey is unset). Set them while rotating the SP encryption key,
// so that an assertion the IdP encrypted to either the old or the new key
// is accepted. They are never used for signing, and are not advertised in
// the metadata.
DecryptionKeys []*rsa.PrivateKey
// HTTPClient to use during SAML artifact resolution and attribute
// queries (QueryAttributes). If nil, http.DefaultClient is used.
HTTPClient *http.Client
// AllowInsecureSOAPEndpoints lets the service provider send SOAP
// messages (ArtifactResolve, AttributeQuery and SOAP LogoutRequest) to
// http endpoints of the IdP. By default they are sent only to https
// endpoints, and an http one fails with an error matching
// ErrInsecureSOAPEndpoint, so that the user's NameID, attributes and
// assertions never cross the network in the clear. Set it only for
// tests and development setups.
AllowInsecureSOAPEndpoints bool
// MetadataURL is the full URL to the metadata endpoint on this host,
// i.e. https://example.com/saml/metadata
MetadataURL url.URL
// AcsURL is the full URL to the SAML Assertion Customer Service endpoint
// on this host, i.e. https://example.com/saml/acs
AcsURL url.URL
// AcsIndex, if set, makes authentication requests carry
// AssertionConsumerServiceIndex with this value, instead of
// AssertionConsumerServiceURL and ProtocolBinding (SAML core §3.4.1
// does not allow both). The IdP then sends the response to the
// AssertionConsumerService endpoint with this index in the SP metadata it
// has on file, using that endpoint's binding. That endpoint's Location
// must still be AcsURL, because responses are only accepted there. If nil,
// requests carry AssertionConsumerServiceURL and ProtocolBinding.
AcsIndex *int
// SloURL is the full URL to the SAML Single Logout endpoint on this host.
// i.e. https://example.com/saml/slo
SloURL url.URL
// IDPMetadata is the metadata from the identity provider.
IDPMetadata *EntityDescriptor
// IDPCertificateFingerprint is fingerprint of the idp public certificate. If this field is specified,
// IDPCertificateFingerprintAlgorithm must also be specified, and IDPCertificate must not be specified.
IDPCertificateFingerprint *string
// IDPCertificateFingerprintAlgorithm is fingerprint algorithm used to obtain fingerprint of the idp public
// certificate.
// If this field is specified, IDPCertificateFingerprint must also be specified, and IDPCertificate must not be specified.
IDPCertificateFingerprintAlgorithm *string
// IDPCertificate to use as idp public certificate. If this field is specified, IDPCertificateFingerprint and
// IDPCertificateFingerprintAlgorithm must not be specified.
IDPCertificate *string
// AuthnNameIDFormat is the format used in the NameIDPolicy for
// authentication requests
AuthnNameIDFormat NameIDFormat
// SendUnspecifiedNameIDFormat, when true and AuthnNameIDFormat is
// UnspecifiedNameIDFormat, sends the full unspecified URI as the Format
// of the AuthnRequest NameIDPolicy and the LogoutRequest NameID. By
// default the Format is left off, which the spec reads as unspecified
// (SAML Core §2.2.2, §3.4.1.1), but some IdPs (e.g. Keycloak) reject a
// request without it.
SendUnspecifiedNameIDFormat bool
// Scoping, when set, is sent in authentication requests. Proxying identity
// providers (gateways) use its IDPList to choose which identity provider to
// delegate authentication to.
Scoping *Scoping
// MetadataValidDuration is a duration used to calculate validUntil
// attribute in the metadata endpoint
MetadataValidDuration time.Duration
// MetadataOmitValidUntil, when true, omits the optional validUntil
// attribute from the metadata (saml-metadata-2.0-os §2.3.2). Because the
// root element must carry validUntil or cacheDuration (§2.3.1), the
// metadata then carries cacheDuration (DefaultCacheDuration) instead.
// MetadataValidDuration is ignored when this is set.
MetadataOmitValidUntil bool
// ForceAuthn allows you to force re-authentication of users even if the user
// has a SSO session at the IdP.
ForceAuthn *bool
// RequestedAuthnContext allow you to specify the requested authentication
// context in authentication requests
RequestedAuthnContext *RequestedAuthnContext
// ValidateAuthnContextClassRef, if true, requires an assertion to carry
// an AuthnStatement whose AuthnContextClassRef is one of the classes in
// RequestedAuthnContext. It has no effect if RequestedAuthnContext is
// nil or names no class.
//
// The "exact" Comparison (or an empty one, which means "exact") is
// supported directly. The ordering that "minimum", "better" and
// "maximum" refer to is defined by each deployment, not by the SAML
// specification (saml-core §3.3.2.2.1), so for any other Comparison
// AuthnContextClassRefComparator decides; without it, every assertion
// is rejected rather than accepted unchecked.
ValidateAuthnContextClassRef bool
// AuthnContextClassRefComparator, if set, lets ValidateAuthnContextClassRef
// check a RequestedAuthnContext whose Comparison is not "exact" (for
// example "minimum", "better" or "maximum"), using the deployment's own
// ordering of authentication context classes.
//
// It is called with the Comparison, the requested classes (in order of
// preference) and the AuthnContextClassRef of one AuthnStatement of the
// assertion, and reports whether that class satisfies the request. The
// assertion is accepted if it returns true for any AuthnStatement. It
// should return false for a Comparison it does not know.
//
// It is not called for the "exact" Comparison, which is always checked
// by string equality.
AuthnContextClassRefComparator func(comparison string, requested []string, got string) bool
// AllowIDPInitiated accepts unsolicited (IdP-initiated) responses, which
// have no InResponseTo. A response or assertion that does carry an
// InResponseTo must still match a request this SP made; set
// ValidateRequestID to accept IdPs that send one on IdP-initiated logins.
AllowIDPInitiated bool
// DefaultRedirectURI where untracked requests (as of IDPInitiated) are redirected to
DefaultRedirectURI string
// SignatureVerifier, if non-nil, allows you to implement an alternative way
// to verify signatures.
SignatureVerifier SignatureVerifier
// SignatureMethod, if non-empty, authentication requests will be signed.
//
// The method specified here must be consistent with the type of Key.
//
// If Key is *rsa.PrivateKey, then this must be one of dsig.RSASHA1SignatureMethod,
// dsig.RSASHA256SignatureMethod, dsig.RSASHA384SignatureMethod, or
// dsig.RSASHA512SignatureMethod:
//
// If Key is *ecdsa.PrivateKey, then this must be one of dsig.ECDSASHA1SignatureMethod,
// dsig.ECDSASHA256SignatureMethod, dsig.ECDSASHA384SignatureMethod, or
// dsig.ECDSASHA512SignatureMethod.
SignatureMethod string
// LogoutSignatureMethod, if non-empty, is used instead of
// SignatureMethod to sign the LogoutRequests and LogoutResponses the SP
// sends, so that they can be signed while AuthnRequests are not. The
// single logout profile requires LogoutRequests and LogoutResponses sent
// with the HTTP-Redirect or HTTP-POST binding to be signed
// (saml-profiles §4.4.3.1 and §4.4.3.4). If empty, SignatureMethod is
// used for them too. It takes the same values as SignatureMethod.
LogoutSignatureMethod string
// SignMetadata, if true, asks that the SP metadata be published with an
// enveloped XML signature made with Key; samlsp.Middleware.ServeMetadata
// honors it. See SignedMetadata.
SignMetadata bool
// LogoutBindings specify the bindings available for SLO endpoint. If empty,
// HTTP-POST binding is used. HTTPPostSimpleSignBinding may be listed: the
// logout validation functions accept HTTP-POST-SimpleSign messages.
LogoutBindings []string
// AssertionConsumerServiceBindings specify the bindings advertised for the
// AssertionConsumerService endpoint in the SP metadata, in order of
// preference. If empty, both HTTP-POST and HTTP-Artifact bindings are
// advertised. Set this to []string{HTTPPostBinding} to stop advertising
// the HTTP-Artifact binding, for example when the IDP does not publish an
// ArtifactResolutionService or the SP cannot reach it. Include
// HTTPPostSimpleSignBinding to advertise that the ACS accepts
// HTTP-POST-SimpleSign responses (ParseResponse always accepts them).
AssertionConsumerServiceBindings []string
// ValidateAudienceRestriction allows you to override the default audience validation
// for an assertion. If nil, the default audience validation is used: the
// assertion must have at least one AudienceRestriction, and every
// AudienceRestriction must list this SP's audience (EntityID, or
// MetadataURL when EntityID is empty) among its audiences (saml-core
// §2.5.1.4).
ValidateAudienceRestriction func(assertion *Assertion) error
// RejectUnknownConditions, if true, refuses an assertion whose
// Conditions has child elements this package does not understand, named
// in Conditions.UnknownConditions: anything but AudienceRestriction,
// OneTimeUse and ProxyRestriction, such as a saml:Condition extended
// with xsi:type. saml-core §2.5.1.1 makes such an assertion
// Indeterminate, and says it MUST be rejected; the error matches
// ErrUnsupported. It is off by default, so such conditions are ignored,
// because some IdPs send extension conditions (delegation restrictions,
// for example) that refusing would break. ValidateUnknownConditions, if
// set, decides instead.
RejectUnknownConditions bool
// RequireSignedResponseForCBC, if true, refuses to decrypt an
// EncryptedAssertion whose EncryptedData uses a CBC block cipher
// (aes128-cbc, aes192-cbc, aes256-cbc or tripledes-cbc) unless the
// message that carries it was authenticated before decryption: a
// Response (or, for the HTTP-Artifact binding, an ArtifactResponse)
// with a valid signature by the IdP, or a Response whose
// HTTP-POST-SimpleSign signature is valid. The saml-core errata (E93,
// §6.2) say that "when CBC-mode algorithms are used for data
// encryption, relying parties SHOULD require the presence of integrity
// protection before processing encrypted SAML assertions", since
// decrypting unauthenticated CBC ciphertext is what padding and format
// oracle attacks on XML Encryption need. A signature on the assertion
// inside the encryption does not count, because it can only be checked
// after decrypting. The refusal matches ErrInvalidSignature, and
// happens before any decryption. AES-GCM is authenticated encryption,
// so it is not affected. ParseXMLAttributeQueryResponse applies it to
// the Response the attribute authority sends.
//
// It is off by default, because many IdPs sign only the assertion and
// encrypt it with AES-CBC; with it on, configure the IdP to sign the
// Response or to encrypt with AES-GCM.
RequireSignedResponseForCBC bool
// ValidateUnknownConditions, if set, decides an assertion whose
// Conditions has child elements this package does not understand (see
// RejectUnknownConditions), whatever RejectUnknownConditions says:
// return nil to accept the assertion, or an error to refuse it. It is
// called only when there are unknown conditions, and for login and
// attribute query assertions alike.
ValidateUnknownConditions func(assertion *Assertion) error
// ValidateRequestID allows you to override the default request ID validation.
// If nil, the default request ID validation is used. With AllowIDPInitiated
// set, it also decides a non-empty assertion SubjectConfirmationData
// InResponseTo, passed as Response.InResponseTo.
ValidateRequestID func(response Response, possibleRequestIDs []string) error
// Clock, if non-nil, is the time source for everything this
// ServiceProvider does that depends on the current time: timestamps on
// the requests and metadata it issues, assertion and logout message time
// checks, and certificate validity during XML and redirect binding
// signature validation.
//
// If nil, the package-level TimeNow and Clock are used. Setting this
// field instead of replacing those globals allows ServiceProviders with
// different clocks to be used concurrently, for example in parallel
// tests.
Clock *dsig.Clock
// IgnoreCertificateExpiry, if true, disables the check that the IDP's
// signing certificate is within its validity period (NotBefore and
// NotAfter) when validating XML and HTTP-Redirect binding signatures.
// The signature must still be made by a key in one of the trusted IDP
// certificates.
//
// The SAML V2.0 Metadata Interoperability Profile treats certificates in
// metadata only as a container for a public key, and permits them to be
// expired or not yet valid. Some IDPs publish expired signing
// certificates as a result. Enabling this allows interoperating with
// them.
IgnoreCertificateExpiry bool
// RejectExpiredIDPMetadata, if true, refuses to rely on IDPMetadata once
// it has expired: when the signing certificates for a Response,
// Assertion, ArtifactResponse, LogoutRequest, LogoutResponse or attribute
// query response are taken from IDPMetadata, and the validUntil of the
// EntityDescriptor, or of an IDPSSODescriptor (or, for attribute query
// responses, AttributeAuthorityDescriptor) they are taken from, has
// passed, the message is refused with an error matching ErrExpired (and
// ErrInvalidSignature, for XML signatures). saml-metadata-2.0-os §4.3.1
// says expired metadata must not be relied on and a fresh copy must be
// retrieved. When IDPCertificate or IDPCertificateFingerprint is set the
// certificates do not come from IDPMetadata, and it is not checked.
//
// Only validUntil is checked; cacheDuration is not, since the
// ServiceProvider does not know when IDPMetadata was retrieved. The
// samlsp Parse and Fetch metadata functions set the ValidUntil of the
// returned EntityDescriptor to the earliest validUntil of the entity and
// of the EntitiesDescriptor elements that enclose it.
//
// It is off by default, because metadata whose validUntil has passed is
// commonly kept in use, and enabling this rejects every login until the
// metadata is refreshed.
RejectExpiredIDPMetadata bool
// RejectSHA1Signatures, if true, refuses messages from the IDP that are
// signed with a SHA-1 based algorithm: an XML signature whose
// SignatureMethod or any DigestMethod is SHA-1 based (rsa-sha1,
// ecdsa-sha1, dsa-sha1, hmac-sha1 or sha1), and an HTTP-Redirect or
// HTTP-POST-SimpleSign signature whose SigAlg is. The check applies to
// every signature the ServiceProvider verifies, including those checked
// by SignatureVerifier, and the error matches ErrUnsupported (and, for
// XML signatures, ErrInvalidSignature). If false, SHA-1 is accepted.
RejectSHA1Signatures bool
// ReplayCache, if set, records the ID of the assertion each accepted
// response is accepted for, and refuses a response whose assertion it
// has already recorded. Without it, a captured assertion is accepted
// again until it expires, and an IdP-initiated one has no request ID to
// tie it to a single use. If nil, assertions are not checked for replay.
//
// It also records the ID of each LogoutRequest that ValidateLogoutRequest
// (and the other LogoutRequest validation methods) accept, and refuses a
// LogoutRequest whose ID it has already recorded. These IDs are recorded
// under the key "LogoutRequest:" followed by the ID, so they cannot
// collide with assertion IDs, which are recorded as is and, being
// xs:ID values, contain no colon.
//
// It also records each artifact ParseResponse resolves, before
// resolving it, and refuses an artifact it has already recorded
// (saml-bindings-2.0-os §3.6.5.2: an artifact is resolved only once). A
// type 0x0004 artifact is recorded under "Artifact:" followed by the hex
// SourceID, a colon and the hex MessageHandle; any other artifact under
// "Artifact:raw:" followed by its value.
ReplayCache AssertionReplayCache
// RequireStandardArtifacts, if true, makes ParseResponse refuse a
// SAMLart that is not a type 0x0004 artifact (saml-bindings-2.0-os
// §3.6.4: base64 of a 2-byte TypeCode 0x0004, a 2-byte EndpointIndex, a
// 20-byte SourceID and a 20-byte MessageHandle), or whose SourceID is
// not the SHA-1 hash of the IdP's entityID (§3.6.4.1), without
// contacting the IdP. The error matches ErrArtifactResolution, and also
// ErrMalformedMessage, ErrUnsupported or ErrIssuerMismatch. If false,
// such an artifact is sent unchanged to the IdP's first SOAP
// ArtifactResolutionService, as before.
//
// Either way, the EndpointIndex of a type 0x0004 artifact selects the
// indexed SOAP ArtifactResolutionService it names in the IdP metadata,
// falling back to the first SOAP ArtifactResolutionService when none
// has that index.
RequireStandardArtifacts bool
// EncryptLogoutNameID, if true, makes MakeLogoutRequest,
// MakeRedirectLogoutRequest and MakeSimpleSignLogoutRequest identify the
// principal with a saml:EncryptedID instead of a NameID: the NameID is
// encrypted to the IDP's encryption certificate from IDPMetadata (see
// EncryptLogoutRequestNameID). Set it when the IDP requires it, or so
// that the NameID is not disclosed to the browser.
EncryptLogoutNameID bool
// LogoutNameIDEncrypter, if set, encrypts the NameID of LogoutRequests
// for the IDP (see EncryptLogoutNameID). It is passed the IDP's
// *x509.Certificate as the key. Use it to select the key transport,
// digest and block cipher the IDP supports, for example:
//
// enc := xmlenc.OAEP()
// enc.BlockCipher = xmlenc.AES256GCM
// sp.LogoutNameIDEncrypter = enc
//
// When nil, RSA-OAEP-MGF1P with a SHA-1 digest is used with the
// strongest block cipher that the IDP metadata lists in the
// EncryptionMethods of its encryption key: AES-GCM (256, 128 then 192
// bit keys) before AES-CBC. If the metadata lists none of them,
// AES-256-GCM is used; set LogoutNameIDEncrypter for an IDP that cannot
// decrypt AES-GCM and does not say so in its metadata.
LogoutNameIDEncrypter xmlenc.Encrypter
// LimitRelayStateLength, if true, makes the calls that start an exchange
// with the IDP refuse a RelayState longer than MaxRelayStateLength (80
// bytes), as the SAML bindings require of senders (saml-bindings-2.0-os
// §3.4.3 and §3.5.3), with an error matching ErrRelayStateTooLong:
// AuthnRequest.Redirect, MakeRedirectAuthenticationRequest,
// MakePostAuthenticationRequest, AuthnRequest.SimpleSign,
// RedirectLogoutRequestURL, MakeRedirectLogoutRequest,
// MakePostLogoutRequest and LogoutRequest.SimpleSign, and samlsp's
// CookieRequestTracker for a RelayStateFunc result. It is off by
// default, because many IdPs accept a longer RelayState and
// applications rely on it. A RelayState the SP echoes in a
// LogoutResponse is never checked.
LimitRelayStateLength bool
// AcceptLogoutRequestBaseID, if true, lets ValidateLogoutRequest accept
// a LogoutRequest whose principal is a saml:BaseID (in the clear, or in
// an EncryptedID) rather than a NameID. The returned request's BaseID
// then holds the element and its NameID is nil, so the caller must
// interpret the BaseID itself. If false, such a request is refused with
// an error matching ErrUnsupported.
AcceptLogoutRequestBaseID bool
// AcceptAssertionBaseID, if true, lets the SP accept an assertion whose
// Subject identifies the principal with a saml:BaseID (in the clear, or
// in an EncryptedID) rather than a NameID (saml-core-2.0-os §2.2.3 and
// §2.4.1). The returned assertion's Subject.BaseID then holds the
// element and its Subject.NameID is nil, so the caller must interpret
// the BaseID itself: samlsp, for one, takes the session subject from
// the NameID only. If false, such an assertion is refused with an error
// matching ErrUnsupported. An assertion whose Subject has none of
// BaseID, NameID and EncryptedID is always refused (ErrMissingElement).
AcceptAssertionBaseID bool
}
ServiceProvider implements SAML Service provider.
In SAML, service providers delegate responsibility for identifying clients to an identity provider. If you are writing an application that uses passwords (or whatever) stored somewhere else, then you are service provider.
See the example directory for an example of a web application using the service provider interface.
func (*ServiceProvider) EncryptLogoutRequestNameID ¶ added in v0.6.2
func (sp *ServiceProvider) EncryptLogoutRequestNameID(req *LogoutRequest) error
EncryptLogoutRequestNameID replaces the NameID of req with a saml:EncryptedID holding it (saml-core-2.0-os §2.2.4), encrypted to the IDP's encryption certificate with LogoutNameIDEncrypter. The certificate is the first one in IDPMetadata whose KeyDescriptor has use="encryption", or else the first one with no use. Call it before signing req. Use it to encrypt the NameID of some requests only; EncryptLogoutNameID encrypts every request.
func (*ServiceProvider) GetArtifactBindingLocation ¶ added in v0.4.6
func (sp *ServiceProvider) GetArtifactBindingLocation(binding string) string
GetArtifactBindingLocation returns URL for the IDP's Artifact binding of the specified type
func (*ServiceProvider) GetAttributeServiceLocation ¶ added in v0.6.1
func (sp *ServiceProvider) GetAttributeServiceLocation(binding string) string
GetAttributeServiceLocation returns the URL of the IdP's AttributeService endpoint with the given binding, from the AttributeAuthorityDescriptors of the IdP metadata, or "" if there is none. Attribute queries use SOAPBinding.
func (*ServiceProvider) GetSLOBindingLocation ¶
func (sp *ServiceProvider) GetSLOBindingLocation(binding string) string
GetSLOBindingLocation returns URL for the IDP's Single Log Out Service binding of the specified type (HTTPRedirectBinding or HTTPPostBinding)
func (*ServiceProvider) GetSSOBindingLocation ¶
func (sp *ServiceProvider) GetSSOBindingLocation(binding string) string
GetSSOBindingLocation returns URL for the IDP's Single Sign On Service binding of the specified type (HTTPRedirectBinding, HTTPPostBinding or HTTPPostSimpleSignBinding)
func (*ServiceProvider) MakeArtifactResolveRequest ¶ added in v0.4.6
func (sp *ServiceProvider) MakeArtifactResolveRequest(artifactID string) (*ArtifactResolve, error)
MakeArtifactResolveRequest produces a new ArtifactResolve object to send to the idp's Artifact resolver
func (*ServiceProvider) MakeAttributeQuery ¶ added in v0.6.1
func (sp *ServiceProvider) MakeAttributeQuery(nameID NameID, attributes ...Attribute) (*AttributeQuery, error)
MakeAttributeQuery returns an AttributeQuery for the attributes of the subject identified by nameID, addressed to the IdP's SOAP AttributeService (see GetAttributeServiceLocation). It returns ErrNoAttributeService if the IdP metadata has none, and an error matching ErrInsecureSOAPEndpoint if its Location is not https and AllowInsecureSOAPEndpoints is not set.
nameID is sent as is. Pass the NameID the IdP issued for the subject, for example Assertion.Subject.NameID from the login, so that its Format and qualifiers match what the IdP knows the subject by.
attributes, if any, restricts the query to those attributes (and, for an Attribute that has Values, to those values). Each attribute may be named only once (saml-core §3.3.2.3). If attributes is empty, the IdP returns every attribute it releases to this service provider.
The query is signed with SignAttributeQuery when Key is set, whether or not SignatureMethod is: attribute authorities usually release attributes only to requesters they can authenticate (saml-profiles §6.3.1). Without Key the query is unsigned, and the requester must be authenticated some other way, such as with a TLS client certificate in HTTPClient.
func (*ServiceProvider) MakeAuthenticationRequest ¶
func (sp *ServiceProvider) MakeAuthenticationRequest(idpURL string, binding string, resultBinding string) (*AuthnRequest, error)
MakeAuthenticationRequest produces a new AuthnRequest object to send to the idpURL that uses the specified binding (HTTPRedirectBinding or HTTPPostBinding)
func (*ServiceProvider) MakeLogoutRequest ¶
func (sp *ServiceProvider) MakeLogoutRequest(idpURL, nameID string, opts ...LogoutRequestOption) (*LogoutRequest, error)
MakeLogoutRequest produces a new LogoutRequest object for idpURL. If sp.SignatureMethod is set, the request carries an enveloped XML signature, which is what the HTTP-POST binding uses.
func (*ServiceProvider) MakeLogoutResponse ¶ added in v0.4.5
func (sp *ServiceProvider) MakeLogoutResponse(idpURL, logoutRequestID string) (*LogoutResponse, error)
MakeLogoutResponse produces a new LogoutResponse object for idpURL and logoutRequestID. If sp.SignatureMethod is set, the response carries an enveloped XML signature, which is what the HTTP-POST binding uses.
func (*ServiceProvider) MakePostAuthenticationRequest ¶
func (sp *ServiceProvider) MakePostAuthenticationRequest(relayState string) ([]byte, error)
MakePostAuthenticationRequest creates a SAML authentication request using the HTTP-POST binding. It returns HTML text representing an HTML form that can be sent presented to a browser to initiate the login process.
func (*ServiceProvider) MakePostLogoutRequest ¶ added in v0.4.1
func (sp *ServiceProvider) MakePostLogoutRequest(nameID, relayState string, opts ...LogoutRequestOption) ([]byte, error)
MakePostLogoutRequest creates a SAML authentication request using the HTTP-POST binding. It returns HTML text representing an HTML form that can be sent presented to a browser to initiate the logout process.
func (*ServiceProvider) MakePostLogoutResponse ¶ added in v0.4.5
func (sp *ServiceProvider) MakePostLogoutResponse(logoutRequestID, relayState string) ([]byte, error)
MakePostLogoutResponse creates a SAML LogoutResponse using the HTTP-POST binding. It returns HTML text representing an HTML form that can be sent presented to a browser for LogoutResponse.
func (*ServiceProvider) MakeRedirectAuthenticationRequest ¶
func (sp *ServiceProvider) MakeRedirectAuthenticationRequest(relayState string) (*url.URL, error)
MakeRedirectAuthenticationRequest creates a SAML authentication request using the HTTP-Redirect binding. It returns a URL that we will redirect the user to in order to start the auth process.
func (*ServiceProvider) MakeRedirectLogoutRequest ¶
func (sp *ServiceProvider) MakeRedirectLogoutRequest(nameID, relayState string, opts ...LogoutRequestOption) (*url.URL, error)
MakeRedirectLogoutRequest creates a SAML LogoutRequest using the HTTP-Redirect binding. It returns a URL that we will redirect the user to in order to start the logout process.
If sp.SignatureMethod is set, the request is signed with a query string signature (SigAlg and Signature parameters) as the binding requires (saml-bindings-2.0-os section 3.4.4.1), rather than with an enveloped XML signature.
func (*ServiceProvider) MakeRedirectLogoutResponse ¶ added in v0.4.5
func (sp *ServiceProvider) MakeRedirectLogoutResponse(logoutRequestID, relayState string) (*url.URL, error)
MakeRedirectLogoutResponse creates a SAML LogoutResponse using the HTTP-Redirect binding. It returns a URL that we will redirect the user to for LogoutResponse.
If sp.SignatureMethod is set, the response is signed with a query string signature (SigAlg and Signature parameters) as the binding requires (saml-bindings-2.0-os section 3.4.4.1), rather than with an enveloped XML signature.
func (*ServiceProvider) MakeSOAPLogoutRequest ¶ added in v0.6.2
func (sp *ServiceProvider) MakeSOAPLogoutRequest(nameID NameID, opts ...LogoutRequestOption) (*LogoutRequest, error)
MakeSOAPLogoutRequest returns a LogoutRequest for the principal nameID, addressed to the IdP's SingleLogoutService with the SAML SOAP binding, to send with SendSOAPLogoutRequest. It returns ErrNoSOAPSingleLogoutService if the IdP metadata has none, and an error matching ErrInsecureSOAPEndpoint if its Location is not https and AllowInsecureSOAPEndpoints is not set.
nameID is sent as is: pass the NameID the IdP issued, with its Format and qualifiers (for example from samlsp's SessionWithSAMLNameID). opts can add SessionIndexes. The NameID is encrypted if EncryptLogoutNameID is set.
The request is signed when Key is set, whether or not SignatureMethod is (with SHA-256 for the type of Key if it is not): the SOAP binding has no other way to show the IdP that the request comes from this service provider (saml-profiles §4.4.3.1). Without Key it is unsigned, and the service provider must authenticate some other way, such as with a TLS client certificate in HTTPClient.
func (*ServiceProvider) MakeSOAPLogoutResponse ¶ added in v0.6.2
func (sp *ServiceProvider) MakeSOAPLogoutResponse(logoutRequestID string, status Status) (*LogoutResponse, error)
MakeSOAPLogoutResponse returns a LogoutResponse to the LogoutRequest logoutRequestID with the given status, to send back to the IdP with the SOAP binding (see WriteSOAPLogoutResponse). It has no Destination, since a SOAP response goes back over the IdP's own connection.
Use a status code of StatusSuccess when every session the request named has ended, and StatusResponder when they could not be ended, for example because sessions are kept only in browser cookies (saml-core §3.7.3.2).
The response is signed when Key is set, with SignatureMethod or, when that is empty, with SHA-256 for the type of Key: the SOAP binding has no other way to show the IdP that the answer comes from this service provider (saml-profiles §4.4.4.2). Without Key it is unsigned, and the IdP must authenticate the service provider some other way, such as with TLS.
func (*ServiceProvider) MakeSimpleSignAuthenticationRequest ¶ added in v0.6.0
func (sp *ServiceProvider) MakeSimpleSignAuthenticationRequest(relayState string) ([]byte, error)
MakeSimpleSignAuthenticationRequest creates a SAML authentication request for the IDP's HTTP-POST-SimpleSign single sign-on endpoint. It returns an auto-submitting HTML form that sends the request to the IDP.
The request carries no XML signature; it is signed with a SimpleSign signature (sstc-saml-binding-simplesign-cs-01 section 2.5) made with Key and SignatureMethod, which must be set. The response is requested with the HTTP-POST binding, as for MakePostAuthenticationRequest; use MakeAuthenticationRequest and AuthnRequest.SimpleSign to request another.
func (*ServiceProvider) MakeSimpleSignLogoutRequest ¶ added in v0.6.0
func (sp *ServiceProvider) MakeSimpleSignLogoutRequest(nameID, relayState string, opts ...LogoutRequestOption) ([]byte, error)
MakeSimpleSignLogoutRequest creates a SAML LogoutRequest for the IDP's HTTP-POST-SimpleSign single logout endpoint. It returns an auto-submitting HTML form that sends the request to the IDP, signed with a SimpleSign signature made with Key and SignatureMethod, which must be set. The request carries no XML signature.
func (*ServiceProvider) MakeSimpleSignLogoutResponse ¶ added in v0.6.0
func (sp *ServiceProvider) MakeSimpleSignLogoutResponse(logoutRequestID, relayState string) ([]byte, error)
MakeSimpleSignLogoutResponse creates a SAML LogoutResponse for the IDP's HTTP-POST-SimpleSign single logout endpoint. It returns an auto-submitting HTML form that sends the response to the IDP, signed with a SimpleSign signature made with Key and SignatureMethod, which must be set. The response carries no XML signature.
func (*ServiceProvider) Metadata ¶
func (sp *ServiceProvider) Metadata() *EntityDescriptor
Metadata returns the service provider metadata
func (*ServiceProvider) ParseLogoutResponse ¶ added in v0.6.0
func (sp *ServiceProvider) ParseLogoutResponse(req *http.Request, possibleRequestIDs []string) (*LogoutResponse, error)
ParseLogoutResponse validates the LogoutResponse content from the request, which may use the HTTP-Redirect, HTTP-POST or HTTP-POST-SimpleSign binding, as ValidateLogoutResponseRequest does, and returns it. In addition, the response's InResponseTo must be one of possibleRequestIDs, the IDs of the LogoutRequests this service provider sent and still expects an answer to, so that a LogoutResponse cannot be replayed or delivered unsolicited.
func (*ServiceProvider) ParseResponse ¶
func (sp *ServiceProvider) ParseResponse(req *http.Request, possibleRequestIDs []string) (*Assertion, error)
ParseResponse extracts the SAML IDP response received in req, resolves artifacts when necessary, validates it, and returns the verified assertion. req.ParseForm must have been called.
A posted form that carries a SigAlg or Signature field is an HTTP-POST-SimpleSign message (sstc-saml-binding-simplesign-cs-01 section 2.10). Its SimpleSign signature must then be valid, or the response is rejected; it is never accepted on the strength of XML signatures alone. A valid SimpleSign signature authenticates the whole Response, so the assertions need not be signed, and the Response must carry a Destination. An enveloped XML signature on the Response is still checked when present. Every other check (Destination, InResponseTo, Issuer, Status, assertion conditions, decryption, ReplayCache) applies as for HTTP-POST. A form without SigAlg and Signature is handled as HTTP-POST, as before.
func (*ServiceProvider) ParseXMLArtifactResponse ¶ added in v0.4.6
func (sp *ServiceProvider) ParseXMLArtifactResponse(soapResponseXML []byte, possibleRequestIDs []string, artifactRequestID string, currentURL url.URL) (*Assertion, error)
ParseXMLArtifactResponse validates the SAML Artifact resolver response and returns the verified assertion.
This function handles verifying the digital signature, and verifying that the specified conditions and properties are met.
If the function fails it will return an InvalidResponseError whose properties are useful in describing which part of the parsing process failed. However, to discourage inadvertent disclosure the diagnostic information, the Error() method returns a static string.
func (*ServiceProvider) ParseXMLAttributeQueryResponse ¶ added in v0.6.1
func (sp *ServiceProvider) ParseXMLAttributeQueryResponse(soapResponseXML []byte, query *AttributeQuery) (*AttributeQueryResult, error)
ParseXMLAttributeQueryResponse validates soapResponseXML, the SOAP envelope an attribute authority returned for query, and returns the attributes it carries. Use it to send query with your own transport; QueryAttributes calls it for you.
The SOAP Body must hold exactly one samlp:Response, which must:
- be InResponseTo query.ID, and recently issued;
- have Issuer equal to the IdP entity ID; Issuer may be omitted only when the Response is not signed;
- have a Success status, or else an ErrBadStatus is returned;
- either carry a valid signature by the IdP, or have every assertion signed by the IdP, in which case it must have at least one assertion;
- have no Destination, or the entity ID of this service provider. A response that comes back over the synchronous SOAP binding is not delivered to an endpoint of the service provider, so there is no URL it can be checked against; Destination is optional (saml-core §3.2.2), and a Destination naming anything else means it was meant for someone else.
Signatures are verified with the signing keys of the IdP's AttributeAuthorityDescriptor, or, if it publishes none, those of its IDPSSODescriptor (or IDPCertificate or IDPCertificateFingerprint, if set).
EncryptedAssertions, and EncryptedIDs in place of a Subject NameID, are decrypted as for login (and, with RequireSignedResponseForCBC, one encrypted in CBC mode only in a signed Response). Every assertion must be valid, or the response is rejected:
- its Issuer is the IdP entity ID, and it was recently issued;
- its Subject has a NameID identical to the one of query (saml-core §3.3.4), where an omitted Format means unspecified, and an omitted NameQualifier or SPNameQualifier means the IdP or this service provider;
- it has Conditions that are currently valid and an AudienceRestriction naming this service provider (or passes ValidateAudienceRestriction), and, with RejectUnknownConditions, no condition this package does not understand (or passes ValidateUnknownConditions);
- any SubjectConfirmationData is currently valid, and, if it has an InResponseTo, is InResponseTo query.ID.
Unlike login, no bearer SubjectConfirmation is required, and its Method and Recipient are not checked: attribute authorities typically use the sender-vouches method or none, and the assertion came straight from the IdP over a connection the service provider opened, rather than from a presenter who would have to be confirmed. This is why the result describes the subject but never authenticates it.
If ReplayCache is set, each assertion's ID is recorded in it, and an assertion it has seen before is rejected.
If the function fails it returns an *InvalidResponseError whose PrivateErr says what was wrong.
func (*ServiceProvider) ParseXMLResponse ¶
func (sp *ServiceProvider) ParseXMLResponse(decodedResponseXML []byte, possibleRequestIDs []string, currentURL url.URL) (*Assertion, error)
ParseXMLResponse parses and validates the SAML IDP response and returns the verified assertion.
This function handles decrypting the message, verifying the digital signature on the assertion, and verifying that the specified conditions and properties are met. A Subject identified by an EncryptedID is given the NameID it holds, decrypted like an EncryptedAssertion.
If the function fails it will return an InvalidResponseError whose properties are useful in describing which part of the parsing process failed. However, to discourage inadvertent disclosure the diagnostic information, the Error() method returns a static string.
func (*ServiceProvider) ParseXMLSOAPLogoutRequest ¶ added in v0.6.2
func (sp *ServiceProvider) ParseXMLSOAPLogoutRequest(soapRequestXML []byte) (*LogoutRequest, error)
ParseXMLSOAPLogoutRequest validates soapRequestXML, a SOAP 1.1 envelope whose Body holds a samlp:LogoutRequest from the IdP, and returns the request. Use it to receive LogoutRequests with your own transport; ValidateSOAPLogoutRequest calls it for you.
The request is checked as ValidateLogoutRequest checks one, except that:
- it must carry an enveloped XML signature by the IdP, verified with the IdP's signing certificates (and refused if it uses SHA-1 when RejectSHA1Signatures is set). The SOAP binding has no other signature this service provider could check, and a LogoutRequest ends sessions;
- its Destination may be omitted, since the SOAP binding does not require it (saml-core §3.2.1, saml-bindings §3.2); if present it must be SloURL.
As with the other bindings, its IssueInstant and NotOnOrAfter must be current, its Issuer must be the IdP, an EncryptedID is decrypted into NameID, and, if ReplayCache is set, its ID must not have been seen before. AllSessionIndexes returns all its SessionIndexes.
If the function fails it returns an *InvalidResponseError whose PrivateErr says what was wrong.
func (*ServiceProvider) ParseXMLSOAPLogoutResponse ¶ added in v0.6.2
func (sp *ServiceProvider) ParseXMLSOAPLogoutResponse(soapResponseXML []byte, req *LogoutRequest) (*LogoutResponse, error)
ParseXMLSOAPLogoutResponse validates soapResponseXML, the SOAP envelope the IdP returned for req, and returns the LogoutResponse it holds. Use it to send req with your own transport; SendSOAPLogoutRequest calls it for you.
The SOAP Body must hold exactly one samlp:LogoutResponse, which must:
- carry an enveloped XML signature by the IdP;
- be InResponseTo req.ID, and recently issued;
- have Issuer equal to the IdP entity ID;
- have no Destination, or SloURL or the entity ID of this service provider (a SOAP response is not delivered to an endpoint of the service provider, so Destination is optional);
- have a Success status, or else an error matching ErrBadStatus is returned.
If the function fails it returns an *InvalidResponseError whose PrivateErr says what was wrong.
func (*ServiceProvider) QueryAttributes ¶ added in v0.6.1
func (sp *ServiceProvider) QueryAttributes(ctx context.Context, nameID NameID, attributes ...Attribute) (*AttributeQueryResult, error)
QueryAttributes asks the IdP's attribute authority for the attributes of the subject identified by nameID, and returns them once the response has been validated with ParseXMLAttributeQueryResponse.
The query is made with MakeAttributeQuery and sent with the SAML SOAP binding to the IdP's SOAP AttributeService, using HTTPClient (or http.DefaultClient) and ctx. The response body is limited to MaxAttributeQueryResponseSize bytes. The AttributeService must be https unless AllowInsecureSOAPEndpoints is set.
Errors in making or sending the query are returned as they are; an invalid response is returned as an *InvalidResponseError.
func (*ServiceProvider) RedirectLogoutRequestURL ¶ added in v0.6.0
func (sp *ServiceProvider) RedirectLogoutRequestURL(req *LogoutRequest, relayState string) (*url.URL, error)
RedirectLogoutRequestURL returns the URL that sends req to its Destination with the HTTP-Redirect binding. Use it instead of MakeRedirectLogoutRequest when the request's ID is needed, for example to track the request and match it with the IDP's LogoutResponse; req is typically made by MakeLogoutRequest with the IDP's HTTP-Redirect SingleLogoutService location.
Any enveloped XML signature on req is left out of the message. If sp.SignatureMethod is set, the URL carries a query string signature instead, as the binding requires (saml-bindings-2.0-os section 3.4.4.1).
func (*ServiceProvider) SendSOAPLogoutRequest ¶ added in v0.6.2
func (sp *ServiceProvider) SendSOAPLogoutRequest(ctx context.Context, req *LogoutRequest) (*LogoutResponse, error)
SendSOAPLogoutRequest sends req, made by MakeSOAPLogoutRequest, to its Destination with the SAML SOAP binding, using HTTPClient (or http.DefaultClient) and ctx, and returns the IdP's LogoutResponse once ParseXMLSOAPLogoutResponse has validated it. The response body is limited to MaxSOAPLogoutMessageSize bytes. The Destination must be https unless AllowInsecureSOAPEndpoints is set (see ErrInsecureSOAPEndpoint).
This is SP initiated single logout without the browser. It does not end any session at this service provider: do that whatever the outcome.
Errors in sending the request are returned as they are; an invalid response, or one whose status is not Success, is returned as an *InvalidResponseError (which matches ErrBadStatus for a status other than Success). A Success with the second-level status PartialLogout is returned without error; check resp.Status if it matters.
func (*ServiceProvider) SignArtifactResolve ¶ added in v0.4.6
func (sp *ServiceProvider) SignArtifactResolve(req *ArtifactResolve) error
SignArtifactResolve adds the `Signature` element to the `ArtifactResolve`.
func (*ServiceProvider) SignAttributeQuery ¶ added in v0.6.1
func (sp *ServiceProvider) SignAttributeQuery(req *AttributeQuery) error
SignAttributeQuery adds an enveloped `Signature` element to the `AttributeQuery`, replacing any it already has. It signs with SignatureMethod or, when that is empty, with SHA-256 for the type of Key.
func (*ServiceProvider) SignAuthnRequest ¶ added in v0.4.1
func (sp *ServiceProvider) SignAuthnRequest(req *AuthnRequest) error
SignAuthnRequest adds the `Signature` element to the `AuthnRequest`.
func (*ServiceProvider) SignLogoutRequest ¶ added in v0.4.5
func (sp *ServiceProvider) SignLogoutRequest(req *LogoutRequest) error
SignLogoutRequest adds the `Signature` element to the `LogoutRequest`.
func (*ServiceProvider) SignLogoutResponse ¶ added in v0.4.5
func (sp *ServiceProvider) SignLogoutResponse(resp *LogoutResponse) error
SignLogoutResponse adds the `Signature` element to the `LogoutResponse`.
func (*ServiceProvider) SignedMetadata ¶ added in v0.6.0
func (sp *ServiceProvider) SignedMetadata() (*etree.Element, error)
SignedMetadata returns the SP metadata as an XML element carrying an enveloped signature made with Key and Certificate (saml-metadata-2.0-os §3).
It signs with SignatureMethod, or, when that is empty, with SHA-256 for the key type; signing metadata does not require request signing to be enabled. The signature references the EntityDescriptor by its ID attribute; one is generated if the metadata does not have one. The returned element must be serialized as-is: re-indenting it changes the signed content.
func (*ServiceProvider) ValidateLogoutRequest ¶ added in v0.6.0
func (sp *ServiceProvider) ValidateLogoutRequest(req *http.Request) (*LogoutRequest, error)
ValidateLogoutRequest validates a LogoutRequest sent by the IDP (IDP initiated single logout), using the HTTP-Redirect, HTTP-POST or HTTP-POST-SimpleSign binding. It returns the request only if it is valid. If the request identifies the principal with an EncryptedID rather than a NameID, it is decrypted with the service provider's decryption keys (as for encrypted assertions) and NameID is set to the result. A request whose principal is a BaseID is refused unless AcceptLogoutRequestBaseID is set; its NameID is then nil. All the request's SessionIndexes are returned by its AllSessionIndexes method.
The request must be signed by the IDP. With the HTTP-Redirect binding that is either a query string signature (SigAlg and Signature parameters) or an enveloped XML signature; with the HTTP-POST binding it is an enveloped XML signature. A posted form that carries a SigAlg or Signature field is an HTTP-POST-SimpleSign message and must have a valid SimpleSign signature (an enveloped XML signature it also carries must be valid too).
If ReplayCache is set, the request's ID is recorded in it once the request is otherwise valid, and a request whose ID is already recorded is refused.
The caller should end the session identified by the returned request's NameID (and SessionIndex, if present) and then answer the IDP, for example with MakeRedirectLogoutResponse(req.ID, relayState).
func (*ServiceProvider) ValidateLogoutRequestForm ¶ added in v0.6.0
func (sp *ServiceProvider) ValidateLogoutRequestForm(postFormData string) (*LogoutRequest, error)
ValidateLogoutRequestForm validates a LogoutRequest received via the HTTP-POST binding. postFormData is the value of the SAMLRequest form field. It returns the request only if it is valid.
func (*ServiceProvider) ValidateLogoutResponseForm
deprecated
added in
v0.4.0
func (sp *ServiceProvider) ValidateLogoutResponseForm(postFormData string) error
ValidateLogoutResponseForm returns a nil error if the logout response is valid.
It does not check the response's InResponseTo; see ParseLogoutResponse.
Deprecated: use ParseLogoutResponse, which reads the form from the request and also checks the response's InResponseTo.
func (*ServiceProvider) ValidateLogoutResponseRedirect
deprecated
added in
v0.4.0
func (sp *ServiceProvider) ValidateLogoutResponseRedirect(queryParameterData string) error
ValidateLogoutResponseRedirect returns a nil error if the logout response is valid. queryParameterData is the URL-decoded value of the SAMLResponse query parameter.
Because it only receives the SAMLResponse value, this method cannot check a query string signature and therefore requires the response to carry an enveloped XML signature. Most IDPs sign HTTP-Redirect binding messages with a query string signature instead (as saml-bindings-2.0-os section 3.4.4.1 requires); use ValidateLogoutResponseRequest to accept those.
It does not check the response's InResponseTo; see ParseLogoutResponse.
Deprecated: use ParseLogoutResponse, which also accepts query string signatures and checks the response's InResponseTo.
URL Binding appears to be gzip / flate encoded See https://www.oasis-open.org/committees/download.php/20645/sstc-saml-tech-overview-2%200-draft-10.pdf 6.6
func (*ServiceProvider) ValidateLogoutResponseRequest
deprecated
added in
v0.4.0
func (sp *ServiceProvider) ValidateLogoutResponseRequest(req *http.Request) error
ValidateLogoutResponseRequest validates the LogoutResponse content from the request, which may use the HTTP-Redirect, HTTP-POST or HTTP-POST-SimpleSign binding.
With the HTTP-Redirect binding the response must be signed, either with a query string signature (SigAlg and Signature parameters) or with an enveloped XML signature. A posted form that carries a SigAlg or Signature field is an HTTP-POST-SimpleSign message and must have a valid SimpleSign signature; an enveloped XML signature it also carries must be valid too.
It does not check the response's InResponseTo against the LogoutRequest this service provider sent; use ParseLogoutResponse for that.
Deprecated: use ParseLogoutResponse, which also checks that the response answers a LogoutRequest this service provider sent, so that a LogoutResponse cannot be replayed or delivered unsolicited.
func (*ServiceProvider) ValidateSOAPLogoutRequest ¶ added in v0.6.2
func (sp *ServiceProvider) ValidateSOAPLogoutRequest(r *http.Request) (*LogoutRequest, error)
ValidateSOAPLogoutRequest validates a LogoutRequest the IdP sent to the SingleLogoutService of this service provider with the SAML SOAP binding (back-channel single logout, saml-profiles §4.4). r must be a POST with Content-Type text/xml (see IsSOAPRequest), and its body, at most MaxSOAPLogoutMessageSize bytes, is checked with ParseXMLSOAPLogoutRequest.
On success, end the sessions the request names, then answer it with MakeSOAPLogoutResponse and WriteSOAPLogoutResponse. On failure, which is an *InvalidResponseError, answer with WriteSOAPFault: an unauthenticated request must not be answered with a signed LogoutResponse.
type ServiceProviderProvider ¶
type ServiceProviderProvider interface {
// GetServiceProvider returns the Service Provider metadata for the
// service provider ID, which is typically the service provider's
// metadata URL. If an appropriate service provider cannot be found then
// the returned error must be os.ErrNotExist.
GetServiceProvider(r *http.Request, serviceProviderID string) (*EntityDescriptor, error)
}
ServiceProviderProvider is an interface used by IdentityProvider to look up service provider metadata for a request.
type Session ¶
type Session struct {
ID string
CreateTime time.Time
ExpireTime time.Time
Index string
NameID string
NameIDFormat string
SubjectID string
Groups []string
UserName string
UserEmail string
UserCommonName string
UserSurname string
UserGivenName string
UserScopedAffiliation string
EduPersonPrincipalName string `json:",omitempty"`
// AuthnContextClassRef is the authentication context class the user
// was actually authenticated with, such as
// "urn:oasis:names:tc:SAML:2.0:ac:classes:X509". DefaultAssertionMaker
// asserts it in the AuthnStatement. When empty, PasswordProtectedTransport
// is asserted, as before. See IdentityProvider.EnforceRequestedAuthnContext.
AuthnContextClassRef string `json:",omitempty"`
CustomAttributes []Attribute
}
Session represents a user session. It is returned by the SessionProvider implementation's GetSession method. Fields here are used to set fields in the SAML assertion.
type SessionIndex ¶ added in v0.4.0
type SessionIndex struct {
Value string `xml:",chardata"`
}
SessionIndex represents the SAML element SessionIndex.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §3.7.1
func (*SessionIndex) Element ¶ added in v0.4.0
func (s *SessionIndex) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type SessionInvalidator ¶ added in v0.6.1
type SessionInvalidator interface {
InvalidateSession(w http.ResponseWriter, r *http.Request, req *IdpLogoutRequest) error
}
SessionInvalidator is an optional interface that a SessionProvider may implement to support single logout. When IdentityProvider.ServeSLO has validated a LogoutRequest from a service provider, it calls InvalidateSession if the SessionProvider implements this interface.
InvalidateSession must terminate the IdP session (or sessions) that req refers to. Use req.MatchesSession to decide whether a Session is one of them: its NameID must be the request's NameID and, if the request carries SessionIndexes, its Index must be one of them. If the IdP's AcceptLogoutRequestBaseID is set, the request may instead identify the principal with req.Request.BaseID, leaving req.Request.NameID nil; then MatchesSession matches no session. Ending no session, for example because the user is already logged out, is not an error.
A LogoutRequest received with the SOAP binding (req.Binding is SOAPBinding) comes from the service provider's server, so r carries no cookie of the user: InvalidateSession must then find the sessions to end among those it stores, with req.MatchesSession. Only accept that binding (by adding SOAPBinding to IdentityProvider.LogoutBindings) if it can.
InvalidateSession may set headers on w, for example to expire a session cookie, but must not write the status line or a body: ServeSLO writes the LogoutResponse afterwards. If it returns an error, ServeSLO logs it and answers the service provider with a LogoutResponse whose status is StatusResponder.
type SessionParticipant ¶ added in v0.6.2
type SessionParticipant struct {
// ServiceProviderID is the entity ID of the service provider, as
// passed to ServiceProviderProvider.GetServiceProvider.
ServiceProviderID string
// NameID is the NameID of the assertion issued to the service provider,
// and SessionIndex the SessionIndex of its AuthnStatement (empty if it
// had none). The LogoutRequest sent to the service provider carries
// them.
NameID NameID
SessionIndex string
}
SessionParticipant is a service provider that an IdP session was used to log in to: a session participant in the sense of saml-profiles-2.0-os §4.4. The IdP records one each time it issues an assertion for the session, and sends it a LogoutRequest when the session is logged out.
type SessionParticipantTracker ¶ added in v0.6.2
type SessionParticipantTracker interface {
// AddSessionParticipant records that an assertion for session was
// issued to participant. Recording the same participant twice should
// not make it appear twice.
AddSessionParticipant(r *http.Request, session *Session, participant SessionParticipant) error
// SessionParticipants returns the participants recorded for every
// session for which match returns true. ServeSLO calls it before it
// ends the sessions (see SessionInvalidator), with
// IdpLogoutRequest.MatchesSession; StartLogout calls it with a function
// that matches its session by ID.
SessionParticipants(r *http.Request, match func(*Session) bool) ([]SessionParticipant, error)
}
SessionParticipantTracker is an optional interface that a SessionProvider may implement to record the service providers each IdP session is used for, which single logout needs to propagate a logout to all of them (saml-profiles-2.0-os §4.4.3.3 and §4.4.4.2).
If the SessionProvider implements it:
- ServeSSO and ServeIDPInitiated call AddSessionParticipant before sending an assertion. If it fails, the assertion is not sent.
- StartLogout (IdP-initiated logout) sends a LogoutRequest to every participant of the session.
- ServeSLO, for a LogoutRequest from a service provider, sends a LogoutRequest to every other participant of the sessions it ends before it answers the service provider.
Without it, ServeSLO only ends the IdP session, and StartLogout contacts no service provider.
type SessionProvider ¶
type SessionProvider interface {
// GetSession returns the remote user session associated with the http.Request.
//
// If (and only if) the request is not associated with a session then GetSession
// must complete the HTTP request and return nil.
// To answer the request with a SAML error Response instead, for example
// an IsPassive request when it would have to prompt the user, it can
// call IdentityProvider.SendErrorResponse and return nil.
GetSession(w http.ResponseWriter, r *http.Request, req *IdpAuthnRequest) *Session
}
SessionProvider is an interface used by IdentityProvider to determine the Session associated with a request. For an example implementation, see GetSession in the samlidp package.
IdentityProvider does not act on the ForceAuthn and IsPassive attributes of the AuthnRequest (req.Request.ForceAuthn and req.Request.IsPassive): implementations are responsible for honouring them (saml-core §3.4.1, saml-profiles §4.1.3.4).
- ForceAuthn="true": the user must be authenticated directly, so an existing session must not be returned. Authenticate the user again and return a session whose CreateTime, which becomes the assertion's AuthnInstant, is the time of that new authentication.
- IsPassive="true": the identity provider must not visibly interact with the user. If a usable session exists, return it as usual. Otherwise do not prompt the user; answer with a SAML error Response with the status StatusResponder and the second-level status StatusNoPassive, by calling IdentityProvider.SendErrorResponse with a *StatusError, and return nil. This also applies when ForceAuthn is "true" as well and the user cannot be authenticated again without interaction.
type ShibbolethScope ¶ added in v0.6.0
type ShibbolethScope struct {
XMLName xml.Name `xml:"urn:mace:shibboleth:metadata:1.0 Scope"`
Regexp bool `xml:"regexp,attr"`
Value string `xml:",chardata"`
}
ShibbolethScope represents the shibmd:Scope metadata extension element. An identity provider uses it to list the security domains (scopes) it is authoritative for, such as the "example.com" in a scoped attribute value like "staff@example.com". When Regexp is true, Value is a regular expression rather than a literal scope.
See https://shibboleth.atlassian.net/wiki/spaces/SC/pages/1912406916/ShibMetaExt
type SignatureVerifier ¶ added in v0.4.0
type SignatureVerifier interface {
VerifySignature(validationContext *dsig.ValidationContext, el *etree.Element) error
}
SignatureVerifier verifies a signature
Can be implemented in order to override ServiceProvider's default way of verifying signatures.
type SignedElementVerifier ¶ added in v0.6.2
type SignedElementVerifier interface {
SignatureVerifier
VerifySignedElement(validationContext *dsig.ValidationContext, el *etree.Element) (*etree.Element, error)
}
SignedElementVerifier is a SignatureVerifier that also returns what the signature covers: the element without its Signature, as dsig's ValidationContext.Validate returns it. When the ServiceProvider's SignatureVerifier implements it, the service provider reads the signed message from the element it returns rather than from the message as received. A SignatureVerifier that does not implement it keeps the old behaviour: the message is read as received.
type SigningMethod ¶ added in v0.6.0
type SigningMethod struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:metadata:algsupport SigningMethod"`
Algorithm string `xml:"Algorithm,attr"`
MinKeySize int `xml:"MinKeySize,attr,omitempty"`
MaxKeySize int `xml:"MaxKeySize,attr,omitempty"`
}
SigningMethod represents the alg:SigningMethod element: an XML Signature algorithm the entity supports, with optional bounds on the key size, in bits, it supports for that algorithm.
See https://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-metadata-algsupport-v1.0-cs01.html §2.4
type Status ¶
type Status struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"`
StatusCode StatusCode
StatusMessage *StatusMessage
StatusDetail *StatusDetail
}
Status represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
type StatusCode ¶
type StatusCode struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol StatusCode"`
Value string `xml:",attr"`
StatusCode *StatusCode
}
StatusCode represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*StatusCode) Element ¶
func (s *StatusCode) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type StatusDetail ¶
StatusDetail represents the SAML element StatusDetail.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §3.2.2.4
func (StatusDetail) Element ¶
func (sm StatusDetail) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (StatusDetail) MarshalXML ¶ added in v0.6.0
func (sm StatusDetail) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler, writing Children as XML.
encoding/xml cannot marshal an *etree.Element itself, so without this method the children were written as their struct fields.
func (*StatusDetail) UnmarshalXML ¶ added in v0.6.0
func (sm *StatusDetail) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler, reading every child element into Children. Text between the children is ignored.
Each child keeps its prefixes. Namespaces declared on StatusDetail are declared again on each child, which no longer has StatusDetail as a parent. A prefix declared further out cannot be recovered and is replaced by a generated one bound to the same namespace.
type StatusError ¶ added in v0.6.2
type StatusError struct {
// TopLevel is the top-level status code: StatusRequester,
// StatusResponder or StatusVersionMismatch (saml-core §3.2.2.2).
TopLevel string
// SecondLevel, if not empty, is the second-level status code nested in
// the top-level one, such as StatusNoPassive, StatusNoAuthnContext,
// StatusRequestDenied or StatusInvalidNameIDPolicy.
SecondLevel string
// Message, if not empty, is sent as the <StatusMessage>. It is read by
// the service provider, so it should not reveal anything the service
// provider should not know.
Message string
}
StatusError is an error that asks the IdentityProvider to answer an AuthnRequest with a SAML <Response> carrying an error <Status> and no assertion, as saml-core §3.4.1.4 requires when the identity provider cannot or will not authenticate the principal as requested (for example Responder with NoPassive for an IsPassive request it cannot satisfy without a login prompt, or Responder with NoAuthnContext).
When an AssertionMaker returns a *StatusError (possibly wrapped), ServeSSO and ServeIDPInitiated send that Response to the assertion consumer service instead of responding with HTTP 500. A SessionProvider can send one itself with IdentityProvider.SendErrorResponse, and then return nil.
func (*StatusError) Error ¶ added in v0.6.2
func (e *StatusError) Error() string
Error implements error.
type StatusMessage ¶
type StatusMessage struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol StatusMessage"`
Value string `xml:",chardata"`
}
StatusMessage represents the SAML element StatusMessage.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §3.2.2.3
func (StatusMessage) Element ¶
func (sm StatusMessage) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type Subject ¶
type Subject struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion Subject"`
// BaseID is the saml:BaseID element (saml-core §2.2.3) that identifies
// the subject in place of NameID, or nil. It is kept as an element
// because the content of a BaseID is defined by its xsi:type extension,
// which this package does not interpret. It is set either as read, or
// by decrypting an EncryptedID that holds a BaseID. The service
// provider refuses an assertion whose Subject is a BaseID unless
// ServiceProvider.AcceptAssertionBaseID is set.
BaseID *etree.Element `xml:"urn:oasis:names:tc:SAML:2.0:assertion BaseID"`
NameID *NameID `xml:"urn:oasis:names:tc:SAML:2.0:assertion NameID"`
// EncryptedID is the saml:EncryptedID element (saml-core §2.2.4) that
// identifies the subject in place of NameID, as received.
//
// When the service provider accepts an assertion whose Subject has an
// EncryptedID, it decrypts it with its decryption keys and sets NameID
// to the NameID it holds (or BaseID to the BaseID it holds), then
// clears EncryptedID.
EncryptedID *etree.Element `xml:"urn:oasis:names:tc:SAML:2.0:assertion EncryptedID"`
SubjectConfirmations []SubjectConfirmation `xml:"urn:oasis:names:tc:SAML:2.0:assertion SubjectConfirmation"`
}
Subject represents the SAML element Subject.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.4.1
func (*Subject) MarshalXML ¶ added in v0.6.2
MarshalXML implements xml.Marshaler
func (*Subject) UnmarshalXML ¶ added in v0.6.2
UnmarshalXML implements xml.Unmarshaler
type SubjectConfirmation ¶
type SubjectConfirmation struct {
Method string `xml:",attr"`
// BaseID *BaseID ... TODO
NameID *NameID `xml:"urn:oasis:names:tc:SAML:2.0:assertion NameID"`
// EncryptedID is the saml:EncryptedID element (saml-core §2.2.4) that
// identifies the confirming entity in place of NameID, as received. The
// service provider decrypts it into NameID, as for Subject.EncryptedID.
EncryptedID *etree.Element `xml:"urn:oasis:names:tc:SAML:2.0:assertion EncryptedID"`
SubjectConfirmationData *SubjectConfirmationData `xml:"urn:oasis:names:tc:SAML:2.0:assertion SubjectConfirmationData"`
}
SubjectConfirmation represents the SAML element SubjectConfirmation.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.4.1.1
func (*SubjectConfirmation) Element ¶
func (a *SubjectConfirmation) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*SubjectConfirmation) MarshalXML ¶ added in v0.6.2
func (a *SubjectConfirmation) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*SubjectConfirmation) UnmarshalXML ¶ added in v0.6.2
func (a *SubjectConfirmation) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type SubjectConfirmationData ¶
type SubjectConfirmationData struct {
NotBefore time.Time `xml:",attr"`
NotOnOrAfter time.Time `xml:",attr"`
Recipient string `xml:",attr"`
InResponseTo string `xml:",attr"`
Address string `xml:",attr"`
}
SubjectConfirmationData represents the SAML element SubjectConfirmationData.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.4.1.2
func (*SubjectConfirmationData) Element ¶
func (s *SubjectConfirmationData) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*SubjectConfirmationData) MarshalXML ¶
func (s *SubjectConfirmationData) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*SubjectConfirmationData) UnmarshalXML ¶
func (s *SubjectConfirmationData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type SubjectLocality ¶
SubjectLocality represents the SAML element SubjectLocality.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.2.1
func (*SubjectLocality) Element ¶
func (a *SubjectLocality) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type X509Certificate ¶ added in v0.4.6
type X509Certificate struct {
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Certificate"`
Data string `xml:",chardata"`
}
X509Certificate represents the XMLSEC object of the same name
type X509Data ¶ added in v0.4.6
type X509Data struct {
XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Data"`
X509Certificates []X509Certificate `xml:"X509Certificate"`
}
X509Data represents the XMLSEC object of the same name
Source Files
¶
- artifact.go
- duration.go
- encrypted_id.go
- errors.go
- etree_xml.go
- flate.go
- identity_provider.go
- identity_provider_authn_context.go
- identity_provider_error_response.go
- identity_provider_logout.go
- identity_provider_logout_propagation.go
- identity_provider_logout_soap.go
- identity_provider_logout_soap_request.go
- identity_provider_nameid.go
- identity_provider_request_subject.go
- metadata.go
- metadata_verify.go
- redirect_binding.go
- saml.go
- saml_gen.go
- schema.go
- service_provider.go
- service_provider_attribute_query.go
- service_provider_soap_logout.go
- sha1_policy.go
- signature_reference.go
- simplesign_binding.go
- simplesign_idp.go
- soap.go
- time.go
- unmarshal_untrusted.go
- util.go
Directories
¶
| Path | Synopsis |
|---|---|
|
This is an example that implements a bitly-esque short link service.
|
This is an example that implements a bitly-esque short link service. |
|
idp
command
Package main contains an example identity provider implementation.
|
Package main contains an example identity provider implementation. |
|
trivial
command
Package main contains an example service provider implementation.
|
Package main contains an example service provider implementation. |
|
internal
|
|
|
signerutil
Package signerutil contains helpers for working with crypto.Signer values.
|
Package signerutil contains helpers for working with crypto.Signer values. |
|
xmlroundtrip
Package xmlroundtrip rejects XML documents that encoding/xml would change if it decoded and re-encoded them.
|
Package xmlroundtrip rejects XML documents that encoding/xml would change if it decoded and re-encoded them. |
|
Package logger provides a logging interface.
|
Package logger provides a logging interface. |
|
Package samlidp a rudimentary SAML identity provider suitable for testing or as a starting point for a more complex service.
|
Package samlidp a rudimentary SAML identity provider suitable for testing or as a starting point for a more complex service. |
|
Package samlsp provides helpers that can be used to protect web services using SAML.
|
Package samlsp provides helpers that can be used to protect web services using SAML. |
|
Package testsaml contains functions for use in testing SAML requests and responses.
|
Package testsaml contains functions for use in testing SAML requests and responses. |
|
Package xmlenc is a partial implementation of the xmlenc standard as described in https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html.
|
Package xmlenc is a partial implementation of the xmlenc standard as described in https://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html. |