saml

package module
v0.0.0-...-c9be13b Latest Latest
Warning

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

Go to latest
Published: Apr 11, 2017 License: BSD-2-Clause Imports: 17 Imported by: 2

README

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.

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 appliation to protect. We'll modify this application so it uses SAML to authenticate users.

package main

import "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 testshib.org, an identity provider designed for testing.

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"

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

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", r.Header.Get("X-Saml-Cn"))
}

func main() {
    key, _ := ioutil.ReadFile("myservice.key")
    cert, _ := ioutil.ReadFile("myservice.cert")
    samlSP, _ := samlsp.New(samlsp.Options{
        IDPMetadataURL: "https://www.testshib.org/metadata/testshib-providers.xml",
        URL:            "http://localhost:8000",
        Key:            string(key),
        Certificate:    string(cert),
    })
    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 identiy provider to establish trust from the service provider to the IDP. For testshib.org, you can do something like:

mdpath=saml-test-$USER-$HOST.xml
curl localhost:8000/saml/metadata > $mdpath
curl -i -F userfile=@$mdpath https://www.testshib.org/procupload.php

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://idp.testshib.org/idp/profile/SAML2/Redirect/SSO

  3. testshib.org prompts you for a username and password.

  4. testshib.org 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 examples/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 fromthe IDP to the service provider are supported vai the HTTP POST binding.

The package supports 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 originaly 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):

TestShib 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 8EA205C01C425FF195A5E9A43FA0768F26FD2554).

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.

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 appliation to protect. We'll modify this application so it uses SAML to authenticate users.

package main

import "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 [testshib.org](testshib.org), an identity provider designed for testing.

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"

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

func hello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %s!", r.Header.Get("X-Saml-Cn"))
}

func main() {
    key, _ := ioutil.ReadFile("myservice.key")
    cert, _ := ioutil.ReadFile("myservice.cert")
    samlSP, _ := samlsp.New(samlsp.Options{
        IDPMetadataURL: "https://www.testshib.org/metadata/testshib-providers.xml",
        URL:            "http://localhost:8000",
        Key:            string(key),
        Certificate:    string(cert),
    })
    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 identiy provider to establish trust from the service provider to the IDP. For [testshib.org](testshib.org), you can do something like:

mdpath=saml-test-$USER-$HOST.xml
curl localhost:8000/saml/metadata > $mdpath
curl -i -F userfile=@$mdpath https://www.testshib.org/procupload.php

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

3. testshib.org prompts you for a username and password.

4. testshib.org 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 `examples/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 fromthe IDP to the service provider are supported vai the HTTP POST binding.

The package supports 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.

[TestShib](http://www.testshib.org/) is a testing ground for SAML service and identity providers.

Index

Constants

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)

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

Variables

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 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 is the value of a StatusCode element when the authentication succeeds. (nominally a constant, except for testing)

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

This section is empty.

Types

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          *xmlsec.Signature
	Subject            *Subject
	Conditions         *Conditions
	AuthnStatement     *AuthnStatement
	AttributeStatement *AttributeStatement
}

Assertion 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 (*Assertion) MarshalXML

func (a *Assertion) MarshalXML(e *xml.Encoder, start xml.StartElement) error

func (*Assertion) UnmarshalXML

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

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 Attribute

type Attribute struct {
	FriendlyName string           `xml:",attr"`
	Name         string           `xml:",attr"`
	NameFormat   string           `xml:",attr"`
	Values       []AttributeValue `xml:"AttributeValue"`
}

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

type AttributeStatement struct {
	Attributes []Attribute `xml:"Attribute"`
}

AttributeStatement 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 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 object of the same name.

See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf

type Audience

type Audience struct {
	Value string `xml:",chardata"`
}

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

type AudienceRestriction struct {
	Audience *Audience
}

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

type AuthnContext struct {
	AuthnContextClassRef *AuthnContextClassRef
}

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

type AuthnContextClassRef struct {
	Value string `xml:",chardata"`
}

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

type AuthnRequest struct {
	XMLName                     xml.Name  `xml:"urn:oasis:names:tc:SAML:2.0:protocol AuthnRequest"`
	AssertionConsumerServiceURL string    `xml:",attr"`
	Destination                 string    `xml:",attr"`
	ID                          string    `xml:",attr"`
	IssueInstant                time.Time `xml:",attr"`

	// Protocol binding is a URI reference that identifies a SAML protocol binding to be used when returning
	// the <Response> message. See [SAMLBind] for more information about protocol bindings and URI references
	// defined for them. This attribute is mutually exclusive with the AssertionConsumerServiceIndex attribute
	// and is typically accompanied by the AssertionConsumerServiceURL attribute.
	ProtocolBinding string `xml:",attr"`

	Version      string            `xml:",attr"`
	Issuer       Issuer            `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
	Signature    *xmlsec.Signature `xml:"http://www.w3.org/2000/09/xmldsig# Signature"`
	NameIDPolicy NameIDPolicy      `xml:"urn:oasis:names:tc:SAML:2.0:protocol NameIDPolicy"`
}

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

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

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

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

func (*AuthnRequest) UnmarshalXML

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

type AuthnStatement

type AuthnStatement struct {
	AuthnInstant    time.Time `xml:",attr"`
	SessionIndex    string    `xml:",attr"`
	SubjectLocality SubjectLocality
	AuthnContext    AuthnContext
}

AuthnStatement 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 (*AuthnStatement) MarshalXML

func (a *AuthnStatement) MarshalXML(e *xml.Encoder, start xml.StartElement) error

func (*AuthnStatement) UnmarshalXML

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

type Conditions

type Conditions struct {
	NotBefore           time.Time `xml:",attr"`
	NotOnOrAfter        time.Time `xml:",attr"`
	AudienceRestriction *AudienceRestriction
}

Conditions 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 (*Conditions) MarshalXML

func (c *Conditions) MarshalXML(e *xml.Encoder, start xml.StartElement) error

func (*Conditions) UnmarshalXML

func (c *Conditions) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type EncryptedAssertion

type EncryptedAssertion struct {
	Assertion     *Assertion
	EncryptedData []byte `xml:",innerxml"`
}

EncryptedAssertion 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 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 section 2.2.2

type EntitiesDescriptor

type EntitiesDescriptor struct {
	XMLName          xml.Name    `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntitiesDescriptor"`
	EntityDescriptor []*Metadata `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 section 2.3.1

type IDPSSODescriptor

type IDPSSODescriptor struct {
	XMLName                    xml.Name        `xml:"urn:oasis:names:tc:SAML:2.0:metadata IDPSSODescriptor"`
	WantAuthnRequestsSigned    bool            `xml:",attr"`
	ProtocolSupportEnumeration string          `xml:"protocolSupportEnumeration,attr"`
	KeyDescriptor              []KeyDescriptor `xml:"KeyDescriptor"`
	NameIDFormat               []string        `xml:"NameIDFormat"`
	SingleSignOnService        []Endpoint      `xml:"SingleSignOnService"`
}

IDPSSODescriptor represents the SAML IDPSSODescriptorType object.

See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf section 2.4.3

type IdentityProvider

type IdentityProvider struct {
	Key              string
	Certificate      string
	MetadataURL      string
	SSOURL           string
	ServiceProviders map[string]*Metadata
	SessionProvider  SessionProvider
}

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.

For each service provider that is able to use this IDP you must add their metadata to the ServiceProviders map.

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() *Metadata

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 *Metadata
	ACSEndpoint             *IndexedEndpoint
	Assertion               *Assertion
	AssertionBuffer         []byte
	Response                *Response
}

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

func (req *IdpAuthnRequest) MakeAssertion(session *Session) error

MakeAssertion produces a SAML assertion for the given request and assigns it to req.Assertion.

func (*IdpAuthnRequest) MakeResponse

func (req *IdpAuthnRequest) MakeResponse() error

MakeResponse creates and assigns a new SAML response in Response. `Assertion` must be non-nill. If MarshalAssertion() has not been called, this function calls it for you.

func (*IdpAuthnRequest) MarshalAssertion

func (req *IdpAuthnRequest) MarshalAssertion() error

MarshalAssertion sets `AssertionBuffer` to a signed, encrypted version of `Assertion`.

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"`
	Index    int    `xml:"index,attr"`
}

IndexedEndpoint represents the SAML IndexedEndpointType object.

See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf section 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"`
	Format  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               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

type Metadata

type Metadata struct {
	XMLName          xml.Name          `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntityDescriptor"`
	ValidUntil       time.Time         `xml:"validUntil,attr"`
	CacheDuration    time.Duration     `xml:"cacheDuration,attr,omitempty"`
	EntityID         string            `xml:"entityID,attr"`
	SPSSODescriptor  *SPSSODescriptor  `xml:"SPSSODescriptor"`
	IDPSSODescriptor *IDPSSODescriptor `xml:"IDPSSODescriptor"`
}

Metadata represents the SAML EntityDescriptor object.

See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf section 2.3.2

func (*Metadata) MarshalXML

func (m *Metadata) MarshalXML(e *xml.Encoder, start xml.StartElement) error

func (*Metadata) UnmarshalXML

func (m *Metadata) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type NameID

type NameID struct {
	Format          string `xml:",attr"`
	NameQualifier   string `xml:",attr"`
	SPNameQualifier string `xml:",attr"`
	Value           string `xml:",chardata"`
}

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

type NameIDFormat string
const (
	UnspecifiedNameIDFormat  NameIDFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified"
	TransientNameIDFormat    NameIDFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
	EmailAddressNameIDFormat NameIDFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress"
)

type NameIDPolicy

type NameIDPolicy struct {
	XMLName     xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol NameIDPolicy"`
	AllowCreate bool     `xml:",attr"`
	Format      string   `xml:",chardata"`
}

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

type RelaxedTime

type RelaxedTime time.Time

func (RelaxedTime) MarshalText

func (m RelaxedTime) MarshalText() ([]byte, error)

func (*RelaxedTime) UnmarshalText

func (m *RelaxedTime) UnmarshalText(text []byte) error

type Response

type Response struct {
	XMLName            xml.Name  `xml:"urn:oasis:names:tc:SAML:2.0:protocol Response"`
	Destination        string    `xml:",attr"`
	ID                 string    `xml:",attr"`
	InResponseTo       string    `xml:",attr"`
	IssueInstant       time.Time `xml:",attr"`
	Version            string    `xml:",attr"`
	Issuer             *Issuer   `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"`
	Status             *Status   `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"`
	EncryptedAssertion *EncryptedAssertion
	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

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

func (*Response) UnmarshalXML

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

type SPSSODescriptor

type SPSSODescriptor struct {
	XMLName                    xml.Name          `xml:"urn:oasis:names:tc:SAML:2.0:metadata SPSSODescriptor"`
	AuthnRequestsSigned        bool              `xml:",attr"`
	WantAssertionsSigned       bool              `xml:",attr"`
	ProtocolSupportEnumeration string            `xml:"protocolSupportEnumeration,attr"`
	KeyDescriptor              []KeyDescriptor   `xml:"KeyDescriptor"`
	ArtifactResolutionService  []IndexedEndpoint `xml:"ArtifactResolutionService"`
	SingleLogoutService        []Endpoint        `xml:"SingleLogoutService"`
	ManageNameIDService        []Endpoint
	NameIDFormat               []string          `xml:"NameIDFormat"`
	AssertionConsumerService   []IndexedEndpoint `xml:"AssertionConsumerService"`
	AttributeConsumingService  []interface{}
}

SPSSODescriptor represents the SAML SPSSODescriptorType object.

See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf section 2.4.2

type ServiceProvider

type ServiceProvider struct {
	// Key is the RSA private key we use to sign requests.
	Key string

	// Certificate is the RSA public part of Key.
	Certificate string

	// MetadataURL is the full URL to the metadata endpoint on this host,
	// i.e. https://example.com/saml/metadata
	MetadataURL string

	// AcsURL is the full URL to the SAML Assertion Customer Service endpoint
	// on this host, i.e. https://example.com/saml/acs
	AcsURL string

	// IDPMetadata is the metadata from the identity provider.
	IDPMetadata *Metadata

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

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) 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) (*AuthnRequest, error)

MakeAuthenticationRequest produces a new AuthnRequest object for idpURL.

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

func (sp *ServiceProvider) Metadata() *Metadata

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 attributes of the request.

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.

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
}

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

type SessionStore interface {
	Set(key string, assertion *Assertion)
	Get(key string) *Assertion
	Delete(key string)
}

type Status

type Status struct {
	XMLName    xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"`
	StatusCode StatusCode
}

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

type Subject struct {
	XMLName             xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion Subject"`
	NameID              *NameID
	SubjectConfirmation *SubjectConfirmation
}

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

type SubjectConfirmation struct {
	Method                  string `xml:",attr"`
	SubjectConfirmationData SubjectConfirmationData
}

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

type SubjectConfirmationData struct {
	Address      string    `xml:",attr"`
	InResponseTo string    `xml:",attr"`
	NotOnOrAfter time.Time `xml:",attr"`
	Recipient    string    `xml:",attr"`
}

SubjectConfirmationData 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 (*SubjectConfirmationData) MarshalXML

func (s *SubjectConfirmationData) MarshalXML(e *xml.Encoder, start xml.StartElement) error

func (*SubjectConfirmationData) UnmarshalXML

func (s *SubjectConfirmationData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error

type SubjectLocality

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

SubjectLocality represents the SAML object of the same name.

See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf

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.

Jump to

Keyboard shortcuts

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