mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 19:17:32 +00:00
feat(saml): allow setting nameid-format and alternative mapping for transient format (#7979)
# Which Problems Are Solved ZITADEL currently always uses `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent` in SAML requests, relying on the IdP to respect that flag and always return a peristent nameid in order to be able to map the external user with an existing user (idp link) in ZITADEL. In case the IdP however returns a `urn:oasis:names:tc:SAML:2.0:nameid-format:transient` (transient) nameid, the attribute will differ between each request and it will not be possible to match existing users. # How the Problems Are Solved This PR adds the following two options on SAML IdP: - **nameIDFormat**: allows to set the nameid-format used in the SAML Request - **transientMappingAttributeName**: allows to set an attribute name, which will be used instead of the nameid itself in case the returned nameid-format is transient # Additional Changes To reduce impact on current installations, the `idp_templates6_saml` table is altered with the two added columns by a setup job. New installations will automatically get the table with the two columns directly. All idp unit tests are updated to use `expectEventstore` instead of the deprecated `eventstoreExpect`. # Additional Context Closes #7483 Closes #7743 --------- Co-authored-by: peintnermax <max@caos.ch> Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package idp
|
||||
|
||||
import (
|
||||
"github.com/zitadel/zitadel/internal/crypto"
|
||||
"github.com/zitadel/zitadel/internal/domain"
|
||||
"github.com/zitadel/zitadel/internal/eventstore"
|
||||
"github.com/zitadel/zitadel/internal/zerrors"
|
||||
)
|
||||
@@ -9,13 +10,15 @@ import (
|
||||
type SAMLIDPAddedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Metadata []byte `json:"metadata,omitempty"`
|
||||
Key *crypto.CryptoValue `json:"key,omitempty"`
|
||||
Certificate []byte `json:"certificate,omitempty"`
|
||||
Binding string `json:"binding,omitempty"`
|
||||
WithSignedRequest bool `json:"withSignedRequest,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Metadata []byte `json:"metadata,omitempty"`
|
||||
Key *crypto.CryptoValue `json:"key,omitempty"`
|
||||
Certificate []byte `json:"certificate,omitempty"`
|
||||
Binding string `json:"binding,omitempty"`
|
||||
WithSignedRequest bool `json:"withSignedRequest,omitempty"`
|
||||
NameIDFormat *domain.SAMLNameIDFormat `json:"nameIDFormat,omitempty"`
|
||||
TransientMappingAttributeName string `json:"transientMappingAttributeName,omitempty"`
|
||||
Options
|
||||
}
|
||||
|
||||
@@ -28,18 +31,22 @@ func NewSAMLIDPAddedEvent(
|
||||
certificate []byte,
|
||||
binding string,
|
||||
withSignedRequest bool,
|
||||
nameIDFormat *domain.SAMLNameIDFormat,
|
||||
transientMappingAttributeName string,
|
||||
options Options,
|
||||
) *SAMLIDPAddedEvent {
|
||||
return &SAMLIDPAddedEvent{
|
||||
BaseEvent: *base,
|
||||
ID: id,
|
||||
Name: name,
|
||||
Metadata: metadata,
|
||||
Key: key,
|
||||
Certificate: certificate,
|
||||
Binding: binding,
|
||||
WithSignedRequest: withSignedRequest,
|
||||
Options: options,
|
||||
BaseEvent: *base,
|
||||
ID: id,
|
||||
Name: name,
|
||||
Metadata: metadata,
|
||||
Key: key,
|
||||
Certificate: certificate,
|
||||
Binding: binding,
|
||||
WithSignedRequest: withSignedRequest,
|
||||
NameIDFormat: nameIDFormat,
|
||||
TransientMappingAttributeName: transientMappingAttributeName,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,13 +74,15 @@ func SAMLIDPAddedEventMapper(event eventstore.Event) (eventstore.Event, error) {
|
||||
type SAMLIDPChangedEvent struct {
|
||||
eventstore.BaseEvent `json:"-"`
|
||||
|
||||
ID string `json:"id"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Metadata []byte `json:"metadata,omitempty"`
|
||||
Key *crypto.CryptoValue `json:"key,omitempty"`
|
||||
Certificate []byte `json:"certificate,omitempty"`
|
||||
Binding *string `json:"binding,omitempty"`
|
||||
WithSignedRequest *bool `json:"withSignedRequest,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Metadata []byte `json:"metadata,omitempty"`
|
||||
Key *crypto.CryptoValue `json:"key,omitempty"`
|
||||
Certificate []byte `json:"certificate,omitempty"`
|
||||
Binding *string `json:"binding,omitempty"`
|
||||
WithSignedRequest *bool `json:"withSignedRequest,omitempty"`
|
||||
NameIDFormat *domain.SAMLNameIDFormat `json:"nameIDFormat,omitempty"`
|
||||
TransientMappingAttributeName *string `json:"transientMappingAttributeName,omitempty"`
|
||||
OptionChanges
|
||||
}
|
||||
|
||||
@@ -133,6 +142,18 @@ func ChangeSAMLWithSignedRequest(withSignedRequest bool) func(*SAMLIDPChangedEve
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSAMLNameIDFormat(nameIDFormat *domain.SAMLNameIDFormat) func(*SAMLIDPChangedEvent) {
|
||||
return func(e *SAMLIDPChangedEvent) {
|
||||
e.NameIDFormat = nameIDFormat
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSAMLTransientMappingAttributeName(name string) func(*SAMLIDPChangedEvent) {
|
||||
return func(e *SAMLIDPChangedEvent) {
|
||||
e.TransientMappingAttributeName = &name
|
||||
}
|
||||
}
|
||||
|
||||
func ChangeSAMLOptions(options OptionChanges) func(*SAMLIDPChangedEvent) {
|
||||
return func(e *SAMLIDPChangedEvent) {
|
||||
e.OptionChanges = options
|
||||
|
Reference in New Issue
Block a user