Огляд
Тепер Casdoor можна використовувати як SAML IdP. На цей момент Casdoor підтримує основні функції SAML 2.0.
Конфігурація в SP
Загалом, SP вимагає трьох обов'язкових полів: Single Sign-On
, Issuer
та Public Certificate
. Більшість SP можуть отримати ці поля, завантаживши файл XML Metadata або URL XML 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
Ви також можете знайти метадані на сторінці редагування додатку. Натисніть кнопку, щоб скопіювати URL і вставте його в браузер, щоб завантажити XML Metadata.
Конфігурація в Casdoor IdP
Casdoor підтримує як GET, так і POST SAMLResponse
. Casdoor потрібно знати, які типи запитів підтримує SP, коли Casdoor надсилає SAMLResponse
до SP. Вам потрібно налаштувати додаток у Casdoor відповідно до типу SAMLResponse
, який підтримує ваш SP.
Якщо ви заповните Reply URL
, Casdoor надішле SAMLResponse
за допомогою запиту POST. Якщо URL відповіді порожній, Casdoor використовуватиме запит GET. Ви можете запитати, як Casdoor знає Reply URL
SP, якщо Reply URL
порожній. Насправді, Casdoor може отримати URL під назвою 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 | displayName |
Ім'я | name |
Дивіться https://en.wikipedia.org/wiki/SAML_2.0 для отримання додаткової інформації про SAML та його різні версії.
Приклад
gosaml2 - це реалізація SAML 2.0 для постачальників послуг на основі etree та goxmldsig, чиста реалізація цифрових підписів XML на Go. Ми використовуємо цю бібліотеку для тестування SAML 2.0 у Casdoor, як показано нижче.
Припустимо, ви можете отримати доступ до Casdoor через http://localhost:7001/
, і ваш Casdoor містить додаток під назвою app-built-in
, який належить до організації під назвою built-in
. URL-адреси, 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
Натисніть URL для аутентифікації, і відобразиться сторінка входу Casdoor.
Після аутентифікації ви отримаєте повідомлення відповіді, як показано нижче.