Configure WSO2 Identity Server as SAML2 SSO IDP

WSO2 Identity Server is one of the powerful open source identity management solution. It can act as an SAML2 SSO IDP.  You can use Identity Server to integrate with different applications to achieve seamless user login in your enterprise. You can easily register your service provider applications using WSO2 Identity Server management console. Lets tryout SAML2 SSO sample that is shipped with WSO2 Identity Sever.

Setup SAML2 SSO Web Application.

Step 1. Check out the source from the repository location which contains the samples. You can find the latest sample from here

svn co https://svn.wso2.org/repos/wso2/carbon/platform/branches/turing/products/is/5.0.0/modules/samples/sso/

Step 2. Go to <HOME>/sso/SSOAgentSample directory

Step 3. Replace the exiting pom.xml file with this pom.xml file.  Because you can not build the sample with existing pom.xml file available in the WSO2 SVN until you build the whole platform.

Step 4. Build the project using Maven  3.0.X.

After successfully building the sample, A .war file named travelocity.com can be found inside the <HOME>/sso/SSOAgentSample/target folder.

Step 5. Deploy this sample web app on a web container. To do this, use the Apache Tomcat server.

Since sample web application is written based on Servlet 3.0 it needs to be deployed on Tomcat 7.x.

Use the following steps to deploy the web app in the web container:

a) Stop Apache Tomcat server if it is already running.

b) Copy  travelocity.war file to the <TOMCAT_HOME>/webapps folder.

c) Start Apache Tomcat server.

Step 6.  Configure SAML2 SSO parameters in the web application

The travelocity.properties file, which can be found inside the travelocity.com/WEB-INF/classes folder, can be used to change the properties like issuerID, consumer url and IdP url. This sample web application uses default values and you can override them by using the property file.  As an example,

  • A unique identifier for this SAML 2.0 Service Provider application :
SAML.IssuerID=travelocity.com
  • The URL of the SAML 2.0 Assertion Consumer :
 SAML.ConsumerUrl=http://localhost:8080/travelocity.com/samlsso-home.jsp
  • The URL of the SAML 2.0 Identity Provider :
SAML.IdPUrl=https://localhost:9443/samlsso

Once you do any edit to this file, You may need to restart the Tomcat server.  Now Sample web application is successfully deployed in the web container;  The next step is to configure WSO2 Identity Server as an identity provider.

Configuring SAML2 SSO IDP

Step 1. Login to management console and Add new  service provider

1

Step 2. Configure inbound  authentication for service provider.    Web application is going to communicate with Identity Server using SAML2 SSO web browser profile.  Therefore we need to register web application as SAML2 SSO service provider.

2

Step 3. Following are the service provider configuration options

samlssonew4

 

Issuer :  This is the entity id for SAML2 service provider.

Assertion Consumer URL:  ACS url of the service provider. IDP redirects the SAML2 response to this ACS url.  But If SAML2 request is signed and SAML2 request contains ACS url,  Identity Server would honor to ACS url of SAML2 request. This value should be same as the SAML.ConsumerUrl value mentioned inside the travelocity.com/WEB-INF/classes/travelocity.properties file.

NameID format:  SP and IdP usually communicate each other about a subject. That subject should be identified through a Name-Identifier (NameID) , which should be in some format so that It is easy for the other party to identify it based on the format.  There are some formats that are defined by SAML2 specification. Default format is used by IDP is urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

Use fully qualified username in the NameID :   Fully qualified username means that the user name with user store domain or tenant domain.

If authenticated user is from secondary user store username would be set as  {user store domain}/{user name}.

If authenticated user is from tenant then username would be set as  {user name}@{tenant domain}

If authenticated user is from secondary user store and from tenant username would be set as  {user store domain}/{user name}@{tenant domain}

If you do not enable this,  it would be just the authenticating username would be returned.

Define Claim Uri for NameID :  If you want to define an any other user attribute as the NameID. You want to select the check box and define the claim uri that you need to use for it.

Enable Response Signing :  SAML2 Response must be signed or not

Enable Assertion Signing : SAML2 Assertion must be signed or not

Enable Signature Validation in Authentication Requests and Logout Requests : Whether to IDP must validate the signature of SAML2 auth request and SAML2 logout request that are sent by service provider.

Enable Assertion Encryption : SAML2 Assertion must be encrypted or not

Certificate Alias :  Select the certificate that is used to validate signature of SAML2 requests and cretificate that is used to generate encryption. Basically the Service provider’s certificate must be selected.

Enable Single Logout : Whether single logout must be enabled or not. Once single logout is enabled, IDP would send logout requests to all service providers. Basically,  IDP acts according to the single logout profile. If service provider supports a different url for logout, You can define different url for logout  If not,  IDP uses the ACS url.  More details, can be found here

Enable Attribute Profile :  Identity Server supports for basic attribute profile that IDP can include user’s attributes in the SAML Assertions as attribute statement.  We can define the claims that must be included under service provider claim configurations… I will go through it later…  Also, Once you select the check box of  “Include Attributes in the Response Always”, IDP always includes the attribute values related to selected claims in to the SAML Attribute statement.

Enable Audience Restriction : You can define multiple audience in the SAML Assertion.  Configured audiences would be added in to the SAML2 Assertion.

Enable IdP Initiated SSO  : Enable IDP initiated SSO.  When this is enabled,  service provider does not want to send SAML2 request.

Once IDP is registered, Consumer index is generate for service provider.   If you do not select to include attribute in SAML2 assertion always, Then service provider must send this index in the SAML request that is sent by the service provider.  You can find more details from here

5

 

Service Provider Claim Mapping

 

Following steps are not required.  But it is needed, if you want to send the authenticated users attributes in the SAML2 Assertion.

Step 4. Configure claim mapping for service provider.

You can select the claims that must be sent to the service provider.   If you just want to sent them as claim uris  (as WSO2 uris), Then please select  “Use Local Claim dialect“.  You can add them by clicking on  “Add Claim URI”

Please note that these claims would be added in to the SAML2 Assertion, only if you tick on “Enable Attribute Profile” in SAML2 Issuer configurations.

samlssonew1

 

 

 

If you trace the SAML2 Assertion, you would found as these claims in attribute statement as following.


<saml2:AttributeStatement>
 <saml2:Attribute Name="http://wso2.org/claims/role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
 <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string" >admin,Internal/everyone</saml2:AttributeValue>
 </saml2:Attribute>
 <saml2:Attribute Name="http://wso2.org/claims/emailaddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
 <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">asela@soasecurity.com</saml2:AttributeValue>
 </saml2:Attribute>
 </saml2:AttributeStatement>

 

If you want to define new uris for the attributes that are sent (Actually for the “Name” value in the “Attribute” element), You can define any values for them and map these values with WSO2 Claim uris.  Say, you want to sent email address of the user  as “http://soasecurity.org/claims/emailaddress”  claim uri…   you can define it and  map it in to “http://wso2.org/claims/emailaddress” .   Uri may be depend on how your SP is reading it. Therefore,  you may need to map claims uris in to what SP is preferred.

You need to select “Define Custom Claim Dialect” and define the claim mapping.  Please make sure to mark them as “Requested Claim”

 

samlssonew3

 

Then your attribute statement would be changed as following..


<saml2:AttributeStatement>
 <saml2:Attribute Name="http://soasecurity.org/claims/role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
 <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string" >admin,Internal/everyone</saml2:AttributeValue>
 </saml2:Attribute>
 <saml2:Attribute Name="http://soasecurity.org/claims/emailaddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
 <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">asela@soasecurity.com</saml2:AttributeValue>
 </saml2:Attribute>
 </saml2:AttributeStatement>

 

 User Name for SAML2 Assertion

 

You can trace username for NameID value of the SAML2 Assertion.

<saml2:Subject>
	<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin</saml2:NameID>
</saml2:Subject>

By default,  Username would be the value that you are providing for authentication.  However,  username would be changed in multiple user store and tenant scenarios as explained in “Use fully qualified username in the NameID :”  config.

  • If authenticated user is from secondary user store username would be set as  {user store domain}/{user name}.
  • If authenticated user is from tenant then username would be set as  {user name}@{tenant domain}
  • If authenticated user is from secondary user store and from tenant username would be set as  {user store domain}/{user name}@{tenant domain}

However,  if you like to select any other user’s attribute to add in to the NameID, you can do it as well.  Under claim configuration, you can find a configuration called “Subject Claim URI:”.  Here you can select a desired claim uri that you need to select.  Then user’s attribute value of selected claim uri would be added as NameID.

samlssonew2

Note: please make sure, WSO2IS may complain some error,  if you configure email value as “Subject Claim URI:”. If you found such issue,  you need to configure “EnableEmailUserName”  property  as described in here

Authentication for end users

 

By default,  end users can provide the username/password and authenticated with WSO2IS.  If you need to extend that capabilities,  you can do it as well.  More details can be found on my federated authentication blogs

Step 5. Configure outbound authentication.  Here we just keep it as default configuration. It means IDP authenticate the users with username/password by validating with IDP’s user store.

9

Step 6. Update service provider details.

6

Step 7.  Now you are done.  When you try to login to web application.  You would be directed to Identity Server SAML2 SSO login page.  Once you provide the valid credentials, You would be login to the web application.  You can see the attribute values that are received via SAML token.   You can trace the SAML request and SAML respose messages.

Thanks for reading….!!!

Discuss this article on Stack Overflow

Comments

  1. When I build the project using maven, as mentioned in ‘step 4’, i get the following error:

    [ERROR] Failed to execute goal on project org.wso2.sample.is.sso.agent: Could not resolve dependencies for project org.wso2.identity:org.wso2.sample.is.sso.agent:war:1.2.0: Failure to find org.wso2.carbon:org.wso2.carbon.identity.sso.agent:jar:1.2.0 in http://maven.wso2.org/nexus/content/groups/wso2-public/ was cached in the local repository, resolution will not be reattempted until the update interval of wso2-nexus has elapsed or updates are forced

  2. Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.1:war (default-war) on project org.wso2.sample.is.sso.agent: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode)

  3. An error has occurred
    SAMLResponse signing is enabled, but signature element not found in SAML Response element.

    When login with SAML above error is generated in the home page of travelocity. Any guess?

    1. As error mentioned.. It seems to be “SAML Response” has not be signed by IDP. To enable SAML response signing, you need to tick on following box “Enable Response Signing” when registering your SP in IDP

  4. Thanks for the quick response. Now i encounter another error. Once the machine(localhost) is restarted we can’t start(./wso2server.sh start) the identity server. It gives the following error.

    ‘ps: write error: Bad file descriptor’

  5. Hi Asela,

    I have the sample app and the Identity servers are running different servers. I’m getting the below error in Home.jsp after successful login and redirection from IS.

    Application Environment:
    Tomcat 8.0.14.0
    JDK 1.8.0_20

    WSO2 Identity Server version 5.0.0

    06-Oct-2014 09:55:14.777 SEVERE [http-apr-8080-exec-6] null.null An error has occurred
    org.wso2.carbon.identity.sso.agent.exception.SSOAgentException: Signature validation failed for SAML Response
    at org.wso2.carbon.identity.sso.agent.saml.SAML2SSOManager.validateSignature(SAML2SSOManager.java:577)
    at org.wso2.carbon.identity.sso.agent.saml.SAML2SSOManager.processSSOResponse(SAML2SSOManager.java:297)
    at org.wso2.carbon.identity.sso.agent.saml.SAML2SSOManager.processResponse(SAML2SSOManager.java:198)
    at org.wso2.carbon.identity.sso.agent.SSOAgentFilter.doFilter(SSOAgentFilter.java:89)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:277)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2403)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2392)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

    Also, getting the below error in Eclipse during Maven run configuration (Goal: tomcat:run)

    SEVERE: Exception sending context initialized event to listener instance of class SampleContextEventListener
    java.lang.NoSuchMethodError: javax.servlet.ServletContext.getClassLoader()Ljava/lang/ClassLoader;
    at SampleContextEventListener.contextInitialized(SampleContextEventListener.java:29)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4135)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4630)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:445)
    at org.apache.catalina.startup.Embedded.start(Embedded.java:825)
    at org.codehaus.mojo.tomcat.AbstractRunMojo.startContainer(AbstractRunMojo.java:558)
    at org.codehaus.mojo.tomcat.AbstractRunMojo.execute(AbstractRunMojo.java:255)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:584)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:213)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:157)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)

    Oct 06, 2014 10:14:12 AM org.apache.catalina.core.StandardContext start
    SEVERE: Error listenerStart
    Oct 06, 2014 10:14:12 AM org.apache.catalina.core.StandardContext start
    SEVERE: Context [/org.wso2.sample.is.sso.agent] startup failed due to previous errors

    1. Hi Siva, I am not sure exact issue. But i hope this can be due to java version. I have not tested this in java 8 and also Wso2 product still can not be run in java 8

  6. Thanks for this article. I have set up something very similar. My wso2 response does not include a sessionIndex attribute. Do you know what may have caused this?

    thanks

    1. I think, you may have not enabled the “Enable Single Logout :” in SAML2 SSO issuer configuration. If it is only enabled the single logout, it would return the “sessionIndex” attribute

  7. SAML2 SSO web browser profile does not supported with SAM 1.1. But you can use Passive STS. Then WSO2IS will return SAML1.1 Assertion.

  8. Is it possible to integrate WSO2IS with Spring Boot? I am facing many issues and currently stuck with error “No unmarshaller registered for document element EntityDescriptor”

  9. As i know, it can be done. There are some users already have done it. But i am not aware about the exact configurations in Spring side. If you found any issue in WSO2IS side, let me know. I can help.

    Also; there is some single logout error with Spring as some limitation in WSO2IS. But login must work

  10. Hi Asela,

    I am trying to install WSO2IS SSO configuration.Configuring SSO Web configuration is failing.I have restarted apache TOMCAT after deploying .war file but it is failing with the following warning.AS I am new to this,It would be really great if someone can help me how to solve this issue.

    WARNUNG: ‘SSOAgentPropertiesFilePath’ not configured
    Mrz 09, 2016 9:46:55 AM org.wso2.carbon.identity.sso.agent.util.SSOAgentConfigs
    initCheck
    INFORMATION: ‘SAML.AttributeConsumingServiceIndex’ not configured. No attributes
    of the Subject will be requested
    SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”.
    SLF4J: Defaulting to no-operation (NOP) logger implementation

    Thanks in Advance.

    Regards
    Jaya

  11. Hi I am getting the following error for SAML response in Tomcat logs::
    org.wso2.carbon.identity.sso.agent.SSOAgentException: SAML2 Assertion not found in the Response
    at org.wso2.carbon.identity.sso.agent.saml.SAML2SSOManager.processSSOResponse(SAML2SSOManager.java:408)
    at org.wso2.carbon.identity.sso.agent.saml.SAML2SSOManager.processResponse(SAML2SSOManager.java:303)
    at org.wso2.carbon.identity.sso.agent.SSOAgentFilter.doFilter(SSOAgentFilter.java:97)
    at org.wso2.sample.is.sso.agent.SSOAgentSampleFilter.doFilter(SSOAgentSampleFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

    1. Did you enable SAML Assertion encryption in WSO2IS SAML2 SSO issuer configuration ?

      1. Hello I am having the same exact issue with the “SAML2 Assertion not found in the Response”. I have run into this with both Enable Assertion Encryption ticked and not. Any ideas?

  12. great article and I have performed these steps, but no matter what I try the attributes are not part of the saml response sent to the SP. Is there a back end switch that isn’t included in the ui or something that is preventing the information from coming through?

Leave a Reply

Your email address will not be published. Required fields are marked *