@@ -2,6 +2,7 @@ package samlsp
22
33import (
44 "bytes"
5+ "crypto"
56 "crypto/rsa"
67 "crypto/sha256"
78 "crypto/x509"
@@ -520,3 +521,122 @@ func TestMiddlewareHandlesInvalidResponse(t *testing.T) {
520521 assert .Check (t , is .Equal ("" , resp .Header ().Get ("Location" )))
521522 assert .Check (t , is .Equal ("" , resp .Header ().Get ("Set-Cookie" )))
522523}
524+
525+ type mockSigner struct {
526+ signer crypto.Signer
527+ }
528+
529+ func (m * mockSigner ) Public () crypto.PublicKey {
530+ return m .signer .Public ()
531+ }
532+
533+ func (m * mockSigner ) Sign (rand io.Reader , digest []byte , opts crypto.SignerOpts ) ([]byte , error ) {
534+ return m .signer .Sign (rand , digest , opts )
535+ }
536+
537+ func newMockRSASigner (t * testing.T ) crypto.Signer {
538+ key := mustParsePrivateKey (golden .Get (t , "key.pem" ))
539+ return & mockSigner {signer : key .(crypto.Signer )}
540+ }
541+
542+ func TestMiddleware_WithCryptoSignerE2E (t * testing.T ) {
543+ saml .TimeNow = func () time.Time {
544+ rv , _ := time .Parse ("Mon Jan 2 15:04:05.999999999 MST 2006" , "Mon Dec 1 01:57:09.123456789 UTC 2015" )
545+ return rv
546+ }
547+ saml .Clock = dsig .NewFakeClockAt (saml .TimeNow ())
548+ saml .RandReader = & testRandomReader {}
549+
550+ cert := mustParseCertificate (golden .Get (t , "cert.pem" ))
551+ idpMetadata := golden .Get (t , "idp_metadata.xml" )
552+
553+ var metadata saml.EntityDescriptor
554+ if err := xml .Unmarshal (idpMetadata , & metadata ); err != nil {
555+ panic (err )
556+ }
557+
558+ mockSigner := newMockRSASigner (t )
559+
560+ opts := Options {
561+ URL : mustParseURL ("https://15661444.ngrok.io/" ),
562+ Key : mockSigner ,
563+ Certificate : cert ,
564+ IDPMetadata : & metadata ,
565+ }
566+
567+ middleware , err := New (opts )
568+ assert .Check (t , err )
569+
570+ sessionProvider := DefaultSessionProvider (opts )
571+ sessionProvider .Name = "ttt"
572+ sessionProvider .MaxAge = 7200 * time .Second
573+
574+ sessionCodec := sessionProvider .Codec .(JWTSessionCodec )
575+ sessionCodec .MaxAge = 7200 * time .Second
576+ sessionProvider .Codec = sessionCodec
577+
578+ middleware .Session = sessionProvider
579+ middleware .ServiceProvider .MetadataURL .Path = "/saml2/metadata"
580+ middleware .ServiceProvider .AcsURL .Path = "/saml2/acs"
581+ middleware .ServiceProvider .SloURL .Path = "/saml2/slo"
582+
583+ t .Run ("SessionEncodeDecode" , func (t * testing.T ) {
584+ var tc JWTSessionClaims
585+ if err := json .Unmarshal (golden .Get (t , "token.json" ), & tc ); err != nil {
586+ t .Fatal (err )
587+ }
588+
589+ encoded , err := sessionProvider .Codec .Encode (tc )
590+ assert .Check (t , err )
591+ assert .Assert (t , encoded != "" )
592+
593+ decoded , err := sessionProvider .Codec .Decode (encoded )
594+ assert .Check (t , err )
595+ decodedClaims := decoded .(JWTSessionClaims )
596+ assert .Equal (t , tc .Subject , decodedClaims .Subject )
597+ })
598+
599+ t .Run ("TrackedRequestEncodeDecode" , func (t * testing.T ) {
600+ codec := middleware .RequestTracker .(CookieRequestTracker ).Codec
601+ trackedReq := TrackedRequest {
602+ Index : "test-index" ,
603+ SAMLRequestID : "test-request-id" ,
604+ URI : "/test-uri" ,
605+ }
606+
607+ encoded , err := codec .Encode (trackedReq )
608+ assert .Check (t , err )
609+ assert .Assert (t , encoded != "" )
610+
611+ decoded , err := codec .Decode (encoded )
612+ assert .Check (t , err )
613+ assert .Equal (t , trackedReq .Index , decoded .Index )
614+ assert .Equal (t , trackedReq .SAMLRequestID , decoded .SAMLRequestID )
615+ })
616+
617+ t .Run ("RequireAccountFlow" , func (t * testing.T ) {
618+ handler := middleware .RequireAccount (
619+ http .HandlerFunc (func (_ http.ResponseWriter , _ * http.Request ) {
620+ panic ("not reached" )
621+ }))
622+
623+ req , _ := http .NewRequest ("GET" , "/protected" , nil )
624+ resp := httptest .NewRecorder ()
625+ handler .ServeHTTP (resp , req )
626+
627+ assert .Check (t , is .Equal (http .StatusFound , resp .Code ))
628+ assert .Assert (t , resp .Header ().Get ("Location" ) != "" )
629+ assert .Assert (t , resp .Header ().Get ("Set-Cookie" ) != "" )
630+ })
631+
632+ t .Run ("Metadata" , func (t * testing.T ) {
633+ req , _ := http .NewRequest ("GET" , "/saml2/metadata" , nil )
634+ resp := httptest .NewRecorder ()
635+ middleware .ServeHTTP (resp , req )
636+
637+ assert .Check (t , is .Equal (http .StatusOK , resp .Code ))
638+ assert .Check (t , is .Equal ("application/samlmetadata+xml" ,
639+ resp .Header ().Get ("Content-type" )))
640+ golden .Assert (t , resp .Body .String (), "expected_middleware_metadata.xml" )
641+ })
642+ }
0 commit comments