OpenSSO acts as an authentication hub and as such supports many different modules. We recently upgraded one of them, OpenID, from OpenID 1.0 to OpenID 2.0. This module was written using both OpenSSO’s client library and OpenID4Java library.
This blog post describes the steps necessary to deploy the OpenID 2.0 extension module for OpenSSO. Once deployed, this module will add both OpenID 1.0 and 2.0 support for your IdP. In OpenID parlance, your OpenSSO deployment can act as an OP (OpenID Provider) and thus authenticate users for OpenID client applications.
In the example below, I will be using 2 different hostnames for clarity purposes: openid.example.com to run the OpenID module and opensso.example.com to run OpenSSO and the OP. Remember to, at a minimum, use 2 separate instances of your application server (I use & recommend Glassfish-v2.1): one for OpenID and the other for OpenSSO.
For the OpenID module
-
Deploy the openid war file.
-
Update 3 properties file with values taken from the opensso deployment. Those files are: AMConfig.properties, Provider.properties and ldap.properties (if the OP will be persisting user’s OpenID attributes). Sample configuration files are described at the end of this document.
-
Add properties files to the Classes directory (e.g. /Applications/NetBeans/glassfish-v2.1/domains/domain2/applications/j2ee-modules/openid/WEB-INF/classes/ on my Mac). Note that the domain MUST be restarted once those files have been added. Also at the moment, these files will have to be copied each time the openid war file is (re)deployed.
For OpenSSO
-
Add openid.example.com in the list of realm aliases
(Access Control tab → top realm → General tab) -
Add an OpenID attribute to OpenSSO’s user schema. To do so, insert the following attribute in the <user> section of amUser.xml:
<AttributeSchema name=”ldap.people.return.attribute” type=”single” syntax=”string”
any=”display” i18nKey=”openid-attributes”></AttributeSchema>
This file should be located in your opensso deployment directory under …/config/xml/ (or WEB-INF/classes/). -
Add this OpenID attribute to OpenSSO’s embedded ldap directory (I use Apache Directory Studio)
-
Enable self update of OpenID attribute in the ldap directory: to do so you have 2 choices (thanks to Rajeev for this tip):
-
If you have a LDAP editor:
-
connect to embedded config store directory (default : localhost:50389)
-
login as user cn=Directory Manager )
-
navigate to dn: ou=SelfWriteAttributes,ou=Policies,ou=default
,ou=OrganizationConfig,ou=1.0,ou=iPlanetAMPolicyService,
ou=services,o=sunamhiddenrealmdelegationservicepermissions,
ou=services,dc=opensso,dc=java,dc=net -
Edit the sunKeyValue attribute to add the openID attribute declared in OpenSSO’s schema:
<Value>openid-attibutes</Value> or
-
-
Using the addwriteperm.ldif (see content of this file at the end of this document):
-
Edit the file addwriteperm.ldif and insert the OpenID attribute (openid-attibutes).
-
Execute the shell command:
$DS/ldapmodify -h localhost -p 50389 -a -f ~/bin/addwriteperm.ldif
-D “cn=Directory manager” -w password
-
-
-
You need to add LDAP attributes to the users data store. Log in OpenSSO as admin, browse to the Data Store tab, select the appropriate store (or the users) and add openiduser to the LDAP User Object list and openid-attributes to the LDAP User Attributes list.
-
Restart your app server.
Configuration Files
Below are sample configuration files (only key configuration values are being shown).
AMConfig.properties
- com.iplanet.am.naming.url=
http://opensso.example.com:8080/opensso/namingservice - com.sun.identity.agents.app.username=amAdmin
- com.iplanet.am.service.password=changeme
- com.iplanet.am.service.secret=
AQIC1MSQKNB2HObD21Z8jsHOqPnCKCvL+ACy - am.encryption.pwd=mYqo9kXOHz4pju/dCDVGewVNcl9HsabR
- com.iplanet.am.server.host=opensso.example.com
- com.iplanet.am.server.port=8080
- com.iplanet.am.services.deploymentDescriptor=/opensso
- com.sun.identity.loginurl=
http://opensso.example.com:8080//opensso/UI/Login - com.sun.identity.liberty.authnsvc.url=
http://opensso.example.com:8080//opensso/Liberty/authnsvc
Provider.properties
- openid.provider.service_url=
http://openid.example.com:49723/openid/service - openid.provider.setup_url=
http://openid.example.com:49723/openid/setup.jsf - openid.provider.local-auth-url=
http://openid.example.com:49723/openid/authentication - openid.provider.login_url=
http://opensso.example.com:8080/opensso/UI/Login?realm=openid - openid.provider.simple_registration=true
- openid.provider.attribute_exchange=true
- openid.provider.identity_pattern=
http://openid.example.com:49723/openid/(.+) - openid.provider.principal_pattern=id=(.+),ou=user,dc=opensso,dc=java,dc=net
- openid.provider.external_target=_blank
- openid.provider.strict_protocol=false
- openid.provider.am-profile-attributes=uid|uid,givenName|firstname,sn|lastname,cn|
fullname,postalcode|postcode,c|country,mail|email - openid.provider.am-search-attribute=uid
- openid.provider.attribute_types_map=uid|text,email|text,firstname|text,lastname|
text,fullname|text,nickname|text,dob|date,gender|text,postcode|text,country|
select,language|select,timezone|select - openid.provider.persistence.enabled=true
- openid.provider.persistence.class.name=
ldap.properties
- ldap.host=opensso.example.com
- ldap.port=50389
- ldap.bind.dn=cn=Directory Manager
- ldap.bind.pwd=adminadmin
- ldap.people.base=dc=opensso,dc=java,dc=net
- ldap.people.return.attribute=openid-attributes
- ldap.people.attribute.nodes=firstname,lastname,fullname,nickname,email,
gender,dob,postcode,country,
language,timezone - ldap.people.search.attribute=uid
addwriteperm.ldif
- dn:
ou=SelfWriteAttributes,ou=Policies,ou=default,ou=OrganizationConfig,ou=1.0,
ou=iPlanetAMPolicyService,ou=services,o=sunamhiddenrealmdelegationservicepermissions,
ou=services,dc=opensso,dc=java,dc=net
changetype: modify
replace: sunKeyValue
sunKeyValue: xmlpolicy=<?xml version=”1.0″ encoding=”UTF-8″?><Policy name=”SelfWriteAttributes” referralPolicy=”false” active=”true” ><Rule name=”user-read-rule”> <ServiceName name=”sunAMDelegationService” /> <ResourceName name=”sms://*dc=opensso,dc=java,dc=net/sunIdentityRepositoryService/1.0/application/*” /> <AttributeValuePair> <Attribute name=”MODIFY” /> <Value>allow</Value> </AttributeValuePair> </Rule> <Subjects name=”Subjects” description=””> <Subject name=”delegation-subject” type=”AuthenticatedUsers” includeType=”inclusive”> </Subject> </Subjects> <Conditions name=”AttrCondition” description=””> <Condition name=”condition” type=”UserSelfCheckCondition”> <AttributeValuePair><Attribute name=”attributes”/><Value>sunIdentityServerDeviceStatus</Value><Value>telephonenumber</Value><Value>userpassword</Value><Value>givenname</Value><Value>mail</Value><Value>sn</Value><Value>cn</Value><Value>iplanet-am-user-password-reset-options</Value><Value>postaladdress</Value><Value>sunIdentityServerDeviceKeyValue</Value><Value>preferredlocale</Value><Value>description</Value><Value>iplanet-am-user-password-reset-question-answer</Value><Value>openid-attributes</Value> </AttributeValuePair> </Condition> </Conditions> </Policy>
Testing your deployment
To test your OpenID deployment you will need to have a web application that hands out OpenID identifiers as well as an OpenID client application (this is in addition to the OpenID extension and the OpenSSO instance described above). We also assume you have some users registered in the OpenSSO instance.
We’ve created a very simple application (OP.war) that will serve OpenID identifiers of the form:
http://your_hostname/OP/resources/user_name. Note that in its current form the identifier will point to an OP deployed at the following URL: http://openid.example.com:49723/openid/service
If your deployment URL differs, you’ll have to edit the (only) java file and change that link (in 2 places) before re-compiling the war file.
In our example, we’ll deploy the OP in the same domain than the OpenSSO instance, at the URI (http://opensso.example.com:8080/OP/).
A way to verify the OP is to visit a URI of the form http://opensso.example.com:8080/OP/resources/username where username can be anything. You should see some text explaining what the OP is based on but more importantly you can right-click on the page to take a look at the html source of the page. Note the OpenID metadata present in the HTML <head> section of the page.
OpenID4Java (the library that was used to create the OpenID extension) offers a nice little OpenID client application (Consumer-servlet) that lets you test both OpenID 1.0 and OpenID 2.0 (with persistance of attributes).
In our example, we’ll deploy the OpenID client application in the same domain than the OpenID extension, at the URI: (http://openid.example.com:49723/consumer-servlet/).
2 scenarios can be tested:
OpenID 2.0 Authentication
This scenario demonstrates OpenID-based delegated authentication with an OpenSSO IdP.
- Visit the OpenID Service Provider (aka. Relying Party)
http://openid.example.com:49723/consumer-servlet/ - In the (Sample 1) OpenID Username, enter the OpenID identifier:
http://opensso.example.com:8080/OP/resources/username
and click on Login - You’re redirected to OpenSSO login page. Log in with the credentials of a known user. Note that the user must correspond to the provided OpenID identifier. That mapping is determined by the pattern declared in the Provider.properties file (with the openid.provider.identity_pattern property).
- The next page is the OpenID verification (or consent) page.
Click on trust. - You’re now logged in the blog site.
OpenID 2.0 Authentication with Simple Registration Exchange
In addition to delegated authentication, this demonstrates the provisioning of attributes to the Relying Party.
- Before starting, close all browser windows (or clean cookies) to make sure you don’t have a live session at the IdP.
- Browse to the Relying Party at to the following URL:
http://opensso.example.com:49723/consumer-servlet/ - In the Sample 2 box, enter the same OpenID identifier as above (username being anything you want):http://opensso.example.com:8080/OP/resources/username
- Select (or de-select) the attributes that will be provided at the same time authentication takes place (make sure to leave at least one selected).
- You’re now redirected to OpenSSO for authentication. Enter the credentials of the corresponding user.
- In addition to the same consent page, notice the attributes that were requested. Fill up those information. You can chose to have those attributes remembered, in which case they will be persisted in the ldap directory.
Click on trust. - You’re now back at the Relying Party site on a page that shows the query string and the attributes requested.
September 1, 2009 at 14:47
[…] Deploying the OpenID2.0 Extension for OpenSSO In my previous blog on deploying the OpenID extension with OpenSSO, there is a step (step #3 for OpenSSO) in which you […]
September 7, 2009 at 23:48
[…] The OpenID4java library, upon which is built our extension, already supports this validation. To leverage this feature in your OpenSSO deployment, you’ll have to do the following (I’m assuming you already have deployed the OpenID extension; if not, see this post): […]
September 11, 2009 at 21:01
[…] OpenID 2.0. Hubert’s blog entries cover a number of topics specific to the rewrite, including deployment (with an important follow up) and realm/relying party validation. C’est la Vie is definitely […]
October 23, 2009 at 02:24
[…] OpenID 2.0. Hubert’s blog entries cover a number of topics specific to the rewrite, including deployment (with an important follow up) and realm/relying party validation. C’est la Vie is definitely […]
November 6, 2009 at 21:19
I have used this trick to add a few user writable attributes myself. While this worked OK in Express Build 7, it didn’t work anymore in Express Build 8.
I have noticed that in that version you also have to change ou=SelfWriteAttributes,ou=default,ou=default,ou=OrganizationConfig,ou=1.0,ou=sunEntitlementIndexes,ou=services,o=sunamhiddenrealmdelegationservicepermissions,ou=services,dc=opensso,dc=java,dc=net.
BTW. Apache Directory Studio is an excellent LDAP editor for doing this kind of stuff.
November 7, 2009 at 17:56
Hi Jan,
Interesting, I need to check on Express Build 8. I can
attest though that this works fine on the latest OpenSSO
releases since this is what we use for our OpenID testing.
As for Apache DS, yes it’s a nice ldap editor although
I think it does not work very well with the latest
OpenDS (2.0)…
December 21, 2009 at 20:52
I’m trying to install this OpenID extension on a Linux RHEL5 box, with a Tomcat 6.0.20 installation, and a Java 1.6.0.17 JVM. I am a newbie to OpenSSO as well as JSF, so trying to get this extension working on this setup is proving to be a challenge.
In fact, I’m wondering if the extension can run on this setup at all, given what looks like JSF incompatibility issues with my Tomcat 6 setup. The README file for the extension tells me to go grab Facelets 1.1.14, which seems to be packaged with servlet 2.4. Tomcat 6.x works with Servlet 2.5. Is that going to be a problem?
Plus, I’m getting JSF related classloader problems, when I install the jsf-impl.jar file for the JSF 1.2_04-p02 api that comes with Facelets 1.1.4. catalina.out reports this:
java.lang.LinkageError: loader constraint violation: when resolving interface method “javax.servlet.jsp.JspApplicationContext.getExpressionFactory()Ljavax/el/ExpressionFactory;” the class loader (instance of org/apache/catalina/loader/WebappClassLoader) of the current class, com/sun/faces/config/ConfigureListener, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, javax/servlet/jsp/JspApplicationContext, have different Class objects for the type javax/el/ExpressionFactory used in the signature
at com.sun.faces.config.ConfigureListener.registerELResolverAndListenerWithJsp(ConfigureListener.java:1570)
Like I said, I have doubts that I can make this work on Tomcat 6 without updating various components that support this extension, which may lead me into a whole slew of other problems.
So my question for you, Hubert, is …should this work? I don’t want to spin my wheels on something that is never going to work, and I’m too ignorant to know that yet :-)
Thx in advance.
January 6, 2010 at 17:39
Still slogging away at this after holiday break – managed to get the openid.war file to load under Tomcat6 after mucking with the catalina.properties files and selectively removing jars that conflict with the RHEL5 alternatives — very very messy at the moment – hope I can figure out my cryptic notes later on
New questions:
1) Where to find/build OP.war from extension code?
Above you say
|We’ve created a very simple application (OP.war) |that will serve OpenID identifiers of the form:
|http://your_hostname/OP/resources/user_name.
I originally read that as if I could find in the extension sample code for a war file called “OP.war”. But it sounds like I must create such a war file myself? Or do I just redeploy the openid.war as OP.war?
2) Myriad names for same server?
Posting refers to
openid.example.com:49723
opensso.example.com:49723
in your host setup, are these hostnames referring to the same box where an app server listening on port 49723 has a deployed warball “openid.war”?
What about
openid.example.com:8080
demo.example.com:8080
opensso.example.com:8080
Again, are these all host names referring to an app server listening on port 8080 where the OpenSSO warball is deployed?
thanks.
January 6, 2010 at 23:28
Hi Susan,
Apologies for not responding to your previous comment. My holiday breaks was a long one :)
1) On the OP.war question: there is no such code in the OpenSSO repository, however I have just
published a post with a simple example of what such app would look like. Please be aware
that this is a very simplistic one but that’s a start (please see here).
2) On the names – you are right, the hosts pointing at port 49723 relate to the OpenID instance and the ones on 8080 to OpenSSO. I’ll clean that up, thanks for pointing that out.
January 6, 2010 at 23:15
[…] present example, we will simply hand out that information to any appropriately formed URL (see this post). A real OP should probably verify that the OpenID identifier used corresponds to an existing […]
January 7, 2010 at 14:42
It dawns on me…I might simply have the wrong expectations for what this OpenID OpenSSO extension is going to do for me. Let me ask for a reality check on what I’m expecting.
My belief is that this OpenSSO extension, when I get all the parts in line (the LDAP tweaks, the openid.war, the OP.war webapp, the resource I want to protect, the J2EE agent in front of that resource)…all will build towards the scenario where I can
->go to my OpenSSO console,
->go into my realm,
->click on the Authentication tab
->Click New to create a new module instance
and be presented with the option to create a module instance of type OpenID, along side the standard options of “Active Directory”, “Anonymous” etc.
Is that a reasonable expectation?
Or is the OpenID extension never designed to be a first class authentication module, but only something we integrate in a backdoor manner other than what I listed above?
January 8, 2010 at 18:39
Your postings on the OpenSSO users list about my expectations for what this extension can and cannot do were very helpful. Armed with that knowledge, I’m tackling your instructions here for the umpteenth time.
But is there a missing step above, in the OpenSSO configuration section, a step directing me to creat a subrealm called “openid”?
I say this because you list this property in the sampel AMConfig.properties
“openid.provider.login_url=
http://opensso.example.com:8080/opensso/UI/Login?realm=openid‘
I’m guessing I have a new realm to use the OpenID authentication (and have the top level realm continue to use whatever auth I needed), correct?
Related to that supposition: in step 1
“Add openid.example.com in the list of realm aliases (Access Control tab → top realm → General tab)”
doesn’t that alias get put into the alias for this new openid realm, not the top realm? Or must it go in the top realm for reasons I don’t fully understand yet?