More AA & HS unification (merged separate relying party implementations).
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / common / ServiceProviderMapper.java
1 /*
2  * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
3  * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
4  * provided that the following conditions are met: Redistributions of source code must retain the above copyright
5  * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above
6  * copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials
7  * provided with the distribution, if any, must include the following acknowledgment: "This product includes software
8  * developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu> Internet2 Project.
9  * Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
10  * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2, nor
11  * the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
12  * products derived from this software without specific prior written permission. For written permission, please contact
13  * shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2, UCAID, or the
14  * University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name, without prior
15  * written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS PROVIDED BY THE
16  * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE
18  * DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. IN NO
19  * EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC.
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 package edu.internet2.middleware.shibboleth.common;
27
28 import java.net.MalformedURLException;
29 import java.net.URI;
30 import java.net.URISyntaxException;
31 import java.net.URL;
32 import java.util.HashMap;
33 import java.util.Map;
34
35 import org.apache.log4j.Logger;
36 import org.w3c.dom.Element;
37 import org.w3c.dom.NodeList;
38
39 import edu.internet2.middleware.shibboleth.idp.IdPConfig;
40 import edu.internet2.middleware.shibboleth.metadata.Metadata;
41 import edu.internet2.middleware.shibboleth.metadata.Provider;
42
43 /**
44  * Class for determining the effective relying party from the unique id of the service provider. Checks first for an
45  * exact match on the service provider, then for membership in a federation. Uses the default relying party if neither
46  * is found.
47  * 
48  * @author Walter Hoehn
49  */
50 public class ServiceProviderMapper {
51
52         private static Logger log = Logger.getLogger(ServiceProviderMapper.class.getName());
53         protected Map relyingParties = new HashMap();
54         private Metadata metaData;
55         private IdPConfig configuration;
56         private Credentials credentials;
57         private NameMapper nameMapper;
58
59         public ServiceProviderMapper(Element rawConfig, IdPConfig configuration, Credentials credentials,
60                         NameMapper nameMapper, Metadata metaData) throws ServiceProviderMapperException {
61
62                 this.metaData = metaData;
63                 this.configuration = configuration;
64                 this.credentials = credentials;
65                 this.nameMapper = nameMapper;
66
67                 NodeList itemElements = rawConfig.getElementsByTagNameNS(IdPConfig.originConfigNamespace, "RelyingParty");
68
69                 for (int i = 0; i < itemElements.getLength(); i++) {
70                         addRelyingParty((Element) itemElements.item(i));
71                 }
72
73                 verifyDefaultParty(configuration);
74
75         }
76
77         private IdPConfig getOriginConfig() {
78
79                 return configuration;
80         }
81
82         protected void verifyDefaultParty(IdPConfig configuration) throws ServiceProviderMapperException {
83
84                 // Verify we have a proper default party
85                 String defaultParty = configuration.getDefaultRelyingPartyName();
86                 if (defaultParty == null || defaultParty.equals("")) {
87                         if (relyingParties.size() != 1) {
88                                 log
89                                                 .error("Default Relying Party not specified.  Add a (defaultRelyingParty) attribute to <IdPConfig>.");
90                                 throw new ServiceProviderMapperException("Required configuration not specified.");
91                         } else {
92                                 log.debug("Only one Relying Party loaded.  Using this as the default.");
93                         }
94                 }
95                 log.debug("Default Relying Party set to: (" + defaultParty + ").");
96                 if (!relyingParties.containsKey(defaultParty)) {
97                         log.error("Default Relying Party refers to a Relying Party that has not been loaded.");
98                         throw new ServiceProviderMapperException("Invalid configuration (Default Relying Party).");
99                 }
100         }
101
102         protected RelyingParty getRelyingPartyImpl(String providerIdFromTarget) {
103
104                 // Null request, send the default
105                 if (providerIdFromTarget == null) {
106                         RelyingParty relyingParty = getDefaultRelyingParty();
107                         log.info("Using default Relying Party: (" + relyingParty.getName() + ").");
108                         return new UnknownProviderWrapper(relyingParty, providerIdFromTarget);
109                 }
110
111                 // Look for a configuration for the specific relying party
112                 if (relyingParties.containsKey(providerIdFromTarget)) {
113                         log.info("Found Relying Party for (" + providerIdFromTarget + ").");
114                         return (RelyingParty) relyingParties.get(providerIdFromTarget);
115                 }
116
117                 // Next, check to see if the relying party is in any groups
118                 RelyingParty groupParty = findRelyingPartyByGroup(providerIdFromTarget);
119                 if (groupParty != null) {
120                         log.info("Provider is a member of Relying Party (" + groupParty.getName() + ").");
121                         return new RelyingPartyGroupWrapper(groupParty, providerIdFromTarget);
122                 }
123
124                 // OK, we can't find it... just send the default
125                 RelyingParty relyingParty = getDefaultRelyingParty();
126                 log.info("Could not locate Relying Party configuration for (" + providerIdFromTarget
127                                 + ").  Using default Relying Party: (" + relyingParty.getName() + ").");
128                 return new UnknownProviderWrapper(relyingParty, providerIdFromTarget);
129         }
130
131         private RelyingParty findRelyingPartyByGroup(String providerIdFromTarget) {
132
133                 Provider provider = metaData.lookup(providerIdFromTarget);
134                 if (provider != null) {
135                         String[] groups = provider.getGroups();
136                         for (int i = 0; groups.length > i; i++) {
137                                 // We need to iterate backward because the groups go from least to most specific
138                                 String group = groups[groups.length - 1 - i];
139                                 if (relyingParties.containsKey(group)) {
140                                         log.info("Found matching Relying Party for group (" + group + ").");
141                                         return (RelyingParty) relyingParties.get(group);
142                                 } else {
143                                         log
144                                                         .debug("Provider is a member of group (" + group
145                                                                         + "), but no matching Relying Party was found.");
146                                 }
147                         }
148                 }
149                 return null;
150         }
151
152         public RelyingParty getDefaultRelyingParty() {
153
154                 // If there is no explicit default, pick the single configured Relying
155                 // Party
156                 String defaultParty = getOriginConfig().getDefaultRelyingPartyName();
157                 if (defaultParty == null || defaultParty.equals("")) { return (RelyingParty) relyingParties.values().iterator()
158                                 .next(); }
159
160                 // If we do have a default specified, use it...
161                 return (RelyingParty) relyingParties.get(defaultParty);
162         }
163
164         /**
165          * Returns the relying party for a legacy provider(the default)
166          */
167         public RelyingParty getLegacyRelyingParty() {
168
169                 RelyingParty relyingParty = getDefaultRelyingParty();
170                 log.info("Request is from legacy shib target.  Selecting default Relying Party: (" + relyingParty.getName()
171                                 + ").");
172                 return new LegacyWrapper((RelyingParty) relyingParty);
173
174         }
175
176         /**
177          * Returns the appropriate relying party for the supplied service provider id.
178          */
179         public RelyingParty getRelyingParty(String providerIdFromTarget) {
180
181                 if (providerIdFromTarget == null || providerIdFromTarget.equals("")) {
182                         RelyingParty relyingParty = getDefaultRelyingParty();
183                         log.info("Selecting default Relying Party: (" + relyingParty.getName() + ").");
184                         return new NoMetadataWrapper((RelyingParty) relyingParty);
185                 }
186
187                 return (RelyingParty) getRelyingPartyImpl(providerIdFromTarget);
188         }
189
190         private void addRelyingParty(Element e) throws ServiceProviderMapperException {
191
192                 log.debug("Found a Relying Party.");
193                 try {
194                         if (e.getLocalName().equals("RelyingParty")) {
195                                 RelyingParty party = new RelyingPartyImpl(e, configuration, credentials, nameMapper);
196                                 log.debug("Relying Party (" + party.getName() + ") loaded.");
197                                 relyingParties.put(party.getName(), party);
198                         }
199                 } catch (ServiceProviderMapperException exc) {
200                         log.error("Encountered an error while attempting to load Relying Party configuration.  Skipping...");
201                 }
202
203         }
204
205         /**
206          * Base relying party implementation.
207          * 
208          * @author Walter Hoehn
209          */
210         protected class RelyingPartyImpl implements RelyingParty {
211
212                 private RelyingPartyIdentityProvider identityProvider;
213                 private String name;
214                 private String overridenOriginProviderId;
215                 private URL overridenAAUrl;
216                 private URI overridenDefaultAuthMethod;
217                 private String hsNameFormatId;
218                 private IdPConfig configuration;
219                 private boolean overridenPassThruErrors = false;
220                 private boolean passThruIsOverriden = false;
221
222                 public RelyingPartyImpl(Element partyConfig, IdPConfig globalConfig, Credentials credentials,
223                                 NameMapper nameMapper) throws ServiceProviderMapperException {
224
225                         configuration = globalConfig;
226
227                         // Get party name
228                         name = ((Element) partyConfig).getAttribute("name");
229                         if (name == null || name.equals("")) {
230                                 log.error("Relying Party name not set.  Add a (name) attribute to <RelyingParty>.");
231                                 throw new ServiceProviderMapperException("Required configuration not specified.");
232                         }
233                         log.debug("Loading Relying Party: (" + name + ").");
234
235                         // Process overrides for global configuration data
236                         String attribute = ((Element) partyConfig).getAttribute("providerId");
237                         if (attribute != null && !attribute.equals("")) {
238                                 log.debug("Overriding providerId for Relying Pary (" + name + ") with (" + attribute + ").");
239                                 overridenOriginProviderId = attribute;
240                         }
241
242                         attribute = ((Element) partyConfig).getAttribute("AAUrl");
243                         if (attribute != null && !attribute.equals("")) {
244                                 log.debug("Overriding AAUrl for Relying Pary (" + name + ") with (" + attribute + ").");
245                                 try {
246                                         overridenAAUrl = new URL(attribute);
247                                 } catch (MalformedURLException e) {
248                                         log.error("(AAUrl) attribute to is not a valid URL.");
249                                         throw new ServiceProviderMapperException("Configuration is invalid.");
250                                 }
251                         }
252
253                         attribute = ((Element) partyConfig).getAttribute("defaultAuthMethod");
254                         if (attribute != null && !attribute.equals("")) {
255                                 log.debug("Overriding defaultAuthMethod for Relying Pary (" + name + ") with (" + attribute + ").");
256                                 try {
257                                         overridenDefaultAuthMethod = new URI(attribute);
258                                 } catch (URISyntaxException e1) {
259                                         log.error("(defaultAuthMethod) attribute to is not a valid URI.");
260                                         throw new ServiceProviderMapperException("Configuration is invalid.");
261                                 }
262                         }
263
264                         attribute = ((Element) partyConfig).getAttribute("passThruErrors");
265                         if (attribute != null && !attribute.equals("")) {
266                                 log.debug("Overriding passThruErrors for Relying Pary (" + name + ") with (" + attribute + ").");
267                                 overridenPassThruErrors = Boolean.valueOf(attribute).booleanValue();
268                                 passThruIsOverriden = true;
269                         }
270
271                         // Load and verify the name format that the HS should use in
272                         // assertions for this RelyingParty
273                         NodeList hsNameFormats = ((Element) partyConfig).getElementsByTagNameNS(IdPConfig.originConfigNamespace,
274                                         "HSNameFormat");
275                         // If no specification. Make sure we have a default mapping
276                         if (hsNameFormats.getLength() < 1) {
277                                 if (nameMapper.getNameIdentifierMappingById(null) == null) {
278                                         log.error("Relying Party HS Name Format not set.  Add a <HSNameFormat> element to <RelyingParty>.");
279                                         throw new ServiceProviderMapperException("Required configuration not specified.");
280                                 }
281
282                         } else {
283                                 // We do have a specification, so make sure it points to a
284                                 // valid Name Mapping
285                                 if (hsNameFormats.getLength() > 1) {
286                                         log.warn("Found multiple HSNameFormat specifications for Relying Party (" + name
287                                                         + ").  Ignoring all but the first.");
288                                 }
289
290                                 hsNameFormatId = ((Element) hsNameFormats.item(0)).getAttribute("nameMapping");
291                                 if (hsNameFormatId == null || hsNameFormatId.equals("")) {
292                                         log.error("HS Name Format mapping not set.  Add a (nameMapping) attribute to <HSNameFormat>.");
293                                         throw new ServiceProviderMapperException("Required configuration not specified.");
294                                 }
295
296                                 if (nameMapper.getNameIdentifierMappingById(hsNameFormatId) == null) {
297                                         log.error("Relying Party HS Name Format refers to a name mapping that is not loaded.");
298                                         throw new ServiceProviderMapperException("Required configuration not specified.");
299                                 }
300                         }
301
302                         // Load credentials for signing
303                         Credential authNCredential = null;
304                         Credential attrCredential = null;
305
306                         boolean signAuthResponses = new Boolean(((Element) partyConfig).getAttribute("signAuthResponses"))
307                                         .booleanValue();
308                         boolean signAuthAssertions = new Boolean(((Element) partyConfig).getAttribute("signAuthAssertions"))
309                                         .booleanValue();
310                         boolean signAttrResponses = new Boolean(((Element) partyConfig).getAttribute("signAttrResponses"))
311                                         .booleanValue();
312                         boolean signAttrAssertions = new Boolean(((Element) partyConfig).getAttribute("signAttrAssertions"))
313                                         .booleanValue();
314
315                         String credentialName = ((Element) partyConfig).getAttribute("signingCredential");
316
317                         // Load the credential for AuthN signing
318                         if (signAuthResponses || signAuthAssertions) {
319
320                                 authNCredential = credentials.getCredential(credentialName);
321                                 if (authNCredential == null) {
322                                         if (credentialName == null || credentialName.equals("")) {
323                                                 log.error("Relying Party credential not set.  Add a (signingCredential) "
324                                                                 + "attribute to <RelyingParty>.");
325                                                 throw new ServiceProviderMapperException("Required configuration not specified.");
326                                         } else {
327                                                 log.error("Relying Party credential invalid.  Fix the (signingCredential) attribute "
328                                                                 + "on <RelyingParty>.");
329                                                 throw new ServiceProviderMapperException("Required configuration is invalid.");
330                                         }
331                                 }
332                         }
333
334                         // Load the credential for Attribute signing
335                         if (signAttrAssertions || signAttrResponses) {
336                                 String aaCredentialName = ((Element) partyConfig).getAttribute("AASigningCredential");
337                                 attrCredential = credentials.getCredential(aaCredentialName);
338                                 if (aaCredentialName == null || aaCredentialName.equals("")) {
339                                         if (authNCredential != null) {
340                                                 attrCredential = authNCredential;
341                                         } else {
342                                                 aaCredentialName = ((Element) partyConfig).getAttribute("signingCredential");
343                                                 attrCredential = credentials.getCredential(aaCredentialName);
344                                         }
345                                 } else {
346                                         log.debug("Using (AASigningCredential) for AA signing.");
347                                 }
348                         }
349
350                         if ((attrCredential == null) && (signAttrResponses || signAttrAssertions)) {
351                                 if (credentialName == null || credentialName.equals("")) {
352                                         log.error("Relying Party credential not set.  Add a (AASigningCredential) or (signingCredential) "
353                                                         + "attribute to <RelyingParty>.");
354                                         throw new ServiceProviderMapperException("Required configuration not specified.");
355                                 } else {
356                                         log.error("Relying Party credential invalid.  Fix the (signingCredential) attribute "
357                                                         + "on <RelyingParty>.");
358                                         throw new ServiceProviderMapperException("Required configuration is invalid.");
359                                 }
360                         }
361
362                         // Initialize and Identity Provider object for this use by this relying party
363                         identityProvider = new RelyingPartyIdentityProvider(overridenOriginProviderId != null
364                                         ? overridenOriginProviderId
365                                         : configuration.getProviderId(), signAuthResponses ? authNCredential : null, signAuthAssertions
366                                         ? authNCredential
367                                         : null, signAttrResponses ? attrCredential : null, signAttrAssertions ? attrCredential : null);
368
369                 }
370
371                 public String getProviderId() {
372
373                         return name;
374                 }
375
376                 public String getName() {
377
378                         return name;
379                 }
380
381                 public IdentityProvider getIdentityProvider() {
382
383                         return identityProvider;
384                 }
385
386                 public boolean isLegacyProvider() {
387
388                         return false;
389                 }
390
391                 public String getHSNameFormatId() {
392
393                         return hsNameFormatId;
394                 }
395
396                 public URI getDefaultAuthMethod() {
397
398                         if (overridenDefaultAuthMethod != null) {
399                                 return overridenDefaultAuthMethod;
400                         } else {
401                                 return configuration.getDefaultAuthMethod();
402                         }
403                 }
404
405                 public URL getAAUrl() {
406
407                         if (overridenAAUrl != null) {
408                                 return overridenAAUrl;
409                         } else {
410                                 return configuration.getAAUrl();
411                         }
412                 }
413
414                 public boolean passThruErrors() {
415
416                         if (passThruIsOverriden) {
417                                 return overridenPassThruErrors;
418                         } else {
419                                 return configuration.passThruErrors();
420                         }
421                 }
422
423                 /**
424                  * Default identity provider implementation.
425                  * 
426                  * @author Walter Hoehn
427                  */
428                 protected class RelyingPartyIdentityProvider implements IdentityProvider {
429
430                         private String providerId;
431                         private Credential authNResponseSigningCredential;
432                         private Credential authNAssertionSigningCredential;
433                         private Credential attributeResponseSigningCredential;
434                         private Credential attributeAssertionSigningCredential;
435
436                         public RelyingPartyIdentityProvider(String providerId, Credential authNResponseSigningCredential,
437                                         Credential authNAssertionSigningCredential, Credential attributeResponseSigningCredential,
438                                         Credential attributeAssertionSigningCredential) {
439
440                                 this.providerId = providerId;
441                                 this.authNResponseSigningCredential = authNResponseSigningCredential;
442                                 this.authNAssertionSigningCredential = authNAssertionSigningCredential;
443                                 this.attributeResponseSigningCredential = attributeResponseSigningCredential;
444                                 this.attributeAssertionSigningCredential = attributeAssertionSigningCredential;
445                         }
446
447                         public String getProviderId() {
448
449                                 return providerId;
450                         }
451
452                         public Credential getAuthNResponseSigningCredential() {
453
454                                 return authNResponseSigningCredential;
455                         }
456
457                         public Credential getAuthNAssertionSigningCredential() {
458
459                                 return authNAssertionSigningCredential;
460                         }
461
462                         public Credential getAttributeResponseSigningCredential() {
463
464                                 return attributeResponseSigningCredential;
465                         }
466
467                         public Credential getAttributeAssertionSigningCredential() {
468
469                                 return attributeAssertionSigningCredential;
470                         }
471
472                 }
473         }
474
475         /**
476          * Relying party implementation wrapper for relying parties that are federations.
477          * 
478          * @author Walter Hoehn
479          */
480         class RelyingPartyGroupWrapper implements RelyingParty {
481
482                 private RelyingParty wrapped;
483                 private String providerId;
484
485                 RelyingPartyGroupWrapper(RelyingParty wrapped, String providerId) {
486
487                         this.wrapped = wrapped;
488                         this.providerId = providerId;
489                 }
490
491                 public String getName() {
492
493                         return wrapped.getName();
494                 }
495
496                 public boolean isLegacyProvider() {
497
498                         return false;
499                 }
500
501                 public IdentityProvider getIdentityProvider() {
502
503                         return wrapped.getIdentityProvider();
504                 }
505
506                 public String getProviderId() {
507
508                         return providerId;
509                 }
510
511                 public String getHSNameFormatId() {
512
513                         return wrapped.getHSNameFormatId();
514                 }
515
516                 public URL getAAUrl() {
517
518                         return wrapped.getAAUrl();
519                 }
520
521                 public URI getDefaultAuthMethod() {
522
523                         return wrapped.getDefaultAuthMethod();
524                 }
525
526                 public boolean passThruErrors() {
527
528                         return wrapped.passThruErrors();
529                 }
530         }
531
532         /**
533          * Relying party implementation wrapper for anonymous service providers.
534          * 
535          * @author Walter Hoehn
536          */
537         protected class UnknownProviderWrapper implements RelyingParty {
538
539                 protected RelyingParty wrapped;
540                 protected String providerId;
541
542                 protected UnknownProviderWrapper(RelyingParty wrapped, String providerId) {
543
544                         this.wrapped = wrapped;
545                         this.providerId = providerId;
546                 }
547
548                 public String getName() {
549
550                         return wrapped.getName();
551                 }
552
553                 public IdentityProvider getIdentityProvider() {
554
555                         return wrapped.getIdentityProvider();
556                 }
557
558                 public String getProviderId() {
559
560                         return providerId;
561                 }
562
563                 public String getHSNameFormatId() {
564
565                         return wrapped.getHSNameFormatId();
566                 }
567
568                 public boolean isLegacyProvider() {
569
570                         return wrapped.isLegacyProvider();
571                 }
572
573                 public URL getAAUrl() {
574
575                         return wrapped.getAAUrl();
576                 }
577
578                 public URI getDefaultAuthMethod() {
579
580                         return wrapped.getDefaultAuthMethod();
581                 }
582
583                 public boolean passThruErrors() {
584
585                         return wrapped.passThruErrors();
586                 }
587         }
588
589         /**
590          * Relying party wrapper for Shibboleth &lt;=1.1 service providers.
591          * 
592          * @author Walter Hoehn
593          */
594         class LegacyWrapper extends UnknownProviderWrapper implements RelyingParty {
595
596                 LegacyWrapper(RelyingParty wrapped) {
597
598                         super(wrapped, null);
599                 }
600
601                 public boolean isLegacyProvider() {
602
603                         return true;
604                 }
605
606                 public String getHSNameFormatId() {
607
608                         return ((RelyingParty) wrapped).getHSNameFormatId();
609                 }
610
611                 public URL getAAUrl() {
612
613                         return ((RelyingParty) wrapped).getAAUrl();
614                 }
615
616                 public URI getDefaultAuthMethod() {
617
618                         return ((RelyingParty) wrapped).getDefaultAuthMethod();
619                 }
620         }
621
622         /**
623          * Relying party wrapper for providers for which we have no metadata
624          * 
625          * @author Walter Hoehn
626          */
627         class NoMetadataWrapper extends UnknownProviderWrapper implements RelyingParty {
628
629                 NoMetadataWrapper(RelyingParty wrapped) {
630
631                         super(wrapped, null);
632                 }
633
634                 public String getHSNameFormatId() {
635
636                         return ((RelyingParty) wrapped).getHSNameFormatId();
637                 }
638
639                 public URL getAAUrl() {
640
641                         return ((RelyingParty) wrapped).getAAUrl();
642                 }
643
644                 public URI getDefaultAuthMethod() {
645
646                         return ((RelyingParty) wrapped).getDefaultAuthMethod();
647                 }
648         }
649 }