diff --git a/attribute.go b/attribute.go
index 6b63cd5..c0cf8df 100644
--- a/attribute.go
+++ b/attribute.go
@@ -26,7 +26,11 @@ func (vals Values) Get(k string) string {
return ""
}
if v, ok := vals[k]; ok && len(v.Values) > 0 {
- return string(v.Values[0].Value)
+ if len(v.Values[0].ValueXML) != 0 {
+ return string(v.Values[0].ValueXML)
+ } else {
+ return string(v.Values[0].Value)
+ }
}
return ""
}
@@ -57,7 +61,11 @@ func (vals Values) GetAll(k string) []string {
if v, ok := vals[k]; ok && len(v.Values) > 0 {
for i := 0; i < len(v.Values); i++ {
- av = append(av, string(v.Values[i].Value))
+ if len(v.Values[i].ValueXML) != 0 {
+ av = append(av, string(v.Values[i].ValueXML))
+ } else {
+ av = append(av, string(v.Values[i].Value))
+ }
}
}
diff --git a/saml_test.go b/saml_test.go
index 0a4d575..0a8f895 100644
--- a/saml_test.go
+++ b/saml_test.go
@@ -180,6 +180,7 @@ func TestSAML(t *testing.T) {
require.Equal(t, "Phoebe", assertionInfo.Values.Get("FirstName"))
require.Equal(t, "Simon", assertionInfo.Values.Get("LastName"))
require.Equal(t, "phoebesimon", assertionInfo.Values.Get("Login"))
+ require.Equal(t, "sales@acme.comsupport@acme.com", assertionInfo.Values.Get("emailAddress"))
assertionInfoModifiedAudience := signResponse(t, assertionInfoModifiedAudienceResponse, sp)
diff --git a/test_constants.go b/test_constants.go
index 4707275..6cdce3c 100644
--- a/test_constants.go
+++ b/test_constants.go
@@ -52,7 +52,7 @@ TxkXxsoKNW0awJNpWRbU81QpheMFfENIzLam4Itc/5kSZAaSy/9e2QKfo4jBo/MMbCq2vM9TyeJQ
DJpRaioUTd2lGh4TLUxAxCxtUk/pascL+3Nn936LFmUCLxaxnbeGzPOXAhscCtU1H0nFsXRnKx5a
cPXYSKFZZZktieSkww2Oi8dg2DYaQhGQMSFMVqgVfwEu4bvCRBvdSiNXdWGCZQmFVzBZZ/9rOLzP
pvTFTPnpkavJm81FLlUhiE/oFgKlCDLWDknSpXAI0uZGERcwPca6xvIMh86LjQKjbVci9FYDStXC
-qRnqQ+TccSu/B6uONFsDEngGcXSKfB+aphoebe.simon@scaleft.com123urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransportPhoebeSimonphoebe.simon@scaleft.comphoebesimon`
+qRnqQ+TccSu/B6uONFsDEngGcXSKfB+aphoebe.simon@scaleft.com123urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransportPhoebeSimonphoebe.simon@scaleft.comphoebesimonsales@acme.comsupport@acme.com`
const manInTheMiddledResponse = `
http://www.okta.com/exk5zt0r12Edi4rD20h7ijTqmVmDy7ssK+rvmJaCQ6AQaFaXz+HIN/r6O37B0eQ=G09fAYXGDLK+/jAekHsNL0RLo40Xm6+VwXmUj0IDIrvIIv/mJU5VD6ylOLnPezLDBVY9BJst1YCz+8krdvmQ8Stkd6qiN2bN/5KpCdika111YGpeNdMmg/E57ZG3S895hTNJQYOfCwhPFUtQuXLkspOaw81pcqOTr+bVSofJ8uQP7cVQa/ANxbjKAj0fhAuxAvZfiqPms5Stv4sNGpzULUDJl87CoEleHExGmpTsI7Qt3EvGToPMZXPHF4MGvuC0Z2ZD4iI6Pr7xk98t54PJtAX2qJu1tZqBJmL0Qcq5spl9W3yC1tAZuDeFLm1C4/T9crO2Q5WILP/tkw/yJ+ZttQ==MIIDpDCCAoygAwIBAgIGAVLIBhAwMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYDVQQGEwJVUzETMBEG
diff --git a/types/response.go b/types/response.go
index 2a54c46..5e292a5 100644
--- a/types/response.go
+++ b/types/response.go
@@ -1,11 +1,11 @@
// Copyright 2016 Russell Haering et al.
-//
+//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
-//
+//
// https://www.apache.org/licenses/LICENSE-2.0
-//
+//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -47,15 +47,15 @@ type Response struct {
}
type LogoutResponse struct {
- XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol LogoutResponse"`
- ID string `xml:"ID,attr"`
- InResponseTo string `xml:"InResponseTo,attr"`
- Destination string `xml:"Destination,attr"`
- Version string `xml:"Version,attr"`
- IssueInstant time.Time `xml:"IssueInstant,attr"`
- Status *Status `xml:"Status"`
- Issuer *Issuer `xml:"Issuer"`
- SignatureValidated bool `xml:"-"` // not read, not dumped
+ XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:protocol LogoutResponse"`
+ ID string `xml:"ID,attr"`
+ InResponseTo string `xml:"InResponseTo,attr"`
+ Destination string `xml:"Destination,attr"`
+ Version string `xml:"Version,attr"`
+ IssueInstant time.Time `xml:"IssueInstant,attr"`
+ Status *Status `xml:"Status"`
+ Issuer *Issuer `xml:"Issuer"`
+ SignatureValidated bool `xml:"-"` // not read, not dumped
}
type Status struct {
@@ -168,18 +168,19 @@ type Attribute struct {
}
type AttributeValue struct {
- XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion AttributeValue"`
- Type string `xml:"xsi:type,attr"`
- Value string `xml:",chardata"`
+ XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion AttributeValue"`
+ Type string `xml:"xsi:type,attr"`
+ Value string `xml:",chardata"`
+ ValueXML string `xml:",innerxml"`
}
type AuthnStatement struct {
- XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthnStatement"`
- //Section 4.1.4.2 - https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
- //If the identity provider supports the Single Logout profile, defined in Section 4.4
- //, any such authentication statements MUST include a SessionIndex attribute to enable
- //per-session logout requests by the service provider.
- SessionIndex string `xml:"SessionIndex,attr,omitempty"`
+ XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:assertion AuthnStatement"`
+ //Section 4.1.4.2 - https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
+ //If the identity provider supports the Single Logout profile, defined in Section 4.4
+ //, any such authentication statements MUST include a SessionIndex attribute to enable
+ //per-session logout requests by the service provider.
+ SessionIndex string `xml:"SessionIndex,attr,omitempty"`
AuthnInstant *time.Time `xml:"AuthnInstant,attr,omitempty"`
SessionNotOnOrAfter *time.Time `xml:"SessionNotOnOrAfter,attr,omitempty"`
AuthnContext *AuthnContext `xml:"AuthnContext"`