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:
Livio Spring
2024-05-23 07:04:07 +02:00
committed by GitHub
parent 12be21a3ff
commit e57a9b57c8
58 changed files with 1306 additions and 720 deletions

View File

@@ -2774,6 +2774,8 @@ func TestIDPTemplateProjection_reducesSAML(t *testing.T) {
},
"certificate": `+stringToJSONByte("certificate")+`,
"binding": "binding",
"nameIDFormat": 3,
"transientMappingAttributeName": "customAttribute",
"withSignedRequest": true,
"isCreationAllowed": true,
"isLinkingAllowed": true,
@@ -2810,7 +2812,7 @@ func TestIDPTemplateProjection_reducesSAML(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.idp_templates6_saml (idp_id, instance_id, metadata, key, certificate, binding, with_signed_request) VALUES ($1, $2, $3, $4, $5, $6, $7)",
expectedStmt: "INSERT INTO projections.idp_templates6_saml (idp_id, instance_id, metadata, key, certificate, binding, with_signed_request, transient_mapping_attribute_name, name_id_format) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"idp-id",
"instance-id",
@@ -2819,6 +2821,8 @@ func TestIDPTemplateProjection_reducesSAML(t *testing.T) {
anyArg{},
"binding",
true,
"customAttribute",
domain.SAMLNameIDFormatTransient,
},
},
},
@@ -2842,6 +2846,8 @@ func TestIDPTemplateProjection_reducesSAML(t *testing.T) {
},
"certificate": `+stringToJSONByte("certificate")+`,
"binding": "binding",
"nameIDFormat": 3,
"transientMappingAttributeName": "customAttribute",
"withSignedRequest": true,
"isCreationAllowed": true,
"isLinkingAllowed": true,
@@ -2878,7 +2884,7 @@ func TestIDPTemplateProjection_reducesSAML(t *testing.T) {
},
},
{
expectedStmt: "INSERT INTO projections.idp_templates6_saml (idp_id, instance_id, metadata, key, certificate, binding, with_signed_request) VALUES ($1, $2, $3, $4, $5, $6, $7)",
expectedStmt: "INSERT INTO projections.idp_templates6_saml (idp_id, instance_id, metadata, key, certificate, binding, with_signed_request, transient_mapping_attribute_name, name_id_format) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)",
expectedArgs: []interface{}{
"idp-id",
"instance-id",
@@ -2887,6 +2893,8 @@ func TestIDPTemplateProjection_reducesSAML(t *testing.T) {
anyArg{},
"binding",
true,
"customAttribute",
domain.SAMLNameIDFormatTransient,
},
},
},