wai-saml2: SAML2 assertion validation as WAI middleware

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

A Haskell library which implements SAML2 assertion validation as WAI middleware


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.2.0.0, 0.2.0.0, 0.2.1.0, 0.2.1.1, 0.2.1.2, 0.2.1.3, 0.3.0.0, 0.3.0.1, 0.4, 0.5
Change log CHANGELOG.md
Dependencies base (>=4.8 && <5), base64-bytestring (>=0.1 && <2), bytestring (>=0.9 && <0.11), c14n (>=0.1.0.1 && <1), cryptonite (<1), data-default-class (<1), http-types (<1), mtl (>=2.2.1 && <3), text (<2), time (>=1.9 && <2), vault (>=0.3 && <1), wai (>=3.0 && <4), wai-extra (>=3.0 && <4), x509 (<2), x509-store (<2), xml-conduit (<2) [details]
License MIT
Copyright Copyright (c) Michael B. Gale
Author Michael B. Gale
Maintainer m.gale@warwick.ac.uk
Category Security
Home page https://github.com/mbg/wai-saml2#readme
Bug tracker https://github.com/mbg/wai-saml2/issues
Source repo head: git clone https://github.com/mbg/wai-saml2
Uploaded by mbg at 2020-06-29T13:58:38Z

Modules

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for wai-saml2-0.2.0.0

[back to package description]

wai-saml2

GitHub Haskell CI

A Haskell library which implements SAML2 assertion validation as WAI middleware. This can be used by a Haskell web application (the service provider, SP) to perform identity provider (IdP) initiated authentication, i.e. SAML2-based authentication where the authentication begins at the IdP-end, the IdP authenticates the user, and then gets the user to submit a SAML2 assertion back to the SP (known as "unsolicited SSO" within e.g. the Shibboleth project).

Completeness

There are currently a number of limitations to this library:

Security

The library is estimated to be sufficiently robust for use in a production environment. If you wish to implement this middleware, please note the following:

Usage

Preliminaries

You need to have registered your service provider with the identity provider. You need to have access to the IdP's metadata, which will contain the public key used for signature validation.

Configuration

The saml2Config function may be used to construct SAML2Config values. It expects at least the SP's private key and the IdP's public key as arguments, but you should almost certainly customise the configuration further. The private and public keys can be loaded with functions from the Data.X509 and Data.X509.File modules (from the x509 and x509-store packages, respectively):

(saml2Config spPrivateKey idpPublicKey){
    saml2AssertionPath = "/sso/assert",
    saml2ExpectedIssuer = Just "https://idp.sp.com/saml2",
    saml2ExpectedDestination = Just "https://example.com/sso/assert",
} 

The configuration options are documented in the Haddock documentation for the Network.Wai.SAML2.Config module.

Implementation

Two interfaces to the middleware are provided. See the Haddock documentation for the Network.Wai.SAML2 module for full usage examples. An example using the saml2Callback variant is shown below, where cfg is a SAML2Config value and app is your existing WAI application:

saml2Callback cfg callback mainApp
 where callback (Left err) app req sendResponse = do
           -- a POST request was made to the assertion endpoint, but
           -- something went wrong, details of which are provided by
           -- the error: this should probably be logged as it may
           -- indicate that an attack was attempted against the 
           -- endpoint, but you *must* not show the error
           -- to the client as it would severely compromise
           -- system security
           -- 
           -- you may also want to return e.g. a HTTP 400 or 401 status
       callback (Right result) app req sendResponse = do   
           -- a POST request was made to the assertion endpoint and the
           -- SAML2 response was successfully validated:        
           -- you *must* check that you have not encountered the 
           -- assertion ID before; we assume that there is a
           -- computation tryRetrieveAssertion which looks up
           -- assertions by ID in e.g. a database
           result <- tryRetrieveAssertion (assertionId (assertion result))
           
           case result of 
               Just something -> -- a replay attack has occurred
               Nothing -> do
                   -- store the assertion id somewhere
                   storeAssertion (assertionId (assertion result))
                   
                   -- the assertion is valid and you can now e.g.
                   -- retrieve user data from your database
                   -- before proceeding with the request by e.g.
                   -- redirecting them to the main view

Contributions

Please see CONTRIBUTING.md

References