metabase/saml20-clj
On GitHub, metabase/saml20-clj has picked up 38 stars, Clojure. A Clojure SAML 2.0 library for SSO
Snapshot summary built from the project's own GitHub metadata — there's no written TopGit review yet. The page will update automatically when a full review is published.
TopGit writes full reviews for the most-starred, most-requested repositories. This page is a snapshot until then — see the READ ME tab for the original README in full.
Snapshot
Top contributors
Show top contributors
saml20-clj
-
This is a SAML 2.0 Clojure library for SSO acting as a thin wrapper around the Java libraries OpenSAML v4 and some utility functions from OneLogin's SAML library This library allows a Clojure application to act as a Service Provider (SP).
4.0.0 Usage
Creating metadata
In order for an identityprovider to understand you as a service-provider, you need to provide metadata about your service. This is done in the following manner:
(in-ns my-saml.core
(:require [saml20-clj.core :as saml-core]
[saml20-clj.coerce :as saml-coerce]))
(def config {:app-name "My Fancy App"
:acs-url "https://my-app.com/saml/login"
:slo-url "https://my-app.com/saml/logout"})
(def credentials {:alias "my-saml-secrets"
:filename "path/to/keystorefile.jks"
:password "s1krit"})
(def metadata (-> {:sp-cert (saml-coerce/->X509Certificate credentials)}
(merge config)
saml-core/metadata))
Recording Requests
You can keep track of which requests are in flight to determine whether responses correspond to valid requests we've
issued and whether we've already got a response for a request (e.g. to replay attacks) by using a StateManager. This
library ships with a simple in-memory state manager suitable for a single instance, but you can create your own
implementation if you need something more sophisticated.
(require '[saml20-clj.core :as saml])
(def state-manager (saml/in-memory-state-manager))
Logging In (SSO)
Requests
Basic usage for requests to the IdP looks like:
(require '[saml20-clj.core :as saml])
;; create a Ring redirect response to the IDP URL; pass the request as base-64 encoded `SAMLRequest` query parameter
(saml/idp-redirect-response
{:sp-name "My SP Name"
:acs-url "http://sp.example.com/demo1/index.php?acs"
:idp-url "http://idp.example.com/SSOService.php"
:issuer "http://sp.example.com/demo1/metadata.php"
;; state manager (discussed above) is optional, but if passed `request` will record the newly created request.
:state-manager state-manager
;; :credential is optional. If passed, sign the request with this key and attach public key data, if present
:credential sp-private-key}
;; This is RelayState. In the old version of the lib it was encrypted. In some cases,
;; like this it's not really sensitive so it doesn't need to be encrypted. Adding
;; automatic encryption support back is on the TODO list
"http://sp.example.com/please/redirect/me/to/here")
The :credential can be used to sign the request to the IdP, and attach any public key information (if present). It will happily accept several formats, depending on the use-case:
private-key: A PEM formatted string[public-cert private-key]: A tuple containing an X509 Certificate and a private key, both in PEM format{:filepath "/path/to/keystore" :password "keystore-password" :alias "key-alias"}: A map describing a keystore and alias used.
Responses
Basic usage for responses from the IdP looks like this (assuming a Ring request):
(require '[saml20-clj.core :as saml])
(require '[saml20-clj.encode-decode :as saml-decode])
(-> request
(saml/validate-response idp-cert sp-private-key)
;; convert the Assertions to a convenient Clojure map so you can do something with them
saml/assertions)
validate-response options
validate-response accepts an options map that allows you to configure what validations are done, as well as the
stateful parameters (if relevent) those validations are verified against. The list of options and their defaults are
shown below:
If you do not supply required state to the validators (eg. request-id, issuer) those validations will fail. If you do not plan to handle this state you should remove those validations from the request-valiators or the assertion-validators.
{ ;; e.g. "http://sp.example.com/demo1/index.php?acs" The assertion consumer service URL. It is *required*
;; always pass this value, as the SAML20 spec dictates that any Recipient field within a <SubjectConfirmationData>
;; must be checked against the :acs-url.
:acs-url nil
;; The ID of the request we (the SP) sent to the IdP. ID is generated on our end, and should be something like a UUID
;; rather than a sequential number. If non-nil, the :in-response-to validator checks that <SubjectConfirmationData>
;; nodes have a value of InResponseTo that matches an ID.
;;
;; The state manager implementation that ships with this library does not keep request state; InResponseTo validation
;; is provided as an option in case you write your own more sophisticated implementation.
:request-id (str (java.util.UUID/randomUUID))
;; If passed, must refer to an implementation of the StateManager protocol (either the built-in `in-memory-state-manager`
;; suitable for a single instance or a custom implementation suitable for your deployment). The StateManager, if enabled,
;; should record the `:request-id` and verify it against any returning response. Please refer to `state.clj` for implementation
;; details.
;; Note that enforcement of the `:state-manager` requires enabling the `:valid-request-id` response validator (which is
;; enabled by default).
:state-manager nil
;; whether this response was solicited (i.e., in response to a request we sent to the IdP). If this is false, the
;; :in-response-to validator checks that the request-id is nil.
:solicited? true
;; maximum amount of clock skew to allow for the :not-on-or-after and :not-before validators
:allowable-clock-skew-seconds 180
;; address of the client. If set, the :address validator will check that <SubjectConfirmationData> nodes have an
;; Address matching this value *iff* Address is present. Address is optional attribute.
:user-agent-address nil
;; Unique identifier of the IdP. Also referred to as Entity ID or 'Issuer'. If passed, the `:issuer` validators will check
;; that the <Issuer> property for <Response> and <Assertion>s matches.
:issuer nil
;; :response-validators and :assertion-validators are validation functions that run and check that the Response is
;; valid. If a check fails, these methods will throw an Exception. You can exclude some of these validators or add
;; your own by passing different values for these keys. Both types of validators are defined as multimethods; you can
;; add custom validators by adding more method implementations to their respective multimethods.
;; :response-validators are validation functions that run once for the entire Response. They are defined as
;; implementations of the saml20-clj.sp.response/validate-response multimethod.
:response-validators (see below)
;; :assertion validators are validation functions that run against every Assertion in the response. They are defined
;; as implementations of saml20-clj.sp.response/validate-assertion.
:assertion-validators (see below)
}
Default :response-validators
[;; If the <Response> itself is signed, verifies that this signature is matches the Response itself and matches the
;; IdP certificate. If Response is not signed, this validator does nothing.
:signature
;; requires that a message contains an authenticated signature for the message
:require-authenticated
;; If the :issuer option is passed and <Response> has <Issuer> information, checks that these match.
:issuer
;; Asserts that request-id matches the in-reponse-to
:in-response-to
;; Asserts that all assertions are encrypted if the message contains assertions
:require-encryption]
Default :assertion-validators
[;; If <Assertion> is signed, the signature matches the Assertion and the IdP certificate. If <Assertion> is not
;; signed, this validator does nothing.
:signature
;; If :acs-url is non-nil, and <SubjectConfirmationData> is present, checks that <SubjectConfirmationData> has a
;; Recipient attribute matching this value.
:recipient
;; If the :issuer option is passed, checks that Assertions have <Issuer> information and that it matches :issuer.
:issuer
;; If <SubjectConfirmationData> is present, has a NotOnOrAfter attribute, and its value is in the future,
;; accounting for :allowable-clock-skew-seconds
:not-on-or-after
;; If <SubjectConfirmationData> has a NotBefore attribute, checks that this value is in the past, accounting for
;; :allowable-clock-skew-seconds
:not-before
;; If :request-id is non-nil and <SubjectConfirmationData> is present, checks that <SubjectConfirmationData> has an
;; InResponseTo attribute matching :request-id.
:in-response-to
;; If :user-agent-address is non-nil and <SubjectConfirmationData> has an Address attribute, checks that Address
;; matches this value.
:address]
Logging Out (SLO)
Requests
Basic usage for logging out is to send the client a redirect to the IdP, with a LogoutResponse SAML message. This is done in the following manner:
(request/idp-logout-redirect-response
{:issuer "http://sp.example.com/demo1/metadata.php"
:user-email "[email protected]"
:idp-url "http://idp.example.com/SSOService.php"
:request-id "ONELOGIN_109707f0030a5d00620c9d9df97f627afe9dcc24"
:relay-state "http://sp.example.com/demo1/metadata.php"})
Some clients will prefer that you send them the SAMLRequest as a query parameter, and they will handle the redirect, for that purpose you can use the logout-redirect-location function, which will include the RelayState and SAMLRequest as query parameters.
(request/logout-redirect-location
{:issuer "http://sp.example.com/demo1/metadata.php"
:user-email "[email protected]"
:idp-url "http://idp.example.com/SSOService.php"
:request-id "ONELOGIN_109707f0030a5d00620c9d9df97f627afe9dcc24"
:relay-state "http://sp.example.com/demo1/metadata.php"})
;; =>
;; "http://idp.example.com/SSOService.php?SAMLRequest=fVLLbs<snip>&RelayState=aHR<snip>"
Responses
The IdP will redirect the client back to you, with a SAMLResponse in their query-params. You can validate this response by checking for the SAMLResponse's Status.
Differences from the original saml20-clj library
This repository is forked from vlacs/saml20-clj, and at this point is more or less a complete re-write.
- Other improvements:
- Uses OpenSAML v4 instead of OpenSAML v2 which was EOL'ed in 2016
- Tons of bug fixes, such as
saml20-clj.shared/base64->inflate->strnot actually callingbyte-inflateat all - Fixed millions of reflection warnings
- Removed duplicate functions
- Support for XML signing with SHA-256 instead of SHA-1, which is required by ADFS by default (via k2n/saml20-clj)
- Support for Clojure 1.10+
- Support for base-64 encodings that contain newlines
- Removed lots of dependencies on other libraries
- Reorganized code
- Removed tons of duplicate/unnecessary, untested code
- Fixed
<Assertion>signatures not being validated - Added Single Logout (SLO)
License
- Copyright © 2013 VLACS [email protected]
- Copyright © 2017 Kenji Nakamura [email protected]
- Copyright © 2019-2024 Metabase, Inc.
Distributed under the Eclipse Public License, the same as Clojure.
Related repositories
Master programming by recreating your favorite technologies from scratch.
A curated meta-list of curated lists organized by technology domain. The repository acts as a directory pointing to hundreds of specialized awesome lists covering programming languages, platforms, frameworks, and tooling. All content is community-contributed under the CC0 public domain dedication.
Public APIs is a community-curated GitHub repository listing free, publicly accessible APIs across a wide range of categories, with auth type, HTTPS, and CORS noted for each entry. It's a browsable reference, not a library to install.
freeCodeCamp is a free, self-paced curriculum for learning to code, published as open source at freeCodeCamp/freeCodeCamp. It's a 501(c)(3) nonprofit funded by donor support, structured around six certifications in its Full-Stack Developer Curriculum, each gated by required projects instead of open-book quizzes. The repository also carries beta language certifications for developers, interview-prep resources, and the code that runs the live freecodecamp.org platform.
Quick answers
Is metabase/saml20-clj open source?
TopGit's metadata for metabase/saml20-clj does not record a license. Most public repositories on GitHub ARE open source, but the exact terms vary — verify by opening the LICENSE file directly.
What is metabase/saml20-clj?
metabase/saml20-clj (metabase/saml20-clj) is a Clojure project on GitHub. From the project's own README: A Clojure SAML 2.0 library for SSO
Where do I read more about metabase/saml20-clj?
This TopGit page is a snapshot — the READ ME tab shows the project's own README content (links stripped, images preserved). The GitHub repository at github.com/metabase/saml20-clj is the definitive source.
Read full README in the tab above.
Is saml20-clj worth your time?
ChatGPT, Claude and Perplexity can all read this page. Ask one of them what it makes of saml20-clj.