Ce contenu n'est pas disponible dans la langue sélectionnée.
9.5. Enabling Realms in the STS
9.5.1. Issuing Tokens in Multiple Realms
Overview
Figure 9.11. Realm-Aware SAML Token Issuer
Realm aware token issuing steps
- When a realm-aware STS receives an issue token request, it tries to find out what realm to issue the token in, by calling out to the realm parser instance.WS-Trust does not define a standard way to associate a token with a realm. Hence, you must work out your own approach for indicating the realm and codify this approach by providing a custom implementation of the
RealmParser
interface. The realm parser'sparseRealm
method returns a string, which is the name of the realm to issue the token in.For example, you could identify the realm, by inspecting the URL of the STS Web service endpoint that was invoked. The pathname of the URL could include a segment that identifies the realm. - The
TokenIssueOperation
instance then calls thecanHandleToken
method on each of the registered token providers. In this example, only theSAMLTokenProvider
token provider is registered. ThecanHandleToken
method parameters include the token type and the realm name. - Assuming that the token type matches (for example, the client is requesting a SAML token), the
SAMLTokenProvider
looks up the realm name in its realm map to make sure that it can handle this realm. If theSAMLTokenProvider
finds the realm name in its map, it returnstrue
from thecanHandleToken
method. - The
TokenIssueOperation
instance now calls thecreateToken
method on theSAMLTokenProvider
instance, in order to issue the token in the specified realm. - The
SAMLTokenProvider
looks up the specified realm in the realm map and retrieves the correspondingSAMLRealm
instance. TheSAMLRealm
instance encapsulates the data that is specific to this realm.For example, if the specified realm isA
, theSAMLRealm
instance records that the corresponding issuer name isA-Issuer
and the alias of the signing key to use for this realm isStsKeyA
. - The
SAMLTokenProvider
now uses the realm-specific data in combination with the generic data from the STS properties instance to issue the SAML token in the specified realm.For example, if the specified realm isA
, theSAMLTokenProvider
embeds theA-Issuer
string in the SAML token's issuer element and the SAML token is signed using theStsKeyA
private key from thestsstore.jks
Java keystore file.
Configuring the realm parser
RealmParser
interface and then register your custom realm parser by injecting it into the realmParser
property of the STS properties bean.
URLRealmParser
instance with the StaticSTSProperties
bean as follows:
<beans ... > ... <bean id="transportSTSProperties" class="org.apache.cxf.sts.StaticSTSProperties"> ... <property name="realmParser" ref="customRealmParser" /> ... </bean> <bean id="customRealmParser" class="org.apache.cxf.systest.sts.realms.URLRealmParser" /> ... </beans>
Sample URL realm parser
RealmParser
interface:
public String parseRealm(WebServiceContext context) throws STSException;
parseRealm
passes an instance of javax.xml.ws.WebServiceContext, which provides access to message context and security information about the current request message (issue token request). You can use this message context information to identify the current realm.
URLRealmParser
used in the previous example works by examining the URL of the invoked STS Web service endpoint and checking whether any known realm names are embedded in the URL. The realm name embedded in the URL is then taken to be the realm to issue the token in and the realm is then returned from the parseRealm
method.
// Java package org.apache.cxf.systest.sts.realms; import javax.xml.ws.WebServiceContext; import org.apache.cxf.sts.RealmParser; import org.apache.cxf.ws.security.sts.provider.STSException; /** * A test implementation of RealmParser which returns a realm depending on a String contained * in the URL of the service request. */ public class URLRealmParser implements RealmParser { public String parseRealm(WebServiceContext context) throws STSException { String url = (String)context.getMessageContext().get("org.apache.cxf.request.url"); if (url.contains("realmA")) { return "A"; } else if (url.contains("realmB")) { return "B"; } else if (url.contains("realmC")) { return "C"; } return null; } }
null
return value indicates that the STS should use the default realm (as defined by the issuer
and signatureUsername
properties of the STS properties bean).
Configuring the realm map
SAMLTokenProvider
token provider must be initialized with a realm map, which provides the requisite data about each realm. For example, the scenario shown in Figure 9.11, “Realm-Aware SAML Token Issuer” uses a realm map like the following:
<beans ... > ... <bean id="transportIssueDelegate" class="org.apache.cxf.sts.operation.TokenIssueOperation"> <property name="tokenProviders" ref="transportTokenProviders" /> <property name="services" ref="transportService" /> <property name="stsProperties" ref="transportSTSProperties" /> </bean> <util:list id="transportTokenProviders"> <ref bean="transportSAMLProvider" /> </util:list> <bean id="transportSAMLProvider" class="org.apache.cxf.sts.token.provider.SAMLTokenProvider"> <property name="realmMap" ref="realms" /> </bean> <util:map id="realms"> <entry key="A" value-ref="realmA" /> <entry key="B" value-ref="realmB" /> <entry key="C" value-ref="realmC" /> </util:map> <bean id="realmA" class="org.apache.cxf.sts.token.realm.SAMLRealm"> <property name="issuer" value="A-Issuer" /> <property name="signatureAlias" value="StsKeyA" /> </bean> <bean id="realmB" class="org.apache.cxf.sts.token.realm.SAMLRealm"> <property name="issuer" value="B-Issuer" /> <property name="signatureAlias" value="StsKeyB" /> </bean> <bean id="realmC" class="org.apache.cxf.sts.token.realm.SAMLRealm"> <property name="issuer" value="C-Issuer" /> <property name="signatureAlias" value="StsKeyC" /> </bean> ... </beans>
9.5.2. Validating Tokens in Multiple Realms
Overview
Figure 9.12. Realm-Aware SAML Token Validation
Realm aware token validating steps
- When a realm-aware STS receives a validate token request, it tries to find out what realm to issue the token in, by calling out to the realm parser instance.NoteThe realm identified by the realm parser in this step is not necessarily the same realm that the token was originally issued in. See the section called “Validating tokens across realms”.
- The
TokenValidateOperation
instance then calls thecanHandleToken
method on each of the registered token validators. In this example, only theSAMLTokenValidator
token validator is registered. ThecanHandleToken
method parameters include the token type and the realm name.NoteThe defaultSAMLTokenValidator
class ignores the realm parameter in thecanHandleToken
method, so it will attempt to validate the token in any realm. If you need to implement realm-specific validation steps, however, you have the option of implementing a custom SAML token validator that pays attention to the realm parameter. - The
TokenValidateOperation
instance then calls thevalidateToken
method on theSAMLTokenValidator
, in order to validate the token in the specified realm. - The
SAMLTokenValidator
attempts to validate the received SAML token by checking whether it has been signed by a trusted key. The public part of the signing key pair must match one of the trusted certificates stored in the signature trust store (as configured by thesignaturePropertiesFile
property in the STS properties instance).Hence, for each of the supported realms, the public part of the realm's signing key must be present in the signature trust store (or at least one of the certificate's in that realm's trust chain). Otherwise, theSAMLTokenValidator
will not be able to validate tokens that were issued in that realm.For example, if you want to be able to validate tokens in the realms,A
,B
, andC
, you must store the corresponding certificates (public part of the signature keys),StsKeyA
,StsKeyB
, andStsKeyC
, in thestsstore.jks
Java keystore file. - In case the client needs the information, the
SAMLTokenValidator
also embeds the name of the realm where the token was originally issued into the Validate response message. This is not necessarily the same realm as the realm that the token has just been validated in.To find the original realm that the token was issued in, theSAMLTokenValidator
calls out to the customSAMLRealmCodec
instance. TheSAMLRealmCodec
instance tries to figure out the issuing realm by examining the token contents. If the issuing realm can be established, this information is included in the Validate response message.
Configuring the realm parser
Validating tokens across realms
Response from Validate operation
SAMLTokenValidator
can be configured to discover the token's issuing realm and embed this information in the Validate operation's response. To give the SAMLTokenValidator
the ability to discover the token's issuing realm, you must implement and register a SAMLRealmCodec
instance.
Configuring the SAMLRealmCodec
IssuerSAMLRealmCodec
instance, which implements the SAMLRealmCodec
interface:
<beans ... > ... <bean id="transportValidateDelegate" class="org.apache.cxf.sts.operation.TokenValidateOperation"> <property name="tokenProviders" ref="transportTokenProviders" /> <property name="tokenValidators" ref="transportTokenValidators" /> <property name="stsProperties" ref="transportSTSProperties" /> </bean> ... <util:list id="transportTokenValidators"> <ref bean="transportSAMLValidator" /> </util:list> <bean id="transportSAMLValidator" class="org.apache.cxf.sts.token.validator.SAMLTokenValidator"> ... <property name="samlRealmCodec" ref="customSAMLRealmCodec" /> </bean> <bean id="customSAMLRealmCodec" class="org.apache.cxf.systest.sts.realms.IssuerSAMLRealmCodec" /> ... </beans>
Sample implementation of SAMLRealmCodec
public String getRealmFromToken(AssertionWrapper assertion)
assertion
parameter holds the contents of the SAML token. The assumption made here is that the realm name is either embedded in the SAML token somehow or the identity of the realm can somehow be inferred from the SAML token contents. For example, the SAML issuer name can typically be identified with a security realm.
IssuerSAMLRealmCodec
, which infers the realm name from the value of the issuer string:
// Java package org.apache.cxf.systest.sts.realms; import org.apache.cxf.sts.token.realm.SAMLRealmCodec; import org.apache.ws.security.saml.ext.AssertionWrapper; /** * This class returns a realm associated with a SAML Assertion depending on the issuer. */ public class IssuerSAMLRealmCodec implements SAMLRealmCodec { /** * Get the realm associated with the AssertionWrapper parameter * @param assertion a SAML Assertion wrapper object * @return the realm associated with the AssertionWrapper parameter */ public String getRealmFromToken(AssertionWrapper assertion) { if ("A-Issuer".equals(assertion.getIssuerString())) { return "A"; } else if ("B-Issuer".equals(assertion.getIssuerString())) { return "B"; } return null; } }
9.5.3. Token Transformation across Realms
Overview
Triggering token transformation
<beans ... > ... <jaxws:endpoint id="doubleitrealmtransform" implementor="org.apache.cxf.systest.sts.common.DoubleItPortTypeImpl" endpointName="s:DoubleItRealmTransformPort" serviceName="s:DoubleItService" depends-on="ClientAuthHttpsSettings" address="https://localhost:${testutil.ports.Server}/doubleit/services/doubleitrealmtransform" wsdlLocation="org/apache/cxf/systest/sts/realms/DoubleIt.wsdl" xmlns:s="http://www.example.org/contract/DoubleIt"> <jaxws:properties> <entry key="ws-security.saml2.validator"> <bean class="org.apache.cxf.ws.security.trust.STSTokenValidator"/> </entry> <entry key="security.sts.client"> <bean class="org.apache.cxf.ws.security.trust.STSClient"> <constructor-arg ref="cxf"/> <property name="wsdlLocation" value="https://localhost:${testutil.ports.STSServer}/SecurityTokenService/realmB?wsdl"/> <property name="serviceName" value="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}SecurityTokenService"/> <property name="endpointName" value="{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}Transport_Port"/> <property name="properties"> <map> <entry key="security.username" value="alice"/> <entry key="security.callback-handler" value="org.apache.cxf.systest.sts.common.CommonCallbackHandler"/> <entry key="security.sts.token.username" value="myclientkey"/> <entry key="security.sts.token.properties" value="clientKeystore.properties"/> <entry key="security.sts.token.usecert" value="true"/> </map> </property> <property name="tokenType" value="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"/> </bean> </entry> </jaxws:properties> </jaxws:endpoint> ... </beans>
jaxws:endpoint
element are of key importance in configuring token transformation:
ws-security.saml2.validator
- By initializing this property with an instance of the
STSTokenValidator
class, you are instructing the JAX-WS endpoint to validate incoming tokens by contacting the STS and invoking the Validate operation. security.sts.client
- When validation is enabled on the JAX-WS endpoint, you must also configure an
STSClient
instance, which encapsulates all of the settings required to connect to the STS. The properties you can set on theSTSClient
instance are discussed in detail in Creating an STSClient Instance. tokenType
- In order to enable a token transformation request (as distinct from a simple validation request), you must also set the
tokenType
property on theSTSClient
instance. This is the key setting that triggers token transformation. When this setting is present, the Validate operation will perform token transformation and return a newly issued token of the specified type in the Validate response message.For the list of possible token type URIs you can specify here, see Table 8.2.
Relying party as a gateway service
Transformation algorithm
- When the STS receives the Validate request message, it performs all of the usual tests to validate the received token (see Section 9.1.4, “Customizing the Validate Operation”).
- After validating the token successfully, the STS checks whether the
TokenType
has been explicitly set in the Validate request message (that is, whether the token type has some value other than the default dummy value). - If the token type was explicitly set, the STS proceeds to transform the token, which means that it issues a new token to replace the validated token.
- The STS now checks whether the current realm (as determined by the realm parser—see the section called “Configuring the realm parser”) is the same as the realm that issued the received token (as determined by the configured
SAMLRealmCodec
—see the section called “Configuring the SAMLRealmCodec”). If the realms are different, the STS checks whether anIdentityMapper
instance is configured on the STS properties object. - If an
IdentityMapper
is configured, the STS transforms the validated token's principal by calling themapPrincipal
method on theIdentityMapper
. The mapped identity will now be used as the transformed token's principal.NoteIn the context of SAML tokens, the principal corresponds to the value of theSubject/NameID
element in the SAML token. - The STS now proceeds to issue a new token in the current realm using the (possibly transformed) principal, based on the data in the validated token. The STS iterates over all of the registered token providers, until it finds a token provider that can handle the requested token type in the current realm.
- The STS then issues a new token by calling out to the token provider and returns the newly issued token in the Validate response message.
Configuring the TokenValidateOperation
TokenValidateOperation
instance is configured in an STS that supports token transformation:
<beans ... >
...
<bean id="transportValidateDelegate" class="org.apache.cxf.sts.operation.TokenValidateOperation">
<property name="tokenProviders" ref="transportTokenProviders" />
<property name="tokenValidators" ref="transportTokenValidators" />
<property name="stsProperties" ref="transportSTSProperties" />
</bean>
...
</beans>
tokenValidators
property (as is usual for the Valdate operation—for example, see Section 9.1.4, “Customizing the Validate Operation”). What you might not expect, however, is that you are also required to provide a list of token providers to the tokenProviders
property: this is because the Validate operation is also responsible for issuing new tokens, in the token transformation scenario.
Implementing an IdentityMapper
IdentityMapper
interface and implement the mapPrincipal
method, as shown in the following example:
// Java package org.apache.cxf.systest.sts.realms; import java.security.Principal; import org.apache.cxf.sts.IdentityMapper; import org.apache.ws.security.CustomTokenPrincipal; /** * A test implementation of RealmParser. */ public class CustomIdentityMapper implements IdentityMapper { /** * Map a principal in the source realm to the target realm * @param sourceRealm the source realm of the Principal * @param sourcePrincipal the principal in the source realm * @param targetRealm the target realm of the Principal * @return the principal in the target realm */ public Principal mapPrincipal(String sourceRealm, Principal sourcePrincipal, String targetRealm) { if ("A".equals(sourceRealm) && "B".equals(targetRealm)) { return new CustomTokenPrincipal("B-Principal"); } else if ("B".equals(sourceRealm) && "A".equals(targetRealm)) { return new CustomTokenPrincipal("A-Principal"); } return null; } }
CustomTokenPrincipal
class is just a simple implementation of the java.security.Principal
interface, which holds the string value of the returned principal.
Configuring the IdentityMapper
IdentityMapper
instance is configured by setting the identityMapper
property on the STS properties instance, as follows:
<beans ... > ... <bean id="transportSTSProperties" class="org.apache.cxf.sts.StaticSTSProperties"> ... <property name="identityMapper" ref="customIdentityMapper" /> <property name="realmParser" ref="customRealmParser" /> </bean> <bean id="customIdentityMapper" class="org.apache.cxf.systest.sts.realms.CustomIdentityMapper" /> <bean id="customRealmParser" class="org.apache.cxf.systest.sts.realms.URLRealmParser" /> ... </beans>
9.5.4. Realms Demonstration
Overview
Demonstration location
CXFInstallDir/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/realms
CXFInstallDir/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/realms
First STS server for A and C realms
Figure 9.13. STS Server for A and C realms
STS for realms A and C
STS endpoint configuration for realms A and C
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:cxf="http://cxf.apache.org/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd"> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/> <cxf:bus> <cxf:features> <cxf:logging/> </cxf:features> </cxf:bus> <bean id="transportSTSProviderBean" class="org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider"> <property name="issueOperation" ref="transportIssueDelegate" /> <property name="validateOperation" ref="transportValidateDelegate" /> </bean> ... <jaxws:endpoint id="RealmASTS" implementor="#transportSTSProviderBean" address="https://localhost:${testutil.ports.STSServer.2}/SecurityTokenService/realmA" ... </jaxws:endpoint> <jaxws:endpoint id="RealmCSTS" implementor="#transportSTSProviderBean" address="https://localhost:${testutil.ports.STSServer.2}/SecurityTokenService/realmC" ... </jaxws:endpoint> <jaxws:endpoint id="DefaultRealmSTS" implementor="#transportSTSProviderBean" address="https://localhost:${testutil.ports.STSServer.2}/SecurityTokenService/realmdefault" ... </jaxws:endpoint> <httpj:engine-factory id="ClientAuthHttpsSettings" bus="cxf"> <httpj:engine port="${testutil.ports.STSServer.2}"> <httpj:tlsServerParameters> ... <sec:clientAuthentication want="true" required="true" /> </httpj:tlsServerParameters> </httpj:engine> </httpj:engine-factory> </beans>
A
, for realm C
, and for the default realm. The endpoint URL that the client connects to, determines the realm in which the token is issued (see Example 9.5, “Demonstration RealmParser Implementation”).
Issue configuration for realms A and C
TokenIssueOperation
instance is configured as follows:
<beans ... >
...
<bean id="transportIssueDelegate" class="org.apache.cxf.sts.operation.TokenIssueOperation">
<property name="tokenProviders" ref="transportTokenProviders" />
<property name="services" ref="transportService" />
<property name="stsProperties" ref="transportSTSProperties" />
</bean>
<util:list id="transportTokenProviders">
<ref bean="transportSAMLProvider" />
</util:list>
<bean id="transportSAMLProvider" class="org.apache.cxf.sts.token.provider.SAMLTokenProvider">
<property name="realmMap" ref="realms" />
</bean>
<util:map id="realms">
<entry key="A" value-ref="realmA" />
<entry key="C" value-ref="realmC" />
</util:map>
<bean id="realmA" class="org.apache.cxf.sts.token.realm.SAMLRealm">
<property name="issuer" value="A-Issuer" />
<property name="signatureAlias" value="myclientkey" />
</bean>
<bean id="realmC" class="org.apache.cxf.sts.token.realm.SAMLRealm">
<property name="issuer" value="C-Issuer" />
<property name="signatureAlias" value="myservicekey" />
</bean>
<!-- List of Web service endpoints that can use this STS -->
<bean id="transportService" class="org.apache.cxf.sts.service.StaticService">
<property name="endpoints" ref="transportEndpoints" />
</bean>
<util:list id="transportEndpoints">
<value>https://localhost:(\d)*/doubleit/services/doubleitrealm.*
</value>
</util:list>
...
</beans>
TokenIssueOperation
is configured with a SAML token provider, but this SAML token provider is also configured with a realm map (through the realmMap
property). The SAML token provider uses the realm map to retrieve the extra data that it needs to generate and sign a SAML token in each of the supported realms (see Section 9.5.1, “Issuing Tokens in Multiple Realms”).
Validate configuration for realms A and C
TokenValidateOperation
instance is configured as follows:
<beans ... > ... <bean id="transportValidateDelegate" class="org.apache.cxf.sts.operation.TokenValidateOperation"> <property name="tokenProviders" ref="transportTokenProviders" /> <property name="tokenValidators" ref="transportTokenValidators" /> <property name="stsProperties" ref="transportSTSProperties" /> </bean> <util:list id="transportTokenProviders"> <ref bean="transportSAMLProvider" /> </util:list> ... <util:list id="transportTokenValidators"> <ref bean="transportSAMLValidator" /> </util:list> <bean id="transportSAMLValidator" class="org.apache.cxf.sts.token.validator.SAMLTokenValidator"> </bean> ... </beans>
TokenValidateOperation
instance. The token provider list is needed in case the STS is asked to issue a new token, in the context of token transformation (see Section 9.5.3, “Token Transformation across Realms”).
STS properties for realms A and C
<beans ... >
...
<bean id="transportSTSProperties" class="org.apache.cxf.sts.StaticSTSProperties">
<property name="signaturePropertiesFile"
value="org/apache/cxf/systest/sts/realms/stsKeystoreRealms.properties" />
<property name="signatureUsername" value="mystskey" />
<property name="callbackHandlerClass"
value="org.apache.cxf.systest.sts.common.CommonCallbackHandler" />
<property name="realmParser" ref="customRealmParser" />
<property name="issuer" value="saml1-issuer" />
</bean>
<bean id="customRealmParser"
class="org.apache.cxf.systest.sts.realms.URLRealmParser" />
...
</beans>
realmParser
property is initialized with an instance of the URLRealmParser
class, whose implementation is shown in Example 9.5, “Demonstration RealmParser Implementation”. The realm parser figures out the current realm by examining the message context.
Second STS server for B realm
Figure 9.14. STS Server for B realm
STS for realm B
STS configuration for realm B
<beans ... >
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<cxf:bus>
<cxf:features>
<cxf:logging/>
</cxf:features>
</cxf:bus>
<bean id="transportSTSProviderBean"
class="org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider">
<property name="issueOperation" ref="transportIssueDelegate" />
<property name="validateOperation" ref="transportValidateDelegate" />
</bean>
...
<jaxws:endpoint id="RealmBSTS" implementor="#transportSTSProviderBean"
address="https://localhost:${testutil.ports.STSServer}/SecurityTokenService/realmB"
...
</jaxws:endpoint>
<httpj:engine-factory id="ClientAuthHttpsSettings"
bus="cxf">
<httpj:engine port="${testutil.ports.STSServer}">
<httpj:tlsServerParameters>
...
<sec:clientAuthentication want="true"
required="true" />
</httpj:tlsServerParameters>
</httpj:engine>
</httpj:engine-factory>
</beans>
realmB
, in the WS endpoint address URL. The endpoint URL that the client connects to, determines the realm in which the token is issued (see Example 9.5, “Demonstration RealmParser Implementation”).
Issue configuration for realm B
TokenIssueOperation
instance is configured as follows:
<beans ... >
...
<bean id="transportIssueDelegate" class="org.apache.cxf.sts.operation.TokenIssueOperation">
<property name="tokenProviders" ref="transportTokenProviders" />
<property name="services" ref="transportService" />
<property name="stsProperties" ref="transportSTSProperties" />
</bean>
<util:list id="transportTokenProviders">
<ref bean="transportSAMLProvider" />
</util:list>
<bean id="transportSAMLProvider"
class="org.apache.cxf.sts.token.provider.SAMLTokenProvider">
<property name="realmMap" ref="realms" />
</bean>
<util:map id="realms">
<entry key="B" value-ref="realmB" />
</util:map>
<bean id="realmB" class="org.apache.cxf.sts.token.realm.SAMLRealm">
<property name="issuer" value="B-Issuer" />
</bean>
<!-- List of Web service endpoints that can use this STS -->
<bean id="transportService" class="org.apache.cxf.sts.service.StaticService">
<property name="endpoints" ref="transportEndpoints" />
</bean>
<util:list id="transportEndpoints">
<value>https://localhost:(\d)*/doubleit/services/doubleitrealm.*
</value>
</util:list>
...
</beans>
TokenIssueOperation
is configured with a SAML token provider, but this SAML token provider is also configured with a realm map (through the realmMap
property). The SAML token provider uses the realm map to retrieve the extra data that it needs to generate and sign a SAML token in each of the supported realms (see Section 9.5.1, “Issuing Tokens in Multiple Realms”).
Validate configuration for realm B
TokenValidateOperation
instance is configured as follows:
<beans ... > ... <bean id="transportValidateDelegate" class="org.apache.cxf.sts.operation.TokenValidateOperation"> <property name="tokenProviders" ref="transportTokenProviders" /> <property name="tokenValidators" ref="transportTokenValidators" /> <property name="stsProperties" ref="transportSTSProperties" /> </bean> <util:list id="transportTokenProviders"> <ref bean="transportSAMLProvider" /> </util:list> ... <util:list id="transportTokenValidators"> <ref bean="transportSAMLValidator" /> </util:list> <bean id="transportSAMLValidator" class="org.apache.cxf.sts.token.validator.SAMLTokenValidator"> <property name="subjectConstraints" ref="subjectConstraintList" /> <property name="samlRealmCodec" ref="customSAMLRealmCodec" /> </bean> <util:list id="subjectConstraintList"> <value>.*CN=www.client.com.*</value> <value>.*CN=www.sts.com.*</value> </util:list> <bean id="customSAMLRealmCodec" class="org.apache.cxf.systest.sts.realms.IssuerSAMLRealmCodec" /> ... </beans>
samlRealmCodec
property with a reference to the SAML realm codec implementation, IssuerSAMLRealmCodec
. The SAML realm codec parses the received token in order to discover what realm it was originally issued in. See Example 9.6, “Demonstration SAMLRealmCodec Implementation”.
STS properties for realm B
<beans ... > ... <bean id="transportSTSProperties" class="org.apache.cxf.sts.StaticSTSProperties"> <property name="signaturePropertiesFile" value="stsKeystore.properties" /> <property name="signatureUsername" value="mystskey" /> <property name="callbackHandlerClass" value="org.apache.cxf.systest.sts.common.CommonCallbackHandler" /> <property name="issuer" value="saml2-issuer" /> <property name="identityMapper" ref="customIdentityMapper" /> <property name="realmParser" ref="customRealmParser" /> </bean> <bean id="customIdentityMapper" class="org.apache.cxf.systest.sts.realms.CustomIdentityMapper" /> <bean id="customRealmParser" class="org.apache.cxf.systest.sts.realms.URLRealmParser" /> ... </beans>
Realm parser implementation
parseRealm
method returns null
, to select the default realm (that is, the realm configured by default, by the STS properties instance).
Example 9.5. Demonstration RealmParser Implementation
// Java package org.apache.cxf.systest.sts.realms; import javax.xml.ws.WebServiceContext; import org.apache.cxf.sts.RealmParser; import org.apache.cxf.ws.security.sts.provider.STSException; /** * A test implementation of RealmParser which returns a realm depending on a String contained * in the URL of the service request. */ public class URLRealmParser implements RealmParser { public String parseRealm(WebServiceContext context) throws STSException { String url = (String)context.getMessageContext().get("org.apache.cxf.request.url"); if (url.contains("realmA")) { return "A"; } else if (url.contains("realmB")) { return "B"; } else if (url.contains("realmC")) { return "C"; } return null; } }
SAMLRealmCodec implementation
SAMLRealmCodec
. The purpose of the codec is to determine the realm that originally issued the received token, by inspecting the contents of the token. In this implementation, it is assumed the SAML assertion's Issuer
string uniquely identifies the issuing realm.
Example 9.6. Demonstration SAMLRealmCodec Implementation
// Java package org.apache.cxf.systest.sts.realms; import org.apache.cxf.sts.token.realm.SAMLRealmCodec; import org.apache.ws.security.saml.ext.AssertionWrapper; /** * This class returns a realm associated with a SAML Assertion depending on the issuer. */ public class IssuerSAMLRealmCodec implements SAMLRealmCodec { /** * Get the realm associated with the AssertionWrapper parameter * @param assertion a SAML Assertion wrapper object * @return the realm associated with the AssertionWrapper parameter */ public String getRealmFromToken(AssertionWrapper assertion) { if ("A-Issuer".equals(assertion.getIssuerString())) { return "A"; } else if ("B-Issuer".equals(assertion.getIssuerString())) { return "B"; } return null; } }
IdentityMapper implementation
Example 9.7. Demonstration IdentityMapper Implementation
// Java package org.apache.cxf.systest.sts.realms; import java.security.Principal; import org.apache.cxf.sts.IdentityMapper; import org.apache.ws.security.CustomTokenPrincipal; /** * A test implementation of RealmParser. */ public class CustomIdentityMapper implements IdentityMapper { /** * Map a principal in the source realm to the target realm * @param sourceRealm the source realm of the Principal * @param sourcePrincipal the principal in the source realm * @param targetRealm the target realm of the Principal * @return the principal in the target realm */ public Principal mapPrincipal(String sourceRealm, Principal sourcePrincipal, String targetRealm) { if ("A".equals(sourceRealm) && "B".equals(targetRealm)) { return new CustomTokenPrincipal("B-Principal"); } else if ("B".equals(sourceRealm) && "A".equals(targetRealm)) { return new CustomTokenPrincipal("A-Principal"); } return null; } }