Перейти к основному содержанию

Обзор

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 Имя АтрибутаПоле пользователя
Emailemail
DisplayNamedisplayName
Имя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. 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.

вход

После аутентификации вы получите сообщения ответа, как показано ниже.

ответ