Passer au contenu principal

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.

métadonnées

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.

info

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 réponse

  • URL de redirection : Tapez un nom unique. Cela peut être appelé Audience ou Entity ID dans votre SP. Assurez-vous de remplir la même URL de redirection ici que dans votre SP.

    Entity ID

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 XMLChamp utilisateur
Emailemail
DisplayNamedisplayName
Nomname

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.

connexion

Après authentification, vous recevrez les messages de réponse comme indiqué ci-dessous.

réponse