Aperçu
Casdoor peut maintenant être utilisé comme IdP SAML. Jusqu'à présent, Casdoor a pris en charge les principales fonctionnalités de SAML 2.0.
Configuration dans le SP
En général, le SP nécessite trois champs obligatoires : Single Sign-On
, Issuer
et Public Certificate
. La plupart des SP peuvent obtenir ces champs en téléchargeant le fichier de métadonnées XML ou l'URL des métadonnées XML pour l'auto-complétion.
Les métadonnées du point de terminaison SAML dans Casdoor sont <Endpoint of casdoor>/api/saml/metadata?application=admin/<application name>
. Supposons que le point de terminaison de Casdoor soit https://door.casdoor.com
, et qu'il contienne une application appelée app-built-in
. L'endpoint des métadonnées XML sera :
https://door.casdoor.com/api/saml/metadata?application=admin/app-built-in
Vous pouvez également trouver les métadonnées dans la page d'édition de l'application. Cliquez sur le bouton pour copier l'URL et collez-la dans le navigateur pour télécharger les métadonnées XML.
Configuration dans Casdoor IdP
Casdoor prend en charge les requêtes GET et POST SAMLResponse
. Casdoor doit savoir quels types de requêtes le SP prend en charge lorsque Casdoor envoie la SAMLResponse
au SP. Vous devez configurer l'application dans Casdoor en fonction du type de SAMLResponse
pris en charge par votre SP.
Si vous remplissez l'URL de réponse, Casdoor enverra la SAMLResponse
par requête POST. Si l'URL de réponse est vide, Casdoor utilisera la requête GET. Vous vous demandez peut-être comment Casdoor connaît l'URL de réponse du SP si l'URL de réponse est vide. En fait, Casdoor peut obtenir l'URL appelée AssertionConsumerServiceURL
en analysant la SAMLRequest
et envoyer la requête avec SAMLResponse
à AssertionConsumerServiceURL
. L'URL de réponse écrasera l'AssertionConsumerServiceURL
dans la SAMLRequest
.
URL de réponse : Tapez l'URL de l'ACS vérifiant la réponse SAML.
URL de redirection : Tapez un nom unique. Cela peut être appelé
Audience
ouEntity ID
dans votre SP. Assurez-vous de remplir la mêmeURL de redirection
ici que dans votre SP.
Profil utilisateur
Après une connexion réussie, le profil utilisateur dans la SAMLResponse
retournée de Casdoor a trois champs. Les attributs dans le XML et les attributs de l'utilisateur dans Casdoor sont mappés comme suit :
Nom d'attribut XML | Champ utilisateur |
---|---|
DisplayName | displayName |
Nom | name |
Voir https://en.wikipedia.org/wiki/SAML_2.0 pour plus d'informations sur SAML et ses différentes versions.
Un exemple
gosaml2 est une implémentation de SAML 2.0 pour les fournisseurs de services basée sur etree et goxmldsig, une implémentation pure Go des signatures numériques XML. Nous utilisons cette bibliothèque pour tester SAML 2.0 dans Casdoor comme indiqué ci-dessous.
Supposons que vous pouvez accéder à Casdoor via http://localhost:7001/
, et que votre Casdoor contient une application appelée app-built-in
, qui appartient à une organisation appelée built-in
. Les URL, http://localhost:6900/acs/example
et http://localhost:6900/saml/acs/example
, doivent être ajoutées aux URL de redirection dans app-built-in
.
import (
"crypto/x509"
"fmt"
"net/http"
"io/ioutil"
"encoding/base64"
"encoding/xml"
saml2 "github.com/russellhaering/gosaml2"
"github.com/russellhaering/gosaml2/types"
dsig "github.com/russellhaering/goxmldsig"
)
func main() {
res, err := http.Get("http://localhost:7001/api/saml/metadata?application=admin/app-built-in")
if err != nil {
panic(err)
}
rawMetadata, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
metadata := &types.EntityDescriptor{}
err = xml.Unmarshal(rawMetadata, metadata)
if err != nil {
panic(err)
}
certStore := dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{},
}
for _, kd := range metadata.IDPSSODescriptor.KeyDescriptors {
for idx, xcert := range kd.KeyInfo.X509Data.X509Certificates {
if xcert.Data == "" {
panic(fmt.Errorf("metadata certificate(%d) must not be empty", idx))
}
certData, err := base64.StdEncoding.DecodeString(xcert.Data)
if err != nil {
panic(err)
}
idpCert, err := x509.ParseCertificate(certData)
if err != nil {
panic(err)
}
certStore.Roots = append(certStore.Roots, idpCert)
}
}
randomKeyStore := dsig.RandomKeyStoreForTest()
sp := &saml2.SAMLServiceProvider{
IdentityProviderSSOURL: metadata.IDPSSODescriptor.SingleSignOnServices[0].Location,
IdentityProviderIssuer: metadata.EntityID,
ServiceProviderIssuer: "http://localhost:6900/acs/example",
AssertionConsumerServiceURL: "http://localhost:6900/v1/_saml_callback",
SignAuthnRequests: true,
AudienceURI: "http://localhost:6900/saml/acs/example",
IDPCertificateStore: &certStore,
SPKeyStore: randomKeyStore,
}
http.HandleFunc("/v1/_saml_callback", func(rw http.ResponseWriter, req *http.Request) {
err := req.ParseForm()
if err != nil {
rw.WriteHeader(http.StatusBadRequest)
return
}
samlReponse := req.URL.Query().Get("SAMLResponse")
assertionInfo, err := sp.RetrieveAssertionInfo(samlReponse)
if err != nil {
fmt.Println(err)
rw.WriteHeader(http.StatusForbidden)
return
}
fmt.Println(assertionInfo)
if assertionInfo.WarningInfo.InvalidTime {
fmt.Println("here12:", assertionInfo.WarningInfo.InvalidTime)
rw.WriteHeader(http.StatusForbidden)
return
}
if assertionInfo.WarningInfo.NotInAudience {
fmt.Println(assertionInfo)
fmt.Println("here13:", assertionInfo.WarningInfo.NotInAudience)
rw.WriteHeader(http.StatusForbidden)
return
}
fmt.Fprintf(rw, "NameID: %s\n", assertionInfo.NameID)
fmt.Fprintf(rw, "Assertions:\n")
for key, val := range assertionInfo.Values {
fmt.Fprintf(rw, " %s: %+v\n", key, val)
}
fmt.Println(assertionInfo.Values.Get("FirstName"))
fmt.Fprintf(rw, "\n")
fmt.Fprintf(rw, "Warnings:\n")
fmt.Fprintf(rw, "%+v\n", assertionInfo.WarningInfo)
})
println("Visit this URL To Authenticate:")
authURL, err := sp.BuildAuthURL("")
if err != nil {
panic(err)
}
println(authURL)
println("Supply:")
fmt.Printf(" SP ACS URL : %s\n", sp.AssertionConsumerServiceURL)
err = http.ListenAndServe(":6900", nil)
if err != nil {
panic(err)
}
}
Exécutez le code ci-dessus, et la console affichera le message suivant.
Visit this URL To Authenticate:
http://localhost:7001/login/saml/authorize/admin/app-built-in?SAMLRequest=lFVbk6K8Fv0rFvNo2QR...
Supply:
SP ACS URL : http://localhost:6900/v1/_saml_callback
Cliquez sur l'URL pour vous authentifier, et la page de connexion de Casdoor s'affichera.
Après authentification, vous recevrez les messages de réponse comme indiqué ci-dessous.