Visão Geral
Casdoor agora pode ser usado como um SAML IdP. Até este ponto, o Casdoor suportou as principais funcionalidades do SAML 2.0.
Configuração no SP
Em geral, o SP requer três campos obrigatórios: Single Sign-On
, Issuer
e Public Certificate
. A maioria dos SPs pode obter esses campos fazendo o upload do arquivo de Metadados XML ou da URL de Metadados XML para preenchimento automático.
Os metadados do ponto de extremidade SAML no Casdoor são <Endpoint of casdoor>/api/saml/metadata?application=admin/<application name>
. Suponha que o ponto de extremidade do Casdoor seja https://door.casdoor.com
, e ele contém uma aplicação chamada app-built-in
. O ponto de extremidade de Metadados XML será:
https://door.casdoor.com/api/saml/metadata?application=admin/app-built-in
Você também pode encontrar os metadados na página de edição da aplicação. Clique no botão para copiar a URL e cole-a no navegador para baixar os Metadados XML.
Configuração no Casdoor IdP
Casdoor suporta tanto GET quanto POST SAMLResponse
. O Casdoor precisa saber quais tipos de solicitações o SP suporta quando o Casdoor envia o SAMLResponse
para o SP. Você precisa configurar a aplicação no Casdoor com base no tipo de SAMLResponse
suportado pelo seu SP.
Se você preencher a URL de Resposta
, o Casdoor enviará o SAMLResponse
por Solicitação POST. Se a URL de Resposta estiver vazia, o Casdoor usará a solicitação GET. Você pode se perguntar como o Casdoor sabe a URL de Resposta
do SP se a URL de Resposta
estiver vazia. Na verdade, o Casdoor pode obter a URL chamada AssertionConsumerServiceURL
analisando o SAMLRequest
e enviar a solicitação com SAMLResponse
para AssertionConsumerServiceURL
. A URL de Resposta
substituirá a AssertionConsumerServiceURL
no SAMLRequest
.
URL de Resposta: Digite a URL do ACS que verifica a resposta SAML.
URL de Redirecionamento: Digite um nome único. Isto pode ser chamado de
Audience
ouEntity ID
no seu SP. Certifique-se de preencher a mesmaURL de Redirecionamento
aqui como no seu SP.
Perfil do usuário
Após o login bem-sucedido, o perfil do usuário na SAMLResponse
retornada do Casdoor tem três campos. Os atributos no XML e os atributos do usuário no Casdoor são mapeados da seguinte forma:
Nome do Atributo XML | Campo do usuário |
---|---|
DisplayName | displayName |
Nome | name |
Veja https://en.wikipedia.org/wiki/SAML_2.0 para mais informações sobre SAML e suas diferentes versões.
Um exemplo
gosaml2 é uma implementação do SAML 2.0 para Provedores de Serviço baseada em etree e goxmldsig, uma implementação pura em Go de assinaturas digitais XML. Usamos esta biblioteca para testar o SAML 2.0 no Casdoor como mostrado abaixo.
Suponha que você possa acessar o Casdoor através de http://localhost:7001/
, e seu Casdoor contém uma aplicação chamada app-built-in
, que pertence a uma organização chamada built-in
. As URLs, http://localhost:6900/acs/example
e http://localhost:6900/saml/acs/example
, devem ser adicionadas às URLs de Redirecionamento em 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)
}
}
Execute o código acima, e o console exibirá a seguinte mensagem.
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
Clique na URL para autenticar, e a página de login do Casdoor será exibida.
Após autenticar, você receberá as mensagens de resposta como mostrado abaixo.