Saturday, September 28, 2013

Configuring OpenLDAP as external user store of WSO2 IS 4.5.0

By default WSO2 IS uses embedded ldap, which is shipped with the product, as the primary user store. But it's possible to configure other user stores (such as OpenLDAP, Active Directory and JDBC user stores) as primary user store. In this blog post I'm going to explain how to configure OpenLDAP as the primary user store of WSO2 IS 4.5.0 in following modes.
  • Read/Write mode
  • Read-only mode
- Since we no longer need embedded ldap, let's disable starting it at server start up. This can be changed in IS_HOME/repository/conf/embedded-ldap.xml


- Now let's comment out the default user store manager in user-mgt.xml which resides in IS_HOME/repository/conf.


OpenLDAP in Read/Write mode

- First uncomment relevant user store manager configuration. i.e.


Note : There are three such user store manager classes in user-mgt.xml. You have to uncomment the configuration which is available after following comment.



- Below I've attached a sample configuration.



Now let's walk through the above configuration to identity the properties that needs to be changed.

1) 
Here you have to provide the connection url of openldap. Pay attention to accuracy of ip and port when specifying it.

2) 
This is the bind dn or the user. i.e. Distinguished name used to authenticate to the Directory server when performing an operation. This user has permission to read all users and perform search operations in Directory server

3) 
This is the password of above bind dn or user

4) 
This is the directory in which users created through IS are stored. Also LDAP search for users starts from this location

5) 
This is the attribute to which the user name is mapped. "cn" and "uid" are commonly used for this purpose

6) 
This property specifies whether groups in LDAP should be read from IS or not. If we do not want to read LDAP groups then non of the other group related properties need to be changed

For more information, please go through IS documentation

7) 
If this is set to false, you cannot add groups to LDAP through Identity Server.

8) 
OpenLDAP does not allow to create roles without at least one user assigned to it. Therefore, if you are going to use openldap this property should be false.

9) 
This is the directory in which groups created through Identity Server are stored. In addition to that LDAP search for groups begin from this place.

Note : Changing the rest of the properties are optional and you can configure them according to your requirement.



- This configuration can be found on top part of user-mgt.xml

- If AddAdmin is set to true, at the first startup of Identity server it checks whether this admin user/admin role is in LDAP. If admin user/admin role are not there, IS adds them to LDAP.
You can set this to false if you need an existing admin user/role for IS.

- Admin user name, admin password and admin role can be changed according to your requirement.

OpenLDAP in Read-Only mode

- For this also we should first comment out the default user store manager as I've explained before.

- Since we need to configure LDAP in read only mode, uncomment following user store manager class


- Below I've attached a sample configuration.



- Properties are same as what I've explained earlier. Only difference is there's no need of having properties like UsernameJavaRegEx, UsernameJavaScriptRegEx, RolenameJavaScriptRegEx, RolenameJavaRegEx, PasswordJavaScriptRegEx, WriteGroups and EmptyRolesAllowed because we are not going to add users or role through Identity Server.


Since this is a read-only user store, you should provide a user who's already there in user store as the admin user.
But depending on your requirement you can provide and existing or non-existing admin role. If admin role is already not there in user store, then it will be added as an internal role at Identity serer first startup.

Special Note : You can find sample user-mgt.xml  files for read/write mode in this location  and for read-only mode here.

Below I've attached some images of LDAP to understand the LDAP structure used in this sample.






Monday, September 23, 2013

OpenID with WSO2 IS 4.5.0

In this blog post, I've used a sample web app to demonstrate the SAML 2.0 behavior with WSO2 IS 4.5.0.

web app

There we used the first option (i.e. Click here to login with SAML from Identity Server)

In this blog post I'm going to explain login with OpenID url provided by WSO2 IS 4.5.0 and hot to login to ap with a google account.

(1) Login with OpenID url provided by WSO2 Identity Server.

- Before trying out this scenario, we first need to import the self signed certificate used by WSO2 server to the trust store of the web container where the web app is deployed on.
Since we are using Apache Tomcat server, let's import the certificate to java cacerts.

First export the certificate using following command.

keytool -export -alias wso2carbon -keystore IS_HOME/repository/resources/security/wso2carbon.jks -storepass wso2carbon -file wso2carbon.pem


Now import this certificate to java cacerts.

keytool -import -alias wso2crbon -file wso2carbon.pem -keystore JAVA_HOME/jre/lib/security/cacerts


- Now click the second option in the web app
Login with OpenID
- You'll be redirect to IS for authentication
Authentication

- Provide valid user name/password. Here I've provided default admin credentials (admin/admin)
- You'll be asked to approve the OpenID user profile.

OpenID user profile
- Click approve or approve always. You'' be logged in and will be able to see the home page.
Home Page

(2) Login with google account.

- Logo ut from google account if you've already logged in and click the third url in the app.
Login with google account

- You'll be prompted to enter username/password. Provide valid credentials

Login  with google credentials
- You'll be logged in and can see the home page


Home Page



Wednesday, September 18, 2013

SAML 2.0 SSO with WSO2 IS 4.5.0

In this blog post, Suresh explains SAML 2.0 SSO behavior with WSO2 IS 3.2.3. WSO2 has released IS 4.5.0 recently and it contains many improvements to SSO. So here I'm going to explain the same scenario with IS 4.5.0.

Configure the web app

1. Check out the source.


2. Go to sso/SSOAgentSample (checked out folder) and build the sample with following command.


3. After successful build, sample war file can be found inside sso/SSOAgentSample/target folder.
sso/SSOAgentSample/target/travelocity.com

Now we need to deploy this sample web app on a web container. Let's use Tomcat server. Since this sample is written based on Servlet 3.0 it needs to be deployed on Tomcat 7.x.

4. Stop the Tomcat server if it's already running.

5. Copy travelocity.war file to TOMCAT_HOME/webapps folder.

6. Start the tomcat server.

Special Note :
travelocity.properties file inside travelocity.com/WEB-INF/classes folder can be used to change the properties like issuerID, consumer url and IdP url. For this sample I'm using default values. i.e.

#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

Now we've deployed the web app successfully on a web container. The next set is to configure WSO2 IS 4.5.0 as IdP.

Configure WSO2 IS 4.5.0 as IdP

1. Start Identity Server and access management console using https://localhost:9443/carbon/

2. Login to management console using default credentials. (i.e. admin/admin)

3. Go to Main -> Manage -> SAML SSO

SAML SSO

4. Click on "Register New Service Provider"

5. Register new service provider, providing following values.
  • Issuer : travelocity.com
(Note : This values should be same as the SAML.IssuerID value specified inside travelocity.com/WEB-INF/classes/travelocity.properties file)
  • Assertion Consumer URL : http://localhost:8080/travelocity.com/samlsso-home.jsp
(Note : This value should be same as the SAML.ConsumerUrl value mentioned inside travelocity.com/WEB-INF/classes/travelocity.properties file)
  • NameID format : default value (i.e. urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress)
  • Use fully qualified username in the NameID : true (tick the checkbox) 
  • Enable Response Signing : true (tick the checkbox)
  •  Enable Assertion Signing : true (tick the checkbox)
  • Enable Signature Validation in Authentication Requests and Logout Requests : true (Certificate alias = wso2carbon)
  • Enable Single Logout : true (tick the checkbox)
After providing above values click register. Below I've attached an image with configured values.

Registered service provider

6. After successfully registering the service provider logout from management console.

We've finished configuring IS as IdP. Now lets run the sample.

Run the sample

1. Visit http://localhost:8080/travelocity.com and you'll be taken to following page.

travelocity.com landing page

2. Since we're going to use SAML2, click the firs link (Click here to login with SAML from Identity Server)

SAML 2.0 login

3. You'll be redirected to IS for authentication.

authentication

4. Enter default admin credentials (admin/admin). 
5. Now you are logged in and you can see the home page of travelocity.com app

travelocity.com home page


Special note : 
1) If you need to view the SAML request and response, please add following debug log to log4j.properties file found inside wso2is-4.5.0/repository/conf

log4j.logger.org.wso2.carbon.identity=DEBUG

2) Since single log out is enabled, if you click logout button in travelocity.com home page, you'll be successfully logged out.

Thursday, September 12, 2013

How to resolve "java.lang.ClassNotFoundException: Error loading SSL Implementation edu.internet2.middleware.security.tomcat6.DelegateToApplicationJSSEImplementation" when deploying Shibboleth on tomcat

If you encounter following error


java.lang.ClassNotFoundException: Error loading SSL Implementation edu.internet2.middleware.security.tomcat6.DelegateToApplicationJSSEImplementation :java.lang.ClassNotFoundException: edu.internet2.middleware.security.tomcat6.DelegateToApplicationJSSEImplementation
at org.apache.tomcat.util.net.SSLImplementation.getInstance(SSLImplementation.java:77)
at org.apache.coyote.http11.Http11Protocol.init(Http11Protocol.java:156)
at org.apache.catalina.connector.Connector.initialize(Connector.java:1123)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:838)
at org.apache.catalina.startup.Catalina.load(Catalina.java:538)
at org.apache.catalina.startup.Catalina.load(Catalina.java:562)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Sep 12, 2013 1:38:27 PM org.apache.catalina.core.StandardService initialize
SEVERE: Failed to initialize connector [Connector[HTTP/1.1-8443]]
LifecycleException:  Protocol handler initialization failed: java.lang.ClassNotFoundException: Error loading SSL Implementation edu.internet2.middleware.security.tomcat6.DelegateToApplicationJSSEImplementation :java.lang.ClassNotFoundException: edu.internet2.middleware.security.tomcat6.DelegateToApplicationJSSEImplementation
at org.apache.catalina.connector.Connector.initialize(Connector.java:1125)
at org.apache.catalina.core.StandardService.initialize(StandardService.java:703)
at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:838)
at org.apache.catalina.startup.Catalina.load(Catalina.java:538)
at org.apache.catalina.startup.Catalina.load(Catalina.java:562)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)


what you have to do is to download tomcat6-dta-ssl-1.0.0.jar and place it inside TOMCAT_HOME/lib folder.

Tuesday, July 30, 2013

Adding users to WSO2 Identity server through SCIM end points when primary user store is OpenLDAP



Consider a scenario where OpenLDAP is used as the primary user store of WSO2 Identity Server .


Note : Above configuration is for WSO2 Identity Server 4.5.0

In this case if user provisioning is done through SCIM without any claim mappings, you'll observe below result.



[2013-07-31 10:09:43,827] ERROR {org.wso2.charon.core.protocol.endpoints.UserResourceEndpoint} -  Error in adding the user: SureshAtt to the user store..
org.wso2.carbon.user.core.UserStoreException: Can not access the directory context or user already exists in the system
at org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager.doAddUser(ReadWriteLDAPUserStoreManager.java:267)
at org.wso2.carbon.user.core.common.AbstractUserStoreManager.addUser(AbstractUserStoreManager.java:997)
at org.wso2.carbon.user.core.common.AbstractUserStoreManager.addUser(AbstractUserStoreManager.java:1020)
at org.wso2.carbon.identity.scim.provider.impl.SCIMUserManager.createUser(SCIMUserManager.java:109)
at org.wso2.charon.core.protocol.endpoints.UserResourceEndpoint.create(UserResourceEndpoint.java:147)
at org.wso2.carbon.identity.scim.provider.resources.UserResource.createUser(UserResource.java:137)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:193)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:102)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:94)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:218)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:198)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:137)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:158)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:243)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:163)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:219)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.wso2.carbon.tomcat.ext.valves.CompositeValve.continueInvocation(CompositeValve.java:178)
at org.wso2.carbon.tomcat.ext.valves.CarbonTomcatValve$1.invoke(CarbonTomcatValve.java:47)
at org.wso2.carbon.webapp.mgt.TenantLazyLoaderValve.invoke(TenantLazyLoaderValve.java:56)
at org.wso2.carbon.tomcat.ext.valves.TomcatValveContainer.invokeValves(TomcatValveContainer.java:47)
at org.wso2.carbon.tomcat.ext.valves.CompositeValve.invoke(CompositeValve.java:141)
at org.wso2.carbon.tomcat.ext.valves.CarbonStuckThreadDetectionValve.invoke(CarbonStuckThreadDetectionValve.java:156)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.wso2.carbon.tomcat.ext.valves.CarbonContextCreatorValve.invoke(CarbonContextCreatorValve.java:52)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1653)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: javax.naming.directory.InvalidAttributeIdentifierException: [LDAP: error code 17 - scimId: attribute type undefined]; remaining name 'uid=SureshAtt'
at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3110)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2987)
at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2794)
at com.sun.jndi.ldap.LdapCtx.c_bind(LdapCtx.java:397)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_bind(ComponentDirContext.java:277)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.bind(PartialCompositeDirContext.java:197)
at org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager.doAddUser(ReadWriteLDAPUserStoreManager.java:259)
... 49 more


To avoid this, have to map SCIM claims to attributes in OpenLDAP. More details can be found in this blog post written by Suresh.

Note : Same claim mapping can be done for OpenLDAP



Tuesday, July 16, 2013

Error when starting OpenLDAP

If you encounter following error when starting openldap...


Starting OpenLDAP: slapd - failed: 
/usr/sbin/slapd: /usr/local/lib/libldap_r-2.4.so.2: no version information available (required by /usr/sbin/slapd)
/usr/sbin/slapd: /usr/local/lib/liblber-2.4.so.2: no version information available (required by /usr/sbin/slapd)
/usr/sbin/slapd: relocation error: /usr/sbin/slapd: symbol ldap_pvt_sasl_mutex_dispose, version OPENLDAP_2.4_2 not defined in file libldap_r-2.4.so.2 with link time reference

solution is....

  • Changed the path for /etc/ld.so.conf.d/libc.conf

  • Ran following command (to setup correct link and to rebuild the cache)
/sbin/ldconfig -v


Please refer following for more information :




Monday, June 17, 2013

java.lang.IllegalStateException: No match found when installing Shibboleth

Have you ever encountered following error when installing Shibboleth.


Updating property file: IDP_HOME/shibboleth-identityprovider-2.4.0/src/installer/resources/install.properties
Created dir: IDP_HOME/bin
Created dir: IDP_HOME/conf
Created dir: IDP_HOME/credentials
Created dir: IDP_HOME/lib
Created dir: IDP_HOME/lib/endorsed
Created dir: IDP_HOME/logs
Created dir: IDP_HOME/metadata
Created dir: IDP_HOME/war

BUILD FAILED
IDP_HOME/shibboleth-identityprovider-2.4.0/src/installer/resources/build.xml:70: java.lang.IllegalStateException: No match found

It's because you've not provided a fully qualified hostname during installation.
e.g It should exactly match the format suggested by shibboleth. i.e. idp.example.org

If you specify localhost, example.org, etc.. then you'll encounter above error.