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/nthsky/saml2/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
- Variables
- func GetSigningContext(sp *ServiceProvider) (*dsig.SigningContext, error)
- type AffiliationDescriptor
- type ArtifactResolve
- type ArtifactResponse
- type Assertion
- type AssertionAttribute
- type AssertionAttributes
- type AssertionMaker
- type Attribute
- type AttributeAuthorityDescriptor
- type AttributeConsumingService
- type AttributeStatement
- type AttributeValue
- type Audience
- type AudienceRestriction
- type AuthnAuthorityDescriptor
- type AuthnContext
- type AuthnContextClassRef
- type AuthnRequest
- func (r *AuthnRequest) Element() *etree.Element
- func (r *AuthnRequest) MarshalXML(e *xml.Encoder, start xml.StartElement) error
- func (req *AuthnRequest) Post(relayState string) []byte
- func (req *AuthnRequest) Redirect(relayState string, sp *ServiceProvider) (*url.URL, error)
- func (r *AuthnRequest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
- type AuthnStatement
- type Conditions
- type ContactPerson
- type DefaultAssertionMaker
- type Duration
- type EncryptionMethod
- type Endpoint
- type EntitiesDescriptor
- type EntityDescriptor
- type ErrBadStatus
- type IDPSSODescriptor
- type IdentityProvider
- func (idp *IdentityProvider) Handler() http.Handler
- func (idp *IdentityProvider) Metadata() *EntityDescriptor
- func (idp *IdentityProvider) ServeIDPInitiated(w http.ResponseWriter, r *http.Request, serviceProviderID string, ...)
- func (idp *IdentityProvider) ServeMetadata(w http.ResponseWriter, r *http.Request)
- func (idp *IdentityProvider) ServeSSO(w http.ResponseWriter, r *http.Request)
- type IdpAuthnRequest
- type IndexedEndpoint
- type InvalidResponseError
- type Issuer
- type KeyDescriptor
- type KeyInfo
- type LocalizedName
- type LocalizedURI
- type LogoutRequest
- func (r *LogoutRequest) Bytes() ([]byte, error)
- func (r *LogoutRequest) Deflate() ([]byte, error)
- func (r *LogoutRequest) Element() *etree.Element
- func (r *LogoutRequest) MarshalXML(e *xml.Encoder, start xml.StartElement) error
- func (req *LogoutRequest) Post(relayState string) []byte
- func (req *LogoutRequest) Redirect(relayState string) *url.URL
- func (r *LogoutRequest) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
- type LogoutResponse
- func (r *LogoutResponse) Element() *etree.Element
- func (r *LogoutResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error
- func (resp *LogoutResponse) Post(relayState string) []byte
- func (resp *LogoutResponse) Redirect(relayState string) *url.URL
- func (r *LogoutResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
- type NameID
- type NameIDFormat
- type NameIDPolicy
- type OneTimeUse
- type Organization
- type PDPDescriptor
- type ProxyRestriction
- type RelaxedTime
- type RequestedAttribute
- type RequestedAuthnContext
- type Response
- type RoleDescriptor
- type SPSSODescriptor
- type SSODescriptor
- type ServiceProvider
- func (sp *ServiceProvider) GetArtifactBindingLocation(binding string) string
- func (sp *ServiceProvider) GetSLOBindingLocation(binding string) string
- func (sp *ServiceProvider) GetSSOBindingLocation(binding string) string
- func (sp *ServiceProvider) MakeArtifactResolveRequest(artifactID string) (*ArtifactResolve, error)
- func (sp *ServiceProvider) MakeAuthenticationRequest(idpURL string, binding string, resultBinding string) (*AuthnRequest, error)
- func (sp *ServiceProvider) MakeLogoutRequest(idpURL, nameID string) (*LogoutRequest, error)
- func (sp *ServiceProvider) MakeLogoutResponse(idpURL, logoutRequestID string) (*LogoutResponse, error)
- func (sp *ServiceProvider) MakePostAuthenticationRequest(relayState string) ([]byte, error)
- func (sp *ServiceProvider) MakePostLogoutRequest(nameID, relayState string) ([]byte, error)
- func (sp *ServiceProvider) MakePostLogoutResponse(logoutRequestID, relayState string) ([]byte, error)
- func (sp *ServiceProvider) MakeRedirectAuthenticationRequest(relayState string) (*url.URL, error)
- func (sp *ServiceProvider) MakeRedirectLogoutRequest(nameID, relayState string) (*url.URL, error)
- func (sp *ServiceProvider) MakeRedirectLogoutResponse(logoutRequestID, relayState string) (*url.URL, error)
- func (sp *ServiceProvider) Metadata() *EntityDescriptor
- func (sp *ServiceProvider) ParseResponse(req *http.Request, possibleRequestIDs []string) (*Assertion, error)
- func (sp *ServiceProvider) ParseXMLArtifactResponse(decodedResponseXML []byte, possibleRequestIDs []string, ...) (*Assertion, error)
- func (sp *ServiceProvider) ParseXMLResponse(decodedResponseXML []byte, possibleRequestIDs []string) (*Assertion, error)
- func (sp *ServiceProvider) SignArtifactResolve(req *ArtifactResolve) error
- func (sp *ServiceProvider) SignAuthnRequest(req *AuthnRequest) error
- func (sp *ServiceProvider) SignLogoutRequest(req *LogoutRequest) error
- func (sp *ServiceProvider) SignLogoutResponse(resp *LogoutResponse) error
- func (sp *ServiceProvider) ValidateLogoutResponseForm(postFormData string) error
- func (sp *ServiceProvider) ValidateLogoutResponseRedirect(queryParameterData string) error
- func (sp *ServiceProvider) ValidateLogoutResponseRequest(req *http.Request) error
- type ServiceProviderProvider
- type Session
- type SessionIndex
- type SessionProvider
- type SignatureVerifier
- type Status
- type StatusCode
- type StatusDetail
- type StatusMessage
- type Subject
- type SubjectConfirmation
- type SubjectConfirmationData
- type SubjectLocality
- type X509Certificate
- type X509Data
Constants ¶
const ( // StatusRequester means the request could not be performed due to an error on the part of the requester. StatusRequester = "urn:oasis:names:tc:SAML:2.0:status:Requester" // StatusResponder means the request could not be performed due to an error on the part of the SAML responder or SAML authority. StatusResponder = "urn:oasis:names:tc:SAML:2.0:status:Responder" // StatusVersionMismatch means the SAML responder could not process the request because the version of the request message was incorrect. StatusVersionMismatch = "urn:oasis:names:tc:SAML:2.0:status:VersionMismatch" // StatusAuthnFailed means the responding provider was unable to successfully authenticate the principal. StatusAuthnFailed = "urn:oasis:names:tc:SAML:2.0:status:AuthnFailed" // StatusInvalidAttrNameOrValue means Unexpected or invalid content was encountered within a <saml:Attribute> or <saml:AttributeValue> element. StatusInvalidAttrNameOrValue = "urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue" // StatusInvalidNameIDPolicy means the responding provider cannot or will not support the requested name identifier policy. StatusInvalidNameIDPolicy = "urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy" // StatusNoAuthnContext means the specified authentication context requirements cannot be met by the responder. StatusNoAuthnContext = "urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext" // StatusNoAvailableIDP is used by an intermediary to indicate that none of the supported identity provider <Loc> elements in an <IDPList> can be resolved or that none of the supported identity providers are available. StatusNoAvailableIDP = "urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP" // StatusNoPassive means Indicates the responding provider cannot authenticate the principal passively, as has been requested. StatusNoPassive = "urn:oasis:names:tc:SAML:2.0:status:NoPassive" //nolint:gosec // StatusNoSupportedIDP is used by an intermediary to indicate that none of the identity providers in an <IDPList> are supported by the intermediary. StatusNoSupportedIDP = "urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP" // StatusPartialLogout is used by a session authority to indicate to a session participant that it was not able to propagate logout to all other session participants. StatusPartialLogout = "urn:oasis:names:tc:SAML:2.0:status:PartialLogout" // StatusProxyCountExceeded means Indicates that a responding provider cannot authenticate the principal directly and is not permitted to proxy the request further. StatusProxyCountExceeded = "urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded" // StatusRequestDenied means the SAML responder or SAML authority is able to process the request but has chosen not to respond. This status code MAY be used when there is concern about the security context of the request message or the sequence of request messages received from a particular requester. StatusRequestDenied = "urn:oasis:names:tc:SAML:2.0:status:RequestDenied" // StatusRequestUnsupported means the SAML responder or SAML authority does not support the request. StatusRequestUnsupported = "urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported" // StatusRequestVersionDeprecated means the SAML responder cannot process any requests with the protocol version specified in the request. StatusRequestVersionDeprecated = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated" // StatusRequestVersionTooHigh means the SAML responder cannot process the request because the protocol version specified in the request message is a major upgrade from the highest protocol version supported by the responder. StatusRequestVersionTooHigh = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh" // StatusRequestVersionTooLow means the SAML responder cannot process the request because the protocol version specified in the request message is too low. StatusRequestVersionTooLow = "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow" // StatusResourceNotRecognized means the resource value provided in the request message is invalid or unrecognized. StatusResourceNotRecognized = "urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized" // StatusTooManyResponses means the response message would contain more elements than the SAML responder is able to return. StatusTooManyResponses = "urn:oasis:names:tc:SAML:2.0:status:TooManyResponses" // StatusUnknownAttrProfile means an entity that has no knowledge of a particular attribute profile has been presented with an attribute means drawn from that profile. StatusUnknownAttrProfile = "urn:oasis:names:tc:SAML:2.0:status:UnknownAttrProfile" // StatusUnknownPrincipal means the responding provider does not recognize the principal specified or implied by the request. StatusUnknownPrincipal = "urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal" // StatusUnsupportedBinding means the SAML responder cannot properly fulfill the request using the protocol binding specified in the request. StatusUnsupportedBinding = "urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding" )
const DefaultCacheDuration = time.Hour * 24 * 1
DefaultCacheDuration is how long we ask the IDP to cache the SP metadata.
const DefaultValidDuration = time.Hour * 24 * 2
DefaultValidDuration is how long we assert that the SP metadata is valid.
const HTTPArtifactBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
HTTPArtifactBinding is the official URN for the HTTP-Artifact binding (transport)
const HTTPPostBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
HTTPPostBinding is the official URN for the HTTP-POST binding (transport)
const HTTPRedirectBinding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
HTTPRedirectBinding is the official URN for the HTTP-Redirect binding (transport)
const SOAPBinding = "urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
SOAPBinding is the official URN for the SOAP binding (transport)
Variables ¶
var Clock *dsig.Clock
Clock is assigned to dsig validation and signing contexts if it is not nil, otherwise the default clock is used.
var MaxClockSkew = time.Second * 180
MaxClockSkew allows for leeway for clock skew between the IDP and SP when validating assertions. It defaults to 180 seconds (matches shibboleth).
var MaxIssueDelay = time.Second * 90
MaxIssueDelay is the longest allowed time between when a SAML assertion is issued by the IDP and the time it is received by ParseResponse. This is used to prevent old responses from being replayed (while allowing for some clock drift between the SP and IDP).
var Metadata = struct{}{}
Metadata as been renamed to EntityDescriptor
This change was made to be consistent with the rest of the API which uses names from the SAML specification for types.
This is a tombstone to help you discover this fact. You should update references to saml.Metadata to be saml.EntityDescriptor.
var RandReader = rand.Reader
RandReader is the io.Reader that produces cryptographically random bytes when they are need by the library. The default value is rand.Reader, but it can be replaced for testing.
var StatusSuccess = "urn:oasis:names:tc:SAML:2.0:status:Success"
StatusSuccess means the request succeeded. Additional information MAY be returned in the <StatusMessage> and/or <StatusDetail> elements.
TODO(ross): this value is mostly constant, but is mutated in tests. Fix the hacky test so this can be const.
var TimeNow = func() time.Time { return time.Now().UTC() }
TimeNow is a function that returns the current time. The default value is time.Now, but it can be replaced for testing.
Functions ¶
func 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 ArtifactResolve ¶
type ArtifactResolve struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol ArtifactResolve"` ID string `xml:",attr"` Version string `xml:",attr"` IssueInstant time.Time `xml:",attr"` Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"` Signature *etree.Element Artifact string `xml:"urn:oasis:names:tc:SAML:2.0:protocol Artifact"` }
ArtifactResolve represents the SAML object of the same name.
func (*ArtifactResolve) Element ¶
func (r *ArtifactResolve) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*ArtifactResolve) MarshalXML ¶
func (r *ArtifactResolve) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*ArtifactResolve) SoapRequest ¶
func (r *ArtifactResolve) SoapRequest() *etree.Element
SoapRequest returns a SOAP Envelope contining the ArtifactResolve request
func (*ArtifactResolve) UnmarshalXML ¶
func (r *ArtifactResolve) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type ArtifactResponse ¶
type ArtifactResponse struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol ArtifactResponse"` ID string `xml:",attr"` InResponseTo string `xml:",attr"` Version string `xml:",attr"` IssueInstant time.Time `xml:",attr"` Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"` Signature *etree.Element Status Status `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"` Response Response `xml:"urn:oasis:names:tc:SAML:2.0:protocol Response"` }
ArtifactResponse represents the SAML object of the same name.
func (*ArtifactResponse) Element ¶
func (r *ArtifactResponse) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*ArtifactResponse) MarshalXML ¶
func (r *ArtifactResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error
MarshalXML implements xml.Marshaler
func (*ArtifactResponse) UnmarshalXML ¶
func (r *ArtifactResponse) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
UnmarshalXML implements xml.Unmarshaler
type Assertion ¶
type Assertion struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion Assertion"` ID string `xml:",attr"` IssueInstant time.Time `xml:",attr"` Version string `xml:",attr"` Issuer Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"` Signature *etree.Element Subject *Subject Conditions *Conditions // 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) UnmarshalXML ¶
UnmarshalXML implements xml.Unmarshaler
type AssertionAttribute ¶
AssertionAttribute represents an attribute of the user extracted from a SAML Assertion.
type AssertionAttributes ¶
type AssertionAttributes []AssertionAttribute
AssertionAttributes is a list of AssertionAttribute
func (AssertionAttributes) Get ¶
func (aa AssertionAttributes) Get(name string) *AssertionAttribute
Get returns the assertion attribute whose Name or FriendlyName matches name, or nil if no matching attribute is found.
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
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
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 RequestedAuthnContext *RequestedAuthnContext ForceAuthn *bool `xml:",attr"` IsPassive *bool `xml:",attr"` AssertionConsumerServiceIndex string `xml:",attr"` AssertionConsumerServiceURL string `xml:",attr"` ProtocolBinding string `xml:",attr"` AttributeConsumingServiceIndex string `xml:",attr"` ProviderName string `xml:",attr"` }
AuthnRequest represents the SAML object of the same name, a request from a service provider to authenticate a user.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*AuthnRequest) Element ¶
func (r *AuthnRequest) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
func (*AuthnRequest) MarshalXML ¶
func (r *AuthnRequest) MarshalXML(e *xml.Encoder, 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 ¶
Duration is a time.Duration that uses the xsd:duration format for text marshalling and unmarshalling.
func (Duration) MarshalText ¶
MarshalText implements the encoding.TextMarshaler interface.
func (*Duration) UnmarshalText ¶
UnmarshalText implements the encoding.TextUnmarshaler interface.
type EncryptionMethod ¶
type EncryptionMethod struct {
Algorithm string `xml:"Algorithm,attr"`
}
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"` ArtifactResolutionServices []Endpoint `xml:"ArtifactResolutionService"` 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 ¶
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
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"` X509Data X509Data `xml:"X509Data"` }
KeyInfo represents the XMLSEC object of the same name
type LocalizedName ¶
type LocalizedName struct { Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr"` Value string `xml:",chardata"` }
LocalizedName represents the SAML type localizedNameType.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.2.4
type LocalizedURI ¶
type LocalizedURI struct { Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr"` Value string `xml:",chardata"` }
LocalizedURI represents the SAML type localizedURIType.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.2.5
type LogoutRequest ¶
type LogoutRequest struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol LogoutRequest"` ID string `xml:",attr"` Version string `xml:",attr"` IssueInstant time.Time `xml:",attr"` NotOnOrAfter *time.Time `xml:",attr"` Destination string `xml:",attr"` Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"` NameID *NameID 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
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 ¶
ProxyRestriction represents the SAML element ProxyRestriction.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.5.1.6
func (*ProxyRestriction) Element ¶
func (a *ProxyRestriction) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type RelaxedTime ¶
RelaxedTime is a version of time.Time that supports the time format found in SAML documents.
func (RelaxedTime) MarshalText ¶
func (m RelaxedTime) MarshalText() ([]byte, error)
MarshalText implements encoding.TextMarshaler
func (RelaxedTime) String ¶
func (m RelaxedTime) String() string
func (*RelaxedTime) UnmarshalText ¶
func (m *RelaxedTime) UnmarshalText(text []byte) error
UnmarshalText implements encoding.TextUnmarshaler
type RequestedAttribute ¶
RequestedAttribute represents the SAML RequestedAttribute object.
See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.4.4.2
type RequestedAuthnContext ¶
type RequestedAuthnContext struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol RequestedAuthnContext"` Comparison string `xml:",attr"` AuthnContextClassRef string `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthnContextClassRef"` }
RequestedAuthnContext represents the SAML object of the same name, an indication of the requirements on the authentication process.
func (*RequestedAuthnContext) Element ¶
func (r *RequestedAuthnContext) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type Response ¶
type Response struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol Response"` ID string `xml:",attr"` InResponseTo string `xml:",attr"` Version string `xml:",attr"` IssueInstant time.Time `xml:",attr"` Destination string `xml:",attr"` Consent string `xml:",attr"` Issuer *Issuer `xml:"urn:oasis:names:tc:SAML:2.0:assertion Issuer"` Signature *etree.Element Status Status `xml:"urn:oasis:names:tc:SAML:2.0:protocol Status"` // TODO(ross): more than one EncryptedAssertion is allowed EncryptedAssertion *etree.Element `xml:"urn:oasis:names:tc:SAML:2.0:assertion EncryptedAssertion"` // TODO(ross): more than one Assertion is allowed Assertion *Assertion `xml:"urn:oasis:names:tc:SAML:2.0:assertion Assertion"` }
Response represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*Response) MarshalXML ¶
MarshalXML implements xml.Marshaler
func (*Response) UnmarshalXML ¶
UnmarshalXML implements xml.Unmarshaler
type 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 // HTTPClient to use during SAML artifact resolution HTTPClient *http.Client // 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 // RequestedAuthnContext allow you to specify the requested authentication // context in authentication requests RequestedAuthnContext *RequestedAuthnContext // AllowIdpInitiated AllowIDPInitiated bool // DefaultRedirectURI where untracked requests (as of IDPInitiated) are redirected to DefaultRedirectURI string // SignatureVerifier, if non-nil, allows you to implement an alternative way // to verify signatures. SignatureVerifier SignatureVerifier // SignatureMethod, if non-empty, authentication requests will be signed SignatureMethod string // LogoutBindings specify the bindings available for SLO endpoint. If empty, // HTTP-POST binding is used. LogoutBindings []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) GetArtifactBindingLocation ¶
func (sp *ServiceProvider) GetArtifactBindingLocation(binding string) string
GetArtifactBindingLocation returns URL for the IDP's Artifact binding of the specified type
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) MakeArtifactResolveRequest ¶
func (sp *ServiceProvider) MakeArtifactResolveRequest(artifactID string) (*ArtifactResolve, error)
MakeArtifactResolveRequest produces a new ArtifactResolve object to send to the idp's Artifact resolver
func (*ServiceProvider) MakeAuthenticationRequest ¶
func (sp *ServiceProvider) MakeAuthenticationRequest(idpURL string, binding string, resultBinding string) (*AuthnRequest, error)
MakeAuthenticationRequest produces a new AuthnRequest object to send to the idpURL that uses the specified binding (HTTPRedirectBinding or HTTPPostBinding)
func (*ServiceProvider) MakeLogoutRequest ¶
func (sp *ServiceProvider) MakeLogoutRequest(idpURL, nameID string) (*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, resolves artifacts when necessary, validates it, and returns the verified assertion.
func (*ServiceProvider) ParseXMLArtifactResponse ¶
func (sp *ServiceProvider) ParseXMLArtifactResponse(decodedResponseXML []byte, possibleRequestIDs []string, artifactRequestID string) (*Assertion, error)
ParseXMLArtifactResponse validates the SAML Artifact resolver response and returns the verified assertion.
This function handles verifying the digital signature, and verifying that the specified conditions and properties are met.
If the function fails it will return an InvalidResponseError whose properties are useful in describing which part of the parsing process failed. However, to discourage inadvertent disclosure the diagnostic information, the Error() method returns a static string.
func (*ServiceProvider) ParseXMLResponse ¶
func (sp *ServiceProvider) ParseXMLResponse(decodedResponseXML []byte, possibleRequestIDs []string) (*Assertion, error)
ParseXMLResponse parses and validates the SAML IDP response and returns the verified assertion.
This function handles decrypting the message, verifying the digital signature on the assertion, and verifying that the specified conditions and properties are met.
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) SignArtifactResolve ¶
func (sp *ServiceProvider) SignArtifactResolve(req *ArtifactResolve) error
SignArtifactResolve adds the `Signature` element to the `ArtifactResolve`.
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
type StatusCode ¶
type StatusCode struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol StatusCode"` Value string `xml:",attr"` StatusCode *StatusCode }
StatusCode represents the SAML object of the same name.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
func (*StatusCode) Element ¶
func (s *StatusCode) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type StatusDetail ¶
StatusDetail represents the SAML element StatusDetail.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §3.2.2.4
func (StatusDetail) Element ¶
func (sm StatusDetail) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type StatusMessage ¶
type StatusMessage struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol StatusMessage"` Value string `xml:",chardata"` }
StatusMessage represents the SAML element StatusMessage.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §3.2.2.3
func (StatusMessage) Element ¶
func (sm StatusMessage) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type Subject ¶
type Subject struct { XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion Subject"` // BaseID *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
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 ¶
SubjectLocality represents the SAML element SubjectLocality.
See http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf §2.7.2.1
func (*SubjectLocality) Element ¶
func (a *SubjectLocality) Element() *etree.Element
Element returns an etree.Element representing the object in XML form.
type X509Certificate ¶
type X509Certificate struct { XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Certificate"` Data string `xml:",chardata"` }
X509Certificate represents the XMLSEC object of the same name
type X509Data ¶
type X509Data struct { XMLName xml.Name `xml:"http://www.w3.org/2000/09/xmldsig# X509Data"` X509Certificates []X509Certificate `xml:"X509Certificate"` }
X509Data represents the XMLSEC object of the same name
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
example
module
|
|
samlidp
module
|
|
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. |