Skip to content

Commit

Permalink
Allow ValidUntil to be optional
Browse files Browse the repository at this point in the history
  • Loading branch information
wz2b committed Dec 27, 2024
1 parent 5c1ab6f commit d4de748
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 24 deletions.
17 changes: 10 additions & 7 deletions identity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,20 @@ type IdentityProvider struct {
func (idp *IdentityProvider) Metadata() *EntityDescriptor {
certStr := base64.StdEncoding.EncodeToString(idp.Certificate.Raw)

var validDuration time.Duration
if idp.ValidDuration != nil {
validDuration = *idp.ValidDuration
} else {
validDuration = DefaultValidDuration
var validUntil *time.Time

if idp.ValidDuration == nil {
// To avoid breaking backward compatibility, nil here means default
defaultValid := time.Now().Add(DefaultValidDuration)
validUntil = &defaultValid
} else if *(idp.ValidDuration) == METADATA_OMIT_VALID_UNTIL {
validUntil = nil
}

ed := &EntityDescriptor{
EntityID: idp.MetadataURL.String(),
ValidUntil: TimeNow().Add(validDuration),
CacheDuration: validDuration,
ValidUntil: validUntil,
CacheDuration: idp.ValidDuration,
IDPSSODescriptors: []IDPSSODescriptor{
{
SSODescriptor: SSODescriptor{
Expand Down
53 changes: 40 additions & 13 deletions metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ var Metadata = struct{}{}
//
// See http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf §2.3.2
type EntityDescriptor struct {
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntityDescriptor"`
EntityID string `xml:"entityID,attr"`
ID string `xml:",attr,omitempty"`
ValidUntil time.Time `xml:"validUntil,attr,omitempty"`
CacheDuration time.Duration `xml:"cacheDuration,attr,omitempty"`
XMLName xml.Name `xml:"urn:oasis:names:tc:SAML:2.0:metadata EntityDescriptor"`
EntityID string `xml:"entityID,attr"`
ID string `xml:",attr,omitempty"`
ValidUntil *time.Time `xml:"validUntil,attr,omitempty"`
CacheDuration *time.Duration `xml:"cacheDuration,attr,omitempty"`
Signature *etree.Element
RoleDescriptors []RoleDescriptor `xml:"RoleDescriptor"`
IDPSSODescriptors []IDPSSODescriptor `xml:"IDPSSODescriptor"`
Expand All @@ -69,16 +69,31 @@ type EntityDescriptor struct {
AdditionalMetadataLocations []string `xml:"AdditionalMetadataLocation"`
}

const METADATA_OMIT_VALID_UNTIL = -1

// MarshalXML implements xml.Marshaler
func (m EntityDescriptor) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
type Alias EntityDescriptor
var rt *RelaxedTime

var cacheDuration *Duration
if m.CacheDuration != nil {
d := Duration(*m.CacheDuration)
cacheDuration = &d
}

if m.ValidUntil != nil {
rttemp := RelaxedTime(*m.ValidUntil)
rt = &rttemp
}

aux := &struct {
ValidUntil RelaxedTime `xml:"validUntil,attr,omitempty"`
CacheDuration Duration `xml:"cacheDuration,attr,omitempty"`
ValidUntil *RelaxedTime `xml:"validUntil,attr,omitempty"`
CacheDuration *Duration `xml:"cacheDuration,attr,omitempty"`
*Alias
}{
ValidUntil: RelaxedTime(m.ValidUntil),
CacheDuration: Duration(m.CacheDuration),
ValidUntil: rt,
CacheDuration: cacheDuration,
Alias: (*Alias)(&m),
}
return e.Encode(aux)
Expand All @@ -88,17 +103,29 @@ func (m EntityDescriptor) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
func (m *EntityDescriptor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type Alias EntityDescriptor
aux := &struct {
ValidUntil RelaxedTime `xml:"validUntil,attr,omitempty"`
CacheDuration Duration `xml:"cacheDuration,attr,omitempty"`
ValidUntil *RelaxedTime `xml:"validUntil,attr,omitempty"`
CacheDuration *Duration `xml:"cacheDuration,attr,omitempty"`
*Alias
}{
Alias: (*Alias)(m),
}
if err := d.DecodeElement(aux, &start); err != nil {
return err
}
m.ValidUntil = time.Time(aux.ValidUntil)
m.CacheDuration = time.Duration(aux.CacheDuration)

if aux.ValidUntil != nil {
t := time.Time(*aux.ValidUntil)
m.ValidUntil = &t
} else {
m.ValidUntil = nil
}

if aux.CacheDuration != nil {
d := time.Duration(*aux.CacheDuration)
m.CacheDuration = &d
} else {
m.ValidUntil = nil
}
return nil
}

Expand Down
13 changes: 9 additions & 4 deletions service_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,14 +143,19 @@ const DefaultCacheDuration = time.Hour * 24 * 1

// Metadata returns the service provider metadata
func (sp *ServiceProvider) Metadata() *EntityDescriptor {
validDuration := DefaultValidDuration
var validUntil *time.Time
now := TimeNow()

if sp.MetadataValidDuration > 0 {
validDuration = sp.MetadataValidDuration
*validUntil = now.Add(sp.MetadataValidDuration)
} else if sp.MetadataValidDuration == METADATA_OMIT_VALID_UNTIL {
validUntil = nil
} else {
*validUntil = now.Add(DefaultValidDuration)
}

authnRequestsSigned := len(sp.SignatureMethod) > 0
wantAssertionsSigned := true
validUntil := TimeNow().Add(validDuration)

var keyDescriptors []KeyDescriptor
if sp.Certificate != nil {
Expand Down Expand Up @@ -209,7 +214,7 @@ func (sp *ServiceProvider) Metadata() *EntityDescriptor {
RoleDescriptor: RoleDescriptor{
ProtocolSupportEnumeration: "urn:oasis:names:tc:SAML:2.0:protocol",
KeyDescriptors: keyDescriptors,
ValidUntil: &validUntil,
ValidUntil: validUntil,
},
SingleLogoutServices: sloEndpoints,
NameIDFormats: []NameIDFormat{sp.AuthnNameIDFormat},
Expand Down

0 comments on commit d4de748

Please sign in to comment.