نظرة عامة
يمكن الآن استخدام Casdoor كمزود هوية SAML IdP. حتى هذه النقطة، دعم Casdoor الميزات الرئيسية لـ SAML 2.0.
التكوين في مزود الخدمة SP
بشكل عام، يتطلب مزود الخدمة SP ثلاثة حقول مطلوبة: Single Sign-On
، Issuer
، و Public Certificate
. يمكن لمعظم مزودي الخدمة SP الحصول على هذه الحقول عن طريق تحميل ملف XML Metadata أو URL لـ XML Metadata للإكمال التلقائي.
بيانات metadata لنقطة نهاية SAML في Casdoor هي <Endpoint of casdoor>/api/saml/metadata?application=admin/<application name>
. لنفترض أن نقطة نهاية Casdoor هي https://door.casdoor.com
، وتحتوي على تطبيق يسمى app-built-in
. نقطة نهاية بيانات XML Metadata ستكون:
https://door.casdoor.com/api/saml/metadata?application=admin/app-built-in
يمكنك أيضًا العثور على البيانات metadata في صفحة تحرير التطبيق. انقر على الزر لنسخ الرابط والصقه في المتصفح لتنزيل ملف XML Metadata.
التكوين في مزود الهوية Casdoor IdP
Casdoor يدعم كلاً من طلبات GET و POST SAMLResponse
. Casdoor يحتاج إلى معرفة أنواع الطلبات التي يدعمها مزود الخدمة SP عندما يرسل Casdoor الـ SAMLResponse
إلى مزود الخدمة SP. تحتاج إلى تكوين التطبيق في Casdoor بناءً على نوع SAMLResponse
الذي يدعمه مزود الخدمة SP الخاص بك.
إذا قمت بملء Reply URL
، سيرسل Casdoor الـ SAMLResponse
بواسطة طلب POST. إذا كان عنوان الرد فارغًا، سيستخدم Casdoor طلب GET. قد تتساءل كيف يعرف Casdoor Reply URL
لمزود الخدمة SP إذا كان Reply URL
فارغًا. في الواقع، يمكن لـ Casdoor الحصول على الرابط المسمى AssertionConsumerServiceURL
عن طريق تحليل SAMLRequest
وإرسال الطلب مع SAMLResponse
إلى AssertionConsumerServiceURL
. سيتم الكتابة فوق Reply URL
لـ AssertionConsumerServiceURL
في SAMLRequest
.
عنوان الرد Reply URL: اكتب عنوان URL لخدمة ACS التي تتحقق من استجابة SAML.
عنوان إعادة التوجيه Redirect URL: اكتب اسمًا فريدًا. قد يُطلق على هذا
Audience
أوEntity ID
في مزود الخدمة SP الخاص بك. تأكد من ملء نفسRedirect URL
هنا كما في مزود الخدمة SP الخاص بك.
ملف تعريف المستخدم
بعد تسجيل الدخول بنجاح، يحتوي ملف تعريف المستخدم في الاستجابة SAMLResponse
العائدة من Casdoor على ثلاثة حقول. يتم تعيين السمات في XML وسمات المستخدم في Casdoor على النحو التالي:
اسم السمة XML | حقل المستخدم |
---|---|
البريد الإلكتروني | |
اسم العرض | displayName |
الاسم | name |
راجع https://en.wikipedia.org/wiki/SAML_2.0 لمزيد من المعلومات حول SAML وإصداراته المختلفة.
مثال
gosaml2 هو تنفيذ لـ SAML 2.0 لمزودي الخدمة مبني على etree و goxmldsig، وهو تنفيذ بلغة Go للتوقيعات الرقمية XML. نحن نستخدم هذه المكتبة لاختبار SAML 2.0 في Casdoor كما هو موضح أدناه.
لنفترض أنه يمكنك الوصول إلى Casdoor من خلال http://localhost:7001/
، ويحتوي Casdoor الخاص بك على تطبيق يسمى app-built-in
، والذي ينتمي إلى منظمة تسمى built-in
. يجب إضافة الروابط، http://localhost:6900/acs/example
و http://localhost:6900/saml/acs/example
، إلى روابط إعادة التوجيه Redirect URLs في 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)
}
}
قم بتشغيل الكود أعلاه، وسيعرض الوحدة الطرفية الرسالة التالية.
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
انقر على الرابط للمصادقة، وستظهر صفحة تسجيل الدخول إلى Casdoor.
بعد المصادقة، ستتلقى رسائل الاستجابة كما هو موضح أدناه.