Skip to content

SAML post to correct URL and make example run locally #617

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
coverage.out
coverage.html
vendor/
**/*.cert
**/*.key
example/*.sh

# IDE-specific settings
.idea
.vscode
.vscode

# Fly.io deployment
fly.toml
Dockerfile
18 changes: 18 additions & 0 deletions example/idp/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module github.com/adricasti/samlidp

go 1.23

toolchain go1.24.2

require github.com/crewjam/saml v0.5.1

require (
github.com/beevik/etree v1.5.0 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/russellhaering/goxmldsig v1.4.0 // indirect
golang.org/x/crypto v0.33.0 // indirect
)

// Replace the remote saml module with your local version
replace github.com/crewjam/saml => ../../
44 changes: 44 additions & 0 deletions example/idp/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beevik/etree v1.5.0 h1:iaQZFSDS+3kYZiGoc9uKeOkUY3nYMXOKLl6KIJxiJWs=
github.com/beevik/etree v1.5.0/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russellhaering/goxmldsig v1.4.0 h1:8UcDh/xGyQiyrW+Fq5t8f+l2DLB1+zlhYzkPUJ7Qhys=
github.com/russellhaering/goxmldsig v1.4.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
101 changes: 14 additions & 87 deletions example/idp/idp.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,117 +2,44 @@
package main

import (
"crypto"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"flag"
"net/http"
"net/url"

"golang.org/x/crypto/bcrypt"

"github.com/crewjam/saml/logger"
"github.com/crewjam/saml/samlidp"
)

var key = func() crypto.PrivateKey {
b, _ := pem.Decode([]byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA0OhbMuizgtbFOfwbK7aURuXhZx6VRuAs3nNibiuifwCGz6u9
yy7bOR0P+zqN0YkjxaokqFgra7rXKCdeABmoLqCC0U+cGmLNwPOOA0PaD5q5xKhQ
4Me3rt/R9C4Ca6k3/OnkxnKwnogcsmdgs2l8liT3qVHP04Oc7Uymq2v09bGb6nPu
fOrkXS9F6mSClxHG/q59AGOWsXK1xzIRV1eu8W2SNdyeFVU1JHiQe444xLoPul5t
InWasKayFsPlJfWNc8EoU8COjNhfo/GovFTHVjh9oUR/gwEFVwifIHihRE0Hazn2
EQSLaOr2LM0TsRsQroFjmwSGgI+X2bfbMTqWOQIDAQABAoIBAFWZwDTeESBdrLcT
zHZe++cJLxE4AObn2LrWANEv5AeySYsyzjRBYObIN9IzrgTb8uJ900N/zVr5VkxH
xUa5PKbOcowd2NMfBTw5EEnaNbILLm+coHdanrNzVu59I9TFpAFoPavrNt/e2hNo
NMGPSdOkFi81LLl4xoadz/WR6O/7N2famM+0u7C2uBe+TrVwHyuqboYoidJDhO8M
w4WlY9QgAUhkPyzZqrl+VfF1aDTGVf4LJgaVevfFCas8Ws6DQX5q4QdIoV6/0vXi
B1M+aTnWjHuiIzjBMWhcYW2+I5zfwNWRXaxdlrYXRukGSdnyO+DH/FhHePJgmlkj
NInADDkCgYEA6MEQFOFSCc/ELXYWgStsrtIlJUcsLdLBsy1ocyQa2lkVUw58TouW
RciE6TjW9rp31pfQUnO2l6zOUC6LT9Jvlb9PSsyW+rvjtKB5PjJI6W0hjX41wEO6
fshFELMJd9W+Ezao2AsP2hZJ8McCF8no9e00+G4xTAyxHsNI2AFTCQcCgYEA5cWZ
JwNb4t7YeEajPt9xuYNUOQpjvQn1aGOV7KcwTx5ELP/Hzi723BxHs7GSdrLkkDmi
Gpb+mfL4wxCt0fK0i8GFQsRn5eusyq9hLqP/bmjpHoXe/1uajFbE1fZQR+2LX05N
3ATlKaH2hdfCJedFa4wf43+cl6Yhp6ZA0Yet1r8CgYEAwiu1j8W9G+RRA5/8/DtO
yrUTOfsbFws4fpLGDTA0mq0whf6Soy/96C90+d9qLaC3srUpnG9eB0CpSOjbXXbv
kdxseLkexwOR3bD2FHX8r4dUM2bzznZyEaxfOaQypN8SV5ME3l60Fbr8ajqLO288
wlTmGM5Mn+YCqOg/T7wjGmcCgYBpzNfdl/VafOROVbBbhgXWtzsz3K3aYNiIjbp+
MunStIwN8GUvcn6nEbqOaoiXcX4/TtpuxfJMLw4OvAJdtxUdeSmEee2heCijV6g3
ErrOOy6EqH3rNWHvlxChuP50cFQJuYOueO6QggyCyruSOnDDuc0BM0SGq6+5g5s7
H++S/wKBgQDIkqBtFr9UEf8d6JpkxS0RXDlhSMjkXmkQeKGFzdoJcYVFIwq8jTNB
nJrVIGs3GcBkqGic+i7rTO1YPkquv4dUuiIn+vKZVoO6b54f+oPBXd4S0BnuEqFE
rdKNuCZhiaE2XD9L/O9KP1fh5bfEcKwazQ23EvpJHBMm8BGC+/YZNw==
-----END RSA PRIVATE KEY-----`))
k, _ := x509.ParsePKCS1PrivateKey(b.Bytes)
return k
}()

var cert = func() *x509.Certificate {
b, _ := pem.Decode([]byte(`-----BEGIN CERTIFICATE-----
MIIDBzCCAe+gAwIBAgIJAPr/Mrlc8EGhMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNTEyMjgxOTE5NDVaFw0yNTEyMjUxOTE5
NDVaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBANDoWzLos4LWxTn8Gyu2lEbl4WcelUbgLN5zYm4ron8A
hs+rvcsu2zkdD/s6jdGJI8WqJKhYK2u61ygnXgAZqC6ggtFPnBpizcDzjgND2g+a
ucSoUODHt67f0fQuAmupN/zp5MZysJ6IHLJnYLNpfJYk96lRz9ODnO1Mpqtr9PWx
m+pz7nzq5F0vRepkgpcRxv6ufQBjlrFytccyEVdXrvFtkjXcnhVVNSR4kHuOOMS6
D7pebSJ1mrCmshbD5SX1jXPBKFPAjozYX6PxqLxUx1Y4faFEf4MBBVcInyB4oURN
B2s59hEEi2jq9izNE7EbEK6BY5sEhoCPl9m32zE6ljkCAwEAAaNQME4wHQYDVR0O
BBYEFB9ZklC1Ork2zl56zg08ei7ss/+iMB8GA1UdIwQYMBaAFB9ZklC1Ork2zl56
zg08ei7ss/+iMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAVoTSQ5
pAirw8OR9FZ1bRSuTDhY9uxzl/OL7lUmsv2cMNeCB3BRZqm3mFt+cwN8GsH6f3uv
NONIhgFpTGN5LEcXQz89zJEzB+qaHqmbFpHQl/sx2B8ezNgT/882H2IH00dXESEf
y/+1gHg2pxjGnhRBN6el/gSaDiySIMKbilDrffuvxiCfbpPN0NRRiPJhd2ay9KuL
/RxQRl1gl9cHaWiouWWba1bSBb2ZPhv2rPMUsFo98ntkGCObDX6Y1SpkqmoTbrsb
GFsTG2DLxnvr4GdN1BSr0Uu/KV3adj47WkXVPeMYQti/bQmxQB8tRFhrw80qakTL
UzreO96WzlBBMtY=
-----END CERTIFICATE-----`))
c, _ := x509.ParseCertificate(b.Bytes)
return c
}()

func main() {
logr := logger.DefaultLogger
baseURLstr := flag.String("idp", "", "The URL to the IDP")
baseURLstr := flag.String("idp", "http://localhost:8080", "The URL to the IDP")
certFile := flag.String("cert", "idp.cert", "The certificate file path")
keyFile := flag.String("key", "idp.key", "The private key file path")
flag.Parse()

baseURL, err := url.Parse(*baseURLstr)
if err != nil {
logr.Fatalf("cannot parse base URL: %v", err)
}

idpServer, err := samlidp.New(samlidp.Options{
URL: *baseURL,
Key: key,
Logger: logr,
Certificate: cert,
Store: &samlidp.MemoryStore{},
})
keyPair, err := tls.LoadX509KeyPair(*certFile, *keyFile)
if err != nil {
logr.Fatalf("%s", err)
logr.Fatalf("cannot load key pair: %v", err)
}

hashedPassword, _ := bcrypt.GenerateFromPassword([]byte("hunter2"), bcrypt.DefaultCost)
err = idpServer.Store.Put("/users/alice", samlidp.User{Name: "alice",
HashedPassword: hashedPassword,
Groups: []string{"Administrators", "Users"},
Email: "alice@example.com",
CommonName: "Alice Smith",
Surname: "Smith",
GivenName: "Alice",
})
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
if err != nil {
logr.Fatalf("%s", err)
logr.Fatalf("cannot parse certificate: %v", err)
}

err = idpServer.Store.Put("/users/bob", samlidp.User{
Name: "bob",
HashedPassword: hashedPassword,
Groups: []string{"Users"},
Email: "bob@example.com",
CommonName: "Bob Smith",
Surname: "Smith",
GivenName: "Bob",
idpServer, err := samlidp.New(samlidp.Options{
URL: *baseURL,
Key: keyPair.PrivateKey,
Logger: logr,
Certificate: keyPair.Leaf,
Store: &samlidp.MemoryStore{},
})
if err != nil {
logr.Fatalf("%s", err)
Expand Down
51 changes: 10 additions & 41 deletions example/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,45 +87,14 @@ func ServeWhoami(w http.ResponseWriter, r *http.Request) {
}
}

var (
key = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDU8wdiaFmPfTyRYuFlVPi866WrH/2JubkHzp89bBQopDaLXYxi
3PTu3O6Q/KaKxMOFBqrInwqpv/omOGZ4ycQ51O9I+Yc7ybVlW94lTo2gpGf+Y/8E
PsVbnZaFutRctJ4dVIp9aQ2TpLiGT0xX1OzBO/JEgq9GzDRf+B+eqSuglwIDAQAB
AoGBAMuy1eN6cgFiCOgBsB3gVDdTKpww87Qk5ivjqEt28SmXO13A1KNVPS6oQ8SJ
CT5Azc6X/BIAoJCURVL+LHdqebogKljhH/3yIel1kH19vr4E2kTM/tYH+qj8afUS
JEmArUzsmmK8ccuNqBcllqdwCZjxL4CHDUmyRudFcHVX9oyhAkEA/OV1OkjM3CLU
N3sqELdMmHq5QZCUihBmk3/N5OvGdqAFGBlEeewlepEVxkh7JnaNXAXrKHRVu/f/
fbCQxH+qrwJBANeQERF97b9Sibp9xgolb749UWNlAdqmEpmlvmS202TdcaaT1msU
4rRLiQN3X9O9mq4LZMSVethrQAdX1whawpkCQQDk1yGf7xZpMJ8F4U5sN+F4rLyM
Rq8Sy8p2OBTwzCUXXK+fYeXjybsUUMr6VMYTRP2fQr/LKJIX+E5ZxvcIyFmDAkEA
yfjNVUNVaIbQTzEbRlRvT6MqR+PTCefC072NF9aJWR93JimspGZMR7viY6IM4lrr
vBkm0F5yXKaYtoiiDMzlOQJADqmEwXl0D72ZG/2KDg8b4QZEmC9i5gidpQwJXUc6
hU+IVQoLxRq0fBib/36K9tcrrO5Ba4iEvDcNY+D8yGbUtA==
-----END RSA PRIVATE KEY-----
`)
cert = []byte(`-----BEGIN CERTIFICATE-----
MIIB7zCCAVgCCQDFzbKIp7b3MTANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGEwJV
UzELMAkGA1UECAwCR0ExDDAKBgNVBAoMA2ZvbzESMBAGA1UEAwwJbG9jYWxob3N0
MB4XDTEzMTAwMjAwMDg1MVoXDTE0MTAwMjAwMDg1MVowPDELMAkGA1UEBhMCVVMx
CzAJBgNVBAgMAkdBMQwwCgYDVQQKDANmb28xEjAQBgNVBAMMCWxvY2FsaG9zdDCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1PMHYmhZj308kWLhZVT4vOulqx/9
ibm5B86fPWwUKKQ2i12MYtz07tzukPymisTDhQaqyJ8Kqb/6JjhmeMnEOdTvSPmH
O8m1ZVveJU6NoKRn/mP/BD7FW52WhbrUXLSeHVSKfWkNk6S4hk9MV9TswTvyRIKv
Rsw0X/gfnqkroJcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCMMlIO+GNcGekevKgk
akpMdAqJfs24maGb90DvTLbRZRD7Xvn1MnVBBS9hzlXiFLYOInXACMW5gcoRFfeT
QLSouMM8o57h0uKjfTmuoWHLQLi6hnF+cvCsEFiJZ4AbF+DgmO6TarJ8O05t8zvn
OwJlNCASPZRH/JmF8tX0hoHuAQ==
-----END CERTIFICATE-----
`)
)

func main() {
rootURLstr := flag.String("url", "https://962766ce.ngrok.io", "The base URL of this service")
idpMetadataURLstr := flag.String("idp", "https://516becc2.ngrok.io/metadata", "The metadata URL for the IDP")
rootURLstr := flag.String("url", "http://localhost:8090", "The base URL of this service")
idpMetadataURLstr := flag.String("idp", "http://localhost:8080/metadata", "The metadata URL for the IDP")
certFile := flag.String("cert", "service.cert", "The certificate file path")
keyFile := flag.String("key", "service.key", "The private key file path")
flag.Parse()

keyPair, err := tls.X509KeyPair(cert, key)
keyPair, err := tls.LoadX509KeyPair(*certFile, *keyFile)
if err != nil {
panic(err) // TODO handle error
}
Expand Down Expand Up @@ -175,11 +144,11 @@ func main() {
}

mux := http.NewServeMux()
mux.Handle("GET /saml/", samlSP)
mux.HandleFunc("GET /{link}", ServeLink)
mux.Handle("/saml/", samlSP)
mux.HandleFunc("GET /links/{link}", ServeLink)
mux.Handle("GET /whoami", samlSP.RequireAccount(http.HandlerFunc(ServeWhoami)))
mux.Handle("POST /", samlSP.RequireAccount(http.HandlerFunc(CreateLink)))
mux.Handle("GET /", samlSP.RequireAccount(http.HandlerFunc(ListLinks)))
mux.Handle("POST /links", samlSP.RequireAccount(http.HandlerFunc(CreateLink)))
mux.Handle("GET /links", samlSP.RequireAccount(http.HandlerFunc(ListLinks)))

http.ListenAndServe(":8080", mux)
http.ListenAndServe(":8090", mux)
}
24 changes: 23 additions & 1 deletion identity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
SignatureMethod string
ValidDuration *time.Duration
ResponseFormTemplate *template.Template
SLOURL url.URL // SAML Single Logout URL
}

// Metadata returns the metadata structure for this identity provider.
Expand Down Expand Up @@ -186,6 +187,23 @@
}
}

// Add Single Logout Service endpoints to IDPSSODescriptor
for i, idpSSODescriptor := range ed.IDPSSODescriptors {
if idp.SLOURL.String() != "" {
idpSSODescriptor.SingleLogoutServices = []Endpoint{
{
Binding: HTTPRedirectBinding,
Location: idp.SLOURL.String(),
},
{
Binding: HTTPPostBinding,
Location: idp.SLOURL.String(),
},
}
ed.IDPSSODescriptors[i] = idpSSODescriptor
}
}

return ed
}

Expand Down Expand Up @@ -557,7 +575,7 @@

// MakeAssertion implements AssertionMaker. It produces a SAML assertion from the
// given request and assigns it to req.Assertion.
func (DefaultAssertionMaker) MakeAssertion(req *IdpAuthnRequest, session *Session) error {

Check failure on line 578 in identity_provider.go

View workflow job for this annotation

GitHub Actions / golangci

cyclomatic complexity 31 of func `(DefaultAssertionMaker).MakeAssertion` is high (> 30) (gocyclo)
attributes := []Attribute{}

var attributeConsumingService *AttributeConsumingService
Expand Down Expand Up @@ -784,7 +802,11 @@

nameIDFormat := "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"

if session.NameIDFormat != "" {
// Check if the SP has requested a specific NameID format in the AuthnRequest
if req.Request.NameIDPolicy != nil && req.Request.NameIDPolicy.Format != nil {
nameIDFormat = *req.Request.NameIDPolicy.Format
} else if session.NameIDFormat != "" {
// Fall back to session's format if available
nameIDFormat = session.NameIDFormat
}

Expand Down
5 changes: 5 additions & 0 deletions samlidp/samlidp.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Options struct {
//
// /metadata - the SAML metadata
// /sso - the SAML endpoint to initiate an authentication flow
// /slo - the SAML endpoint for single logout
// /login - prompt for a username and password if no session established
// /login/:shortcut - kick off an IDP-initiated authentication flow
// /services - RESTful interface to Service objects
Expand All @@ -54,6 +55,8 @@ func New(opts Options) (*Server, error) {
metadataURL.Path += "/metadata"
ssoURL := opts.URL
ssoURL.Path += "/sso"
sloURL := opts.URL
sloURL.Path += "/slo"
loginURL := opts.URL
loginURL.Path += "/login"
logr := opts.Logger
Expand All @@ -70,6 +73,7 @@ func New(opts Options) (*Server, error) {
Certificate: opts.Certificate,
MetadataURL: metadataURL,
SSOURL: ssoURL,
SLOURL: sloURL,
LoginURL: loginURL,
},
logger: logr,
Expand Down Expand Up @@ -102,6 +106,7 @@ func (s *Server) InitializeHTTP() {
mux.HandleFunc("/sso", func(w http.ResponseWriter, r *http.Request) {
s.IDP.ServeSSO(w, r)
})
mux.HandleFunc("/slo", s.HandleSLO)

mux.HandleFunc("/login", s.HandleLogin)
mux.HandleFunc("/login/{shortcut}", s.HandleIDPInitiated)
Expand Down
Loading
Loading