17
17
package org .springframework .security .saml2 .provider .service .registration ;
18
18
19
19
import java .io .IOException ;
20
- import java .io .InputStream ;
21
- import java .security .cert .CertificateException ;
22
- import java .security .cert .X509Certificate ;
23
- import java .util .ArrayList ;
24
20
import java .util .Arrays ;
25
21
import java .util .List ;
26
22
27
- import net .shibboleth .utilities .java .support .xml .ParserPool ;
28
- import org .opensaml .core .config .ConfigurationService ;
29
- import org .opensaml .core .xml .XMLObject ;
30
- import org .opensaml .core .xml .config .XMLObjectProviderRegistry ;
31
- import org .opensaml .core .xml .io .Unmarshaller ;
32
- import org .opensaml .saml .common .xml .SAMLConstants ;
33
- import org .opensaml .saml .saml2 .metadata .EntitiesDescriptor ;
34
- import org .opensaml .saml .saml2 .metadata .EntityDescriptor ;
35
- import org .opensaml .saml .saml2 .metadata .IDPSSODescriptor ;
36
- import org .opensaml .saml .saml2 .metadata .KeyDescriptor ;
37
- import org .opensaml .saml .saml2 .metadata .SingleSignOnService ;
38
- import org .opensaml .security .credential .UsageType ;
39
- import org .opensaml .xmlsec .keyinfo .KeyInfoSupport ;
40
- import org .w3c .dom .Document ;
41
- import org .w3c .dom .Element ;
42
-
43
23
import org .springframework .http .HttpInputMessage ;
44
24
import org .springframework .http .HttpOutputMessage ;
45
25
import org .springframework .http .MediaType ;
46
26
import org .springframework .http .converter .HttpMessageConverter ;
47
27
import org .springframework .http .converter .HttpMessageNotReadableException ;
48
28
import org .springframework .http .converter .HttpMessageNotWritableException ;
49
- import org .springframework .security .saml2 .Saml2Exception ;
50
29
import org .springframework .security .saml2 .core .OpenSamlInitializationService ;
51
- import org .springframework .security .saml2 .core .Saml2X509Credential ;
52
30
53
31
/**
54
32
* An {@link HttpMessageConverter} that takes an {@code IDPSSODescriptor} in an HTTP
@@ -84,16 +62,13 @@ public class OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter
84
62
OpenSamlInitializationService .initialize ();
85
63
}
86
64
87
- private final XMLObjectProviderRegistry registry ;
88
-
89
- private final ParserPool parserPool ;
65
+ private final OpenSamlAssertingPartyMetadataConverter converter ;
90
66
91
67
/**
92
68
* Creates a {@link OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter}
93
69
*/
94
70
public OpenSamlRelyingPartyRegistrationBuilderHttpMessageConverter () {
95
- this .registry = ConfigurationService .get (XMLObjectProviderRegistry .class );
96
- this .parserPool = this .registry .getParserPool ();
71
+ this .converter = new OpenSamlAssertingPartyMetadataConverter ();
97
72
}
98
73
99
74
@ Override
@@ -114,101 +89,7 @@ public List<MediaType> getSupportedMediaTypes() {
114
89
@ Override
115
90
public RelyingPartyRegistration .Builder read (Class <? extends RelyingPartyRegistration .Builder > clazz ,
116
91
HttpInputMessage inputMessage ) throws IOException , HttpMessageNotReadableException {
117
- EntityDescriptor descriptor = entityDescriptor (inputMessage .getBody ());
118
- IDPSSODescriptor idpssoDescriptor = descriptor .getIDPSSODescriptor (SAMLConstants .SAML20P_NS );
119
- if (idpssoDescriptor == null ) {
120
- throw new Saml2Exception ("Metadata response is missing the necessary IDPSSODescriptor element" );
121
- }
122
- List <Saml2X509Credential > verification = new ArrayList <>();
123
- List <Saml2X509Credential > encryption = new ArrayList <>();
124
- for (KeyDescriptor keyDescriptor : idpssoDescriptor .getKeyDescriptors ()) {
125
- if (keyDescriptor .getUse ().equals (UsageType .SIGNING )) {
126
- List <X509Certificate > certificates = certificates (keyDescriptor );
127
- for (X509Certificate certificate : certificates ) {
128
- verification .add (Saml2X509Credential .verification (certificate ));
129
- }
130
- }
131
- if (keyDescriptor .getUse ().equals (UsageType .ENCRYPTION )) {
132
- List <X509Certificate > certificates = certificates (keyDescriptor );
133
- for (X509Certificate certificate : certificates ) {
134
- encryption .add (Saml2X509Credential .encryption (certificate ));
135
- }
136
- }
137
- if (keyDescriptor .getUse ().equals (UsageType .UNSPECIFIED )) {
138
- List <X509Certificate > certificates = certificates (keyDescriptor );
139
- for (X509Certificate certificate : certificates ) {
140
- verification .add (Saml2X509Credential .verification (certificate ));
141
- encryption .add (Saml2X509Credential .encryption (certificate ));
142
- }
143
- }
144
- }
145
- if (verification .isEmpty ()) {
146
- throw new Saml2Exception (
147
- "Metadata response is missing verification certificates, necessary for verifying SAML assertions" );
148
- }
149
- RelyingPartyRegistration .Builder builder = RelyingPartyRegistration .withRegistrationId (descriptor .getEntityID ())
150
- .assertingPartyDetails ((party ) -> party .entityId (descriptor .getEntityID ())
151
- .wantAuthnRequestsSigned (Boolean .TRUE .equals (idpssoDescriptor .getWantAuthnRequestsSigned ()))
152
- .verificationX509Credentials ((c ) -> c .addAll (verification ))
153
- .encryptionX509Credentials ((c ) -> c .addAll (encryption )));
154
- for (SingleSignOnService singleSignOnService : idpssoDescriptor .getSingleSignOnServices ()) {
155
- Saml2MessageBinding binding ;
156
- if (singleSignOnService .getBinding ().equals (Saml2MessageBinding .POST .getUrn ())) {
157
- binding = Saml2MessageBinding .POST ;
158
- }
159
- else if (singleSignOnService .getBinding ().equals (Saml2MessageBinding .REDIRECT .getUrn ())) {
160
- binding = Saml2MessageBinding .REDIRECT ;
161
- }
162
- else {
163
- continue ;
164
- }
165
- builder .assertingPartyDetails (
166
- (party ) -> party .singleSignOnServiceLocation (singleSignOnService .getLocation ())
167
- .singleSignOnServiceBinding (binding ));
168
- return builder ;
169
- }
170
- throw new Saml2Exception (
171
- "Metadata response is missing a SingleSignOnService, necessary for sending AuthnRequests" );
172
- }
173
-
174
- private List <X509Certificate > certificates (KeyDescriptor keyDescriptor ) {
175
- try {
176
- return KeyInfoSupport .getCertificates (keyDescriptor .getKeyInfo ());
177
- }
178
- catch (CertificateException ex ) {
179
- throw new Saml2Exception (ex );
180
- }
181
- }
182
-
183
- private EntityDescriptor entityDescriptor (InputStream inputStream ) {
184
- Document document = document (inputStream );
185
- Element element = document .getDocumentElement ();
186
- Unmarshaller unmarshaller = this .registry .getUnmarshallerFactory ().getUnmarshaller (element );
187
- if (unmarshaller == null ) {
188
- throw new Saml2Exception ("Unsupported element of type " + element .getTagName ());
189
- }
190
- try {
191
- XMLObject object = unmarshaller .unmarshall (element );
192
- if (object instanceof EntitiesDescriptor ) {
193
- return ((EntitiesDescriptor ) object ).getEntityDescriptors ().get (0 );
194
- }
195
- if (object instanceof EntityDescriptor ) {
196
- return (EntityDescriptor ) object ;
197
- }
198
- }
199
- catch (Exception ex ) {
200
- throw new Saml2Exception (ex );
201
- }
202
- throw new Saml2Exception ("Unsupported element of type " + element .getTagName ());
203
- }
204
-
205
- private Document document (InputStream inputStream ) {
206
- try {
207
- return this .parserPool .parse (inputStream );
208
- }
209
- catch (Exception ex ) {
210
- throw new Saml2Exception (ex );
211
- }
92
+ return this .converter .convert (inputMessage .getBody ());
212
93
}
213
94
214
95
@ Override
0 commit comments