Today we just added support in our OpenID extension (note to myself: this page needs a serious update…) for another OpenID 2.0 feature: realm & RP validation.

As described in the OpenID 2.0 specification, it is important for an IdP (sorry I mean an OP in OpenID parlance) to verify that the Relying Party (RP) return_to URL (that is the endpoint the browser will be redirected to once authentication has happened at the OP) is indeed an OpenID endpoint. The OP should also verify that this return_to URL is within the realm of the RP. This validation is done by having the OP perform a Yadis-based discovery of the RP (see here for more details).

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):

  1. Create an XRDS document that you’ll host at the RP site.This file describes the RP endpoint and will be retrieved by the OP. At a minimum the file contains one service description with one endpoint (your return_to URL). To folllow up on the deployment I described in previous posts, my XRDS document (I named it yadis.xml) contains the following information:
    <?xml version="1.0" encoding="UTF-8"?>
       <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)"
                  xmlns:openid="http://openid.net/xmlns/1.0">
       <XRD>
          <Service xlmns="xri://$xrd*($v*2.0)">
            <Type>http://specs.openid.net/auth/2.0/return_to</Type>
            <URI>http://opensso.example.com:49723/consumer-servlet</URI>
          </Service>
       </XRD>
    </xrds:XRDS>
    
  2. In the Provider.properties file (see previous post) add the following property: openid.provider.enforcerpid=true (or false if you don’t want it…)

That’s it; now when your RP makes an authentication request, the OP will validate the RP’s endpoint.

In my previous blog on deploying the OpenID extension with OpenSSO, there is a step (step #3 for OpenSSO) in which you have to add the OpenID attribute you created to OpenSSO’s embedded OpenDS directory.
To be more explicit, a way to achieve this is to connect to you OpenSSO DS store and run the following ldif fragment:

dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( 2.16.840.1.113730.3.1.9990 NAME ‘openid-attributes’ DESC ‘Persisted attributes (OpenID)’ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN ‘
Attributes (OpenID)’ )

add: objectClasses
objectClasses: ( 2.16.840.1.113730.3.2.9999 NAME ‘openiduser’ DESC ‘Class to hold the OpenID related attributes’ SUP top AUXILIARY MAY ( uid $
openid-attributes ) X-ORIGIN ‘OpenID Attributes object class’ )

To connect to the OpenSSO embedded store, I recommend you use a tool (e.g. Apache Directory Studio). Feed it with the relevant information: hostname (i.e. opensso.example.com), port (usually 50389) and possibly your encryption method.

Of course, tune the ldif example above to the same name (here openid-attributes) you used in amUser.xml

A quick summary of the OAuth support we’ve recently added in a couple of key projects.

If you’re into RESTful web services and OAuth, we have implemented an extension to the Jersey project (the JAX-RS Reference Implementation). This extension allows for the signing and/or the verification of OAuth 1.0 based requests. It is based on a digital signature library accessed by server and client filters. Detailed information can be found here.

For people interested in a more integrated solution, we have also implemented a module for the open source project OpenSSO to supports OAuth as an authentication module. This module handles the Service Provider side, that is: token issuance, token & message verification as well as SSO session handling (to bridge with other protocols). This module is, for now, an extension to OpenSSO. In other words it is not yet part of the core OpenSSO and should be considered as more experimental. Beside the Java doc, a good source of information on this can be found in this article. There’s also Pat’s demo at Community One this year.

If you’re so inclined, give it a try – any feedback is more than welcome!

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

  1. Deploy the openid war file.

  2. 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.

  1. 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

  1. Add openid.example.com in the list of realm aliases
    (Access Control tab → top realm → General tab)

  2. 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/).

  3. Add this OpenID attribute to OpenSSO’s embedded ldap directory (I use Apache Directory Studio)

  4. Enable self update of OpenID attribute in the ldap directory: to do so you have 2 choices (thanks to Rajeev for this tip):

    1. If you have a LDAP editor:

      1. connect to embedded config store directory (default : localhost:50389)

      2. login as user cn=Directory Manager )

      3. 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

      4. Edit the sunKeyValue attribute to add the openID attribute declared in OpenSSO’s schema:
        <Value>openid-attibutes</Value> or

    2. Using the addwriteperm.ldif (see content of this file at the end of this document):

      1. Edit the file addwriteperm.ldif and insert the OpenID attribute (openid-attibutes).

      2. Execute the shell command:
        $DS/ldapmodify -h localhost -p 50389 -a -f ~/bin/addwriteperm.ldif
        -D “cn=Directory manager” -w password

  5. 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.

  6. Restart your app server.

Configuration Files

Below are sample configuration files (only key configuration values are being shown).

AMConfig.properties

Provider.properties

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.

  1. Visit the OpenID Service Provider (aka. Relying Party)
    http://openid.example.com:49723/consumer-servlet/
  2. In the (Sample 1) OpenID Username, enter the OpenID identifier:
    http://opensso.example.com:8080/OP/resources/username

    and click on Login
  3. 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).
  4. The next page is the OpenID verification (or consent) page.
    Click on trust.
  5. 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.

  1. Before starting, close all browser windows (or clean cookies) to make sure you don’t have a live session at the IdP.
  2. Browse to the Relying Party at to the following URL:
    http://opensso.example.com:49723/consumer-servlet/
  3. 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
  4. 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).
  5. You’re now redirected to OpenSSO for authentication. Enter the credentials of the corresponding user.
  6. 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.
  7. You’re now back at the Relying Party site on a page that shows the query string and the attributes requested.

As mentioned before, during this last JavaOne, my colleague Pat Patterson has been showing a demo that leverages JavaFX and our OpenSSO’s OAuth module (preview for now). Daniel Raskin (our OpenSSO marketing guru at Sun) and him have created a video about the demo here. Check it out, it’s informative and very funny.

I had mentioned in a previous blog an issue I was seeing with my web application and its use of JPA. It turns out (thanks to people on the Glassfish users mailing list) that, after a refactoring, my JPQL query was rendered wrong up by using the name of the table instead of the name of the Java entity.
So
@NamedQueries(name = "Acctoken.findAll", query = "SELECT a FROM Acctoken a")
should have been:
@NamedQuery(name = "AccessToken.findAll", query = "SELECT a FROM AccessToken a")
Simple enough but, as I had written before, the fact that it somehow was working for subsequent calls remains a mystery to me…

JavaOne’09 is now over. Lots of interesting sessions & great discussions. I loved the demo Pat Patterson made using our OAuth implementation. Marc Hadley and I had our BOF session and were pleasantly surprised to see more people than expected since it was late and in direct competition with JavaOne’s big party. Here are the slides we presented – hopefully this will encourage people to participate and help us in our quest for the ultimate identity framework!

Here’s an interesting problem I’m facing.
I have been working on a web application that I’m deploying using Glassfish. The web app leverages the Jersey framework (I really recommend it to anyone interested in RESTful development in Java). I also use the Java Persistence API to store objects in a DB. For all this, I’m using NetBeans tools to create a Persistence Unit and the entities I have to manage (from a DB schema). NetBeans also creates the appropriate mapping of the entities and their Java classes. So far so good…
For each entity, I end up with java classes that look something like this:

@Entity
@Table(name = "ACCTOKEN")
@NamedQueries({@NamedQuery(name = "Acctoken.findAll", query = "SELECT a FROM Acctoken a"),
@NamedQuery(name = "Acctoken.findById", query = "SELECT a FROM Acctoken a WHERE a.id = :id"),
@NamedQuery(name = "Acctoken.findByAcctUri", query = "SELECT a FROM Acctoken a WHERE a.acctUri = :acctUri")
/... more queries .../ })

public class AccessToken implements Serializable { /.../ }

The code above compiles fine and I can deploy the generated war file with Glassfish. However, and this is where I could use suggestions from anyone, I see a weird behaviour upon hitting one of the exposed endpoints:
The very first time I do a POST (or GET), the web application throws an exception that looks like:

Exception [TOPLINK-8034] (Oracle TopLink Essentials - 2.0.1 (Build b04-fcs (04/11/2008))):
oracle.toplink.essentials.exceptions.EJBQLException Exception Description: Error compiling
the query [Acctoken.findByAcctVal: SELECT a FROM Acctoken a WHERE a.acctVal = :acctVal].
Unknown abstract schema type [Acctoken]. at oracle.toplink.essentials.exceptions.
EJBQLException.unknownAbstractSchemaType (EJBQLException.java:494)

What’s funny is that this does not happen in any subsequent access to those URLs, the web app behaves properly. Because subsequent calls are fine I know the mapping does happen and is correct. I thus don’t really have to explicitly list the classes in the persistence.xml file and instead I have the <exclude-unlisted-classes>false</exclude-unlisted-classes> tag. However listing the classes will not help. I have verified this in both Glassfish 2.2 and Glassfish 3: same behaviour.

It really looks like Glassfish (what else?) adopts a “lazy” approach for the mapping to happen and is basically not ready for the 1st call. I already have the <load-on-startup /> tag set in my web.xml and this didn’t help.

So there it is, anyone has an idea?

The more I think and read about the session fixation issue (see the official announcement here and additional info there) that has been discovered in OAuth, the more I’m convinced of the benefits Identity Federation brings to the table.

Think about it, the main issue (beside securing the callback URL which is reasonably easy to achieve) is the fact that the (service) Consumer and the Service Provider can’t currently be sure that the user that has initiated the OAuth flow (and thus has logged in at the Consumer site) is the same user that logs in the Service Provider during the authorization process. If something akin to SAML‘s SSO model were in play (where identities of the principal at the consumer & SP site are federated in a privacy-preserving manner – meaning no correlation issue) then ensuring it is the same user would be a no brainer.

This also can be looked at from the token perspective and what information it conveys. Wouldn’t a SAML assertion be useful here?

Another interesting path would be to use something like Liberty’s Interaction Service to obtain confirmation from the user thus thwarting an attacker to obtain the access token in your name.

Yesterday, I attended the OAuth BOF that took place during the IETF meeting in San Francisco. My participation was virtual though, since I was not physically there but thanks to live mp3 coverage and a chat room it was actually possible to follow the discussions and ask questions – very nice.
There were lots of discussions addressing several areas; here’s my recollection on the main points that were discussed:

  • Interoperability: what elements do people think are must-haves to ensure interoperable implementations of the IETF OAuth specification? Mandating a minimum set of signature algorithms (yes!).
  • Backward compatibility: although very important, we should not prevent ourselves from changing key aspects of the specification for the sake of backward compatibility. This is especially true for security issues. Of course, when not essential, changes that would break compatibility will be discarded.
  • Items to be worked on: via the chat room (see log here), I asked if the 2-legged scenario could be considered as relevant to this specification (the 2-legged case is when the service consumer is equivalent to the principal. In other words, we only have 2 parties involved in the transaction). To my satisfaction, many people agreed and so, after a hum in the room passed, it was agreed to include that use case in this work.
  • Charter: although the goal was to not change it, 2 important modifications will be made: integrate the 2-legged scenario and water down the compatibility constraints.

Overall I think this was a good meeting and we now have an official OAuth working group at IETF (well, once the normal process is completed).