saml

package module
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Jan 24, 2022 License: BSD-2-Clause Imports: 28 Imported by: 0

README

SAML

Build Status

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.

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.

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.id, an identity provider designed for testing.

package main

import (
	"context"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"net/http"
	"net/url"

	"github.com/JBake/saml/samlsp"
)

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s!", samlsp.AttributeFromContext(r.Context(), "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://samltest.id/saml/idp")
	if err != nil {
		panic(err) // TODO handle error
	}
	idpMetadata, err := samlsp.FetchMetadata(context.Background(), http.DefaultClient,
		*idpMetadataURL)
	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,
		IDPMetadata: idpMetadata,
	})
	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. For samltest.id, you can do something like:

mdpath=saml-test-$USER-$HOST.xml
curl localhost:8000/saml/metadata > $mdpath

Navigate to https://samltest.id/upload.php and upload the file you fetched.

Now you should be able to authenticate. The flow should look like this:

  1. You browse to localhost:8000/hello

  2. The middleware redirects you to https://samltest.id/idp/profile/SAML2/Redirect/SSO

  3. samltest.id prompts you for a username and password.

  4. samltest.id 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.

  5. The local service validates the response, issues a session cookie, and redirects you to the original URL, localhost:8000/hello.

  6. 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.

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.

The package can produce signed SAML assertions, and can validate both signed and encrypted SAML assertions. It does not support signed or encrypted requests.

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):

SAMLtest is a testing ground for SAML service and identity 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). If your issue is not a security issue, please use the issue tracker so other contributors can help.

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 assign a custom CookieRequestTracker or CookieSessionProvider - `CookieName` - Instead assign a custom CookieRequestTracker or CookieSessionProvider - `CookieDomain` - Instead assign a custom CookieRequestTracker or CookieSessionProvider - `CookieDomain` - Instead assign a custom CookieRequestTracker or CookieSessionProvider

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.id](https://samltest.id/), an identity provider designed for testing.

```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://samltest.id/saml/idp")
	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. For [samltest.id](https://samltest.id/), you can do something like:

mdpath=saml-test-$USER-$HOST.xml
curl localhost:8000/saml/metadata > $mdpath

Navigate to https://samltest.id/upload.php and upload the file you fetched.

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://samltest.id/idp/profile/SAML2/Redirect/SSO`

1. samltest.id prompts you for a username and password.

1. samltest.id 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.

The package can produce signed SAML assertions, and can validate both signed and encrypted SAML assertions. It does not support signed or encrypted requests.

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://samltest.id/) is a testing ground for SAML service and identity 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

View Source
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"

	// 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"
)
View Source
const DefaultCacheDuration = time.Hour * 24 * 1

DefaultCacheDuration is how long we ask the IDP to cache the SP metadata.

View Source
const DefaultValidDuration = time.Hour * 24 * 2

DefaultValidDuration is how long we assert that the SP metadata is valid.

View Source
const HTTPPostBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"

HTTPPostBinding is the official URN for the HTTP-POST binding (transport)

View Source
const HTTPRedirectBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"

HTTPRedirectBinding is the official URN for the HTTP-Redirect binding (transport)

Variables

View Source
var Clock *dsig.Clock

Clock is assigned to dsig validation and signing contexts if it is not nil, otherwise the default clock is used.

View Source
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).

View Source
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).

View Source
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.

View Source
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.

View Source
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.

View Source
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 GetSigningContext

func GetSigningContext(sp *ServiceProvider) (*dsig.SigningContext, error)

GetSigningContext returns a dsig.SigningContext initialized based on the Service Provider's configuration

Types

type AffiliationDescriptor

type AffiliationDescriptor struct {
	AffiliationOwnerID string        `xml:"affiliationOwnerID,attr"`
	ID                 string        `xml:",attr"`
	ValidUntil         time.Time     `xml:"validUntil,attr,omitempty"`
	CacheDuration      time.Duration `xml:"cacheDuration,attr"`
	Signature          *etree.Element
	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

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
	// Advice *Advice
	// Statements []Statement
	AuthnStatements []AuthnStatement `xml:"AuthnStatement"`
	// AuthzDecisionStatements []AuthzDecisionStatement
	AttributeStatements []AttributeStatement `xml:"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) Element

func (a *Assertion) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

func (*Assertion) UnmarshalXML

func (a *Assertion) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML implements xml.Unmarshaler

type AssertionAttribute

type AssertionAttribute struct {
	FriendlyName string
	Name         string
	Value        string
}

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

Get returns the assertion attribute whose Name or FriendlyName matches name, or nil if no matching attribute is found.

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 Attribute

type Attribute struct {
	FriendlyName string           `xml:",attr"`
	Name         string           `xml:",attr"`
	NameFormat   string           `xml:",attr"`
	Values       []AttributeValue `xml:"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

func (*Attribute) Element

func (a *Attribute) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

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

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 AttributeStatement

type AttributeStatement struct {
	Attributes []Attribute `xml:"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"`
	Value  string `xml:",chardata"`
	NameID *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

func (*Audience) Element

func (a *Audience) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

type AudienceRestriction

type AudienceRestriction struct {
	Audience Audience
}

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

func (*AudienceRestriction) Element

func (a *AudienceRestriction) 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

type AuthnContext

type AuthnContext struct {
	AuthnContextClassRef *AuthnContextClassRef
}

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

	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 Element returns an etree.Element representing the object in XML form.

func (*AuthnRequest) MarshalXML

func (r *AuthnRequest) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML implements xml.Marshaler

func (*AuthnRequest) Post

func (req *AuthnRequest) Post(relayState string) []byte

Post returns an HTML form suitable for using the HTTP-POST binding with the request

func (*AuthnRequest) Redirect

func (req *AuthnRequest) Redirect(relayState string, sp *ServiceProvider) (*url.URL, error)

Redirect returns a URL suitable for using the redirect binding with the request

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
	AuthnContext        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:"AudienceRestriction"`
	OneTimeUse           *OneTimeUse
	ProxyRestriction     *ProxyRestriction
}

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
	GivenName        string
	SurName          string
	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 Duration

type Duration time.Duration

Duration is a time.Duration that uses the xsd:duration format for text marshalling and unmarshalling.

func (Duration) MarshalText

func (d Duration) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface.

func (*Duration) UnmarshalText

func (d *Duration) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

type EncryptionMethod

type EncryptionMethod struct {
	Algorithm string `xml:"Algorithm,attr"`
}

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

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
	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

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
	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                 *ContactPerson
	AdditionalMetadataLocations   []string `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, start 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

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

func (e ErrBadStatus) Error() string

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"`
	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

type IdentityProvider

type IdentityProvider struct {
	Key                     crypto.PrivateKey
	Logger                  logger.Interface
	Certificate             *x509.Certificate
	Intermediates           []*x509.Certificate
	MetadataURL             url.URL
	SSOURL                  url.URL
	LogoutURL               url.URL
	ServiceProviderProvider ServiceProviderProvider
	SessionProvider         SessionProvider
	AssertionMaker          AssertionMaker
	SignatureMethod         string
	ValidDuration           *time.Duration
}

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) Handler

func (idp *IdentityProvider) Handler() http.Handler

Handler returns an http.Handler that serves the metadata and SSO URLs

func (*IdentityProvider) Metadata

func (idp *IdentityProvider) Metadata() *EntityDescriptor

Metadata returns the metadata structure for this identity provider.

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.

func (*IdentityProvider) ServeMetadata

func (idp *IdentityProvider) ServeMetadata(w http.ResponseWriter, r *http.Request)

ServeMetadata is an http.HandlerFunc that serves the IDP metadata

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.

If the assertion cannot be created or returned, a StatusInternalServerError response is sent.

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
}

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.

func (*IdpAuthnRequest) MakeAssertionEl

func (req *IdpAuthnRequest) MakeAssertionEl() error

MakeAssertionEl sets `AssertionEl` to a signed, possibly encrypted, version of `Assertion`.

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) 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.

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.

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

type InvalidResponseError

type InvalidResponseError struct {
	PrivateErr error
	Response   string
	Now        time.Time
}

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

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

func (*Issuer) Element

func (a *Issuer) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

type KeyDescriptor

type KeyDescriptor struct {
	Use               string             `xml:"use,attr"`
	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"`
	Certificate string   `xml:"X509Data>X509Certificate"`
}

KeyInfo represents the XMLSEC object of the same name

TODO(ross): revisit xmldsig and make this type more complete

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"`
	Destination  string    `xml:",attr"`
	Issuer       *Issuer   `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
	NameID       *NameID
	Signature    *etree.Element

	SessionIndex *SessionIndex `xml:"SessionIndex"`
}

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) Bytes

func (r *LogoutRequest) Bytes() ([]byte, error)

Bytes returns a byte array representation of the LogoutRequest

func (*LogoutRequest) Deflate

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, start xml.StartElement) error

MarshalXML implements xml.Marshaler

func (*LogoutRequest) Post

func (req *LogoutRequest) Post(relayState string) []byte

Post returns an HTML form suitable for using the HTTP-POST binding with the request

func (*LogoutRequest) Redirect

func (req *LogoutRequest) Redirect(relayState string) *url.URL

Redirect returns a URL suitable for using the redirect binding with the request

func (*LogoutRequest) UnmarshalXML

func (r *LogoutRequest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML implements xml.Unmarshaler

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, start xml.StartElement) error

MarshalXML implements xml.Marshaler

func (*LogoutResponse) Post

func (resp *LogoutResponse) Post(relayState string) []byte

Post returns an HTML form suitable for using the HTTP-POST binding with the LogoutResponse.

func (*LogoutResponse) Redirect

func (resp *LogoutResponse) Redirect(relayState string) *url.URL

Redirect returns a URL suitable for using the redirect binding with the LogoutResponse.

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

func (*NameID) Element

func (a *NameID) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

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

type ProxyRestriction

type ProxyRestriction struct {
	Count     *int
	Audiences []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

type RelaxedTime time.Time

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

type RequestedAttribute struct {
	Attribute
	IsRequired *bool `xml:"isRequired,attr"`
}

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 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) Element

func (r *Response) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

func (*Response) MarshalXML

func (r *Response) MarshalXML(e *xml.Encoder, start xml.StartElement) error

MarshalXML implements xml.Marshaler

func (*Response) UnmarshalXML

func (r *Response) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

UnmarshalXML implements xml.Unmarshaler

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
	KeyDescriptors             []KeyDescriptor `xml:"KeyDescriptor,omitempty"`
	Organization               *Organization   `xml:"Organization,omitempty"`
	ContactPeople              []ContactPerson `xml:"ContactPerson,omitempty"`
}

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

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 ServiceProvider

type ServiceProvider struct {
	// Entity ID is optional - if not specified then MetadataURL will be used
	EntityID string

	// Key is the RSA private key we use to sign requests.
	Key *rsa.PrivateKey

	// Certificate is the RSA public part of Key.
	Certificate   *x509.Certificate
	Intermediates []*x509.Certificate

	// 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

	// 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

	// AuthnNameIDFormat is the format used in the NameIDPolicy for
	// authentication requests
	AuthnNameIDFormat NameIDFormat

	// MetadataValidDuration is a duration used to calculate validUntil
	// attribute in the metadata endpoint
	MetadataValidDuration time.Duration

	// ForceAuthn allows you to force re-authentication of users even if the user
	// has a SSO session at the IdP.
	ForceAuthn *bool

	// AllowIdpInitiated
	AllowIDPInitiated bool

	// 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
	SignatureMethod string
}

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) 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 or HTTPPostBinding)

func (*ServiceProvider) MakeAuthenticationRequest

func (sp *ServiceProvider) MakeAuthenticationRequest(idpURL string, binding 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) (*LogoutRequest, error)

MakeLogoutRequest produces a new LogoutRequest object for idpURL.

func (*ServiceProvider) MakeLogoutResponse

func (sp *ServiceProvider) MakeLogoutResponse(idpURL, logoutRequestID string) (*LogoutResponse, error)

MakeLogoutResponse produces a new LogoutResponse object for idpURL and logoutRequestID.

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

func (sp *ServiceProvider) MakePostLogoutRequest(nameID, relayState string) ([]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

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) (*url.URL, error)

MakeRedirectLogoutRequest 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) MakeRedirectLogoutResponse

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.

func (*ServiceProvider) Metadata

func (sp *ServiceProvider) Metadata() *EntityDescriptor

Metadata returns the service provider metadata

func (*ServiceProvider) ParseResponse

func (sp *ServiceProvider) ParseResponse(req *http.Request, possibleRequestIDs []string) (*Assertion, error)

ParseResponse extracts the SAML IDP response received in req, validates it, and returns the verified assertion.

func (*ServiceProvider) ParseXMLResponse

func (sp *ServiceProvider) ParseXMLResponse(decodedResponseXML []byte, possibleRequestIDs []string) (*Assertion, error)

ParseXMLResponse 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.

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) SignAuthnRequest

func (sp *ServiceProvider) SignAuthnRequest(req *AuthnRequest) error

SignAuthnRequest adds the `Signature` element to the `AuthnRequest`.

func (*ServiceProvider) SignLogoutRequest

func (sp *ServiceProvider) SignLogoutRequest(req *LogoutRequest) error

SignLogoutRequest adds the `Signature` element to the `LogoutRequest`.

func (*ServiceProvider) SignLogoutResponse

func (sp *ServiceProvider) SignLogoutResponse(resp *LogoutResponse) error

SignLogoutResponse adds the `Signature` element to the `LogoutResponse`.

func (*ServiceProvider) ValidateLogoutResponseForm

func (sp *ServiceProvider) ValidateLogoutResponseForm(postFormData string) error

ValidateLogoutResponseForm returns a nil error if the logout response is valid.

func (*ServiceProvider) ValidateLogoutResponseRedirect

func (sp *ServiceProvider) ValidateLogoutResponseRedirect(queryParameterData string) error

ValidateLogoutResponseRedirect returns a nil error if the logout response is valid.

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

func (sp *ServiceProvider) ValidateLogoutResponseRequest(req *http.Request) error

ValidateLogoutResponseRequest validates the LogoutResponse content from the request

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
	Groups                []string
	UserName              string
	UserEmail             string
	UserCommonName        string
	UserSurname           string
	UserGivenName         string
	UserScopedAffiliation string

	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

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

func (s *SessionIndex) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

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.
	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.

type SignatureVerifier

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 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

func (*Status) Element

func (s *Status) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

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

type StatusDetail struct {
	Children []*etree.Element
}

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.

type StatusMessage

type StatusMessage struct {
	Value string
}

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               *BaseID  ... TODO
	NameID *NameID
	// EncryptedID          *EncryptedID  ... TODO
	SubjectConfirmations []SubjectConfirmation `xml:"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) Element

func (a *Subject) Element() *etree.Element

Element returns an etree.Element representing the object in XML form.

type SubjectConfirmation

type SubjectConfirmation struct {
	Method string `xml:",attr"`
	// BaseID               *BaseID  ... TODO
	NameID *NameID
	// EncryptedID          *EncryptedID  ... TODO
	SubjectConfirmationData *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.

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

type SubjectLocality struct {
	Address string `xml:",attr"`
	DNSName string `xml:",attr"`
}

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.

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
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 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.

Jump to

Keyboard shortcuts

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