You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Aside from simplifying configuration, this commit also makes it possible
to provide a response authentication converter that doesn't need the
NameID element to be present.
Closesgh-12136
In Spring Security 6, the order of authenticating a `<saml2:Response>` is as follows:
65
+
66
+
1. Verify the Response Signature, if any
67
+
2. Decrypt the Response
68
+
3. Validate Response attributes, like Destination and Issuer
69
+
4. For each assertion, verify the signature, decrypt, and then validate its fields
70
+
5. Check to ensure that the response has at least one assertion with a name field
71
+
72
+
This ordering sometimes poses challenges since some response validation is being done in Step 3 and some in Step 5.
73
+
Specifically, this poses a chellenge when an application doesn't have a name field and doesn't need it to be validated.
74
+
75
+
In Spring Security 7, this is simplified by moving response validation to after assertion validation and combining the two separate validation steps 3 and 5.
76
+
When this is complete, response validation will no longer check for the existence of the `NameID` attribute and rely on ``ResponseAuthenticationConverter``s to do this.
77
+
78
+
This will add support ``ResponseAuthenticationConverter``s that don't use the `NameID` element in their `Authentication` instance and so don't need it validated.
79
+
80
+
To opt-in to this behavior in advance, use `OpenSaml5AuthenticationProvider#setValidateResponseAfterAssertions` to `true` like so:
81
+
82
+
[tabs]
83
+
======
84
+
Java::
85
+
+
86
+
[source,java,role="primary"]
87
+
----
88
+
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
This will change the authentication steps as follows:
102
+
103
+
1. Verify the Response Signature, if any
104
+
2. Decrypt the Response
105
+
3. For each assertion, verify the signature, decrypt, and then validate its fields
106
+
4. Validate Response attributes, like Destination and Issuer
107
+
108
+
Note that if you have a custom response authentication converter, then you are now responsible to check if the `NameID` element exists in the event that you need it.
109
+
110
+
Alternatively to updating your response authentication converter, you can specify a custom `ResponseValidator` that adds back in the check for the `NameID` element as follows:
111
+
112
+
[tabs]
113
+
======
114
+
Java::
115
+
+
116
+
[source,java,role="primary"]
117
+
----
118
+
OpenSaml5AuthenticationProvider provider = new OpenSaml5AuthenticationProvider();
Copy file name to clipboardExpand all lines: docs/modules/ROOT/pages/servlet/saml2/login/authentication.adoc
+195
Original file line number
Diff line number
Diff line change
@@ -250,12 +250,135 @@ class SecurityConfig {
250
250
----
251
251
======
252
252
253
+
== Converting an `Assertion` into an `Authentication`
254
+
255
+
`OpenSamlXAuthenticationProvider#setResponseAuthenticationConverter` provides a way for you to change how it converts your assertion into an `Authentication` instance.
256
+
257
+
You can set a custom converter in the following way:
open fun convert(responseToken: ResponseToken): Saml2Authentication {
361
+
val authentication = this.delegate.convert(responseToken) <1>
362
+
val principal = this.userDetailsService.loadByUsername(username) <2>
363
+
val saml2Response = authentication.getSaml2Response()
364
+
val authorities = principal.getAuthorities()
365
+
return Saml2Authentication(userDetails as AuthenticatedPrincipal, saml2Response, authorities) <3>
366
+
}
367
+
368
+
}
369
+
----
370
+
======
371
+
<1> First, call the default converter, which extracts attributes and authorities from the response
372
+
<2> Second, call the xref:servlet/authentication/passwords/user-details-service.adoc#servlet-authentication-userdetailsservice[`UserDetailsService`] using the relevant information
373
+
<3> Third, return an authentication that includes the user details
374
+
375
+
[TIP]
376
+
====
377
+
If your `UserDetailsService` returns a value that also implements `AuthenticatedPrincipal`, then you don't need a custom authentication implementation.
378
+
====
379
+
380
+
Or, if you are using OpenSaml 4, then you can achieve something similar as follows:
381
+
259
382
[tabs]
260
383
======
261
384
Java::
@@ -336,6 +459,78 @@ open class SecurityConfig {
336
459
It's not required to call ``OpenSaml4AuthenticationProvider``'s default authentication converter.
337
460
It returns a `Saml2AuthenticatedPrincipal` containing the attributes it extracted from ``AttributeStatement``s as well as the single `ROLE_USER` authority.
338
461
462
+
=== Configuring the Principal Name
463
+
464
+
Sometimes, the principal name is not in the `<saml2:NameID>` element.
465
+
In that case, you can configure the `ResponseAuthenticationConverter` with a custom strategy like so:
0 commit comments