Перейти до основного вмісту

Огляд

Тепер 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 відповідь.

    URL відповіді

  • Redirect URL: Введіть унікальне ім'я. Це може називатися Audience або Entity ID у вашому SP. Переконайтеся, що ви заповнили той самий Redirect URL тут, як і у вашому SP.

    Entity ID

Профіль користувача

Після успішного входу в систему профіль користувача у поверненому SAMLResponse від Casdoor має три поля. Атрибути в XML і атрибути користувача в Casdoor відображаються наступним чином:

Назва XML атрибутуПоле користувача
Електронна поштаemail
DisplayNamedisplayName
Ім'я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.

вхід

Після аутентифікації ви отримаєте повідомлення відповіді, як показано нижче.

відповідь