Showing posts with label security. Show all posts
Showing posts with label security. Show all posts

Saturday, January 30, 2010

Plaxo OpenID Recipe

Plaxo was probably one of the first main sites where I saw OpenID support for your user credentials. But only today did I notice that they also have a really nice write-up of of their OpenID implementation, which could serve you as a guide/recipe for implementing your own OpenID supporting user registration process.

Check it out at: http://www.plaxo.com/api/openid_recipe

Wednesday, January 27, 2010

Automating User Registrations with OpenID and Spring Security 3.0 - Part 3

Preparing heavily for DevNexus 2010, I did not have as much time as I hoped for in order to continue my series on using OpenID with the new SpringSecurity 3.0 (See Part 2 for details) Thus, today I would just like to cut and paste some of the code from my little 'home-POC'. In the coming weeks I still hope to incorporate it properly into jRecruiter.

Here is the JSP snippet for the OpenID login form:
<div id="openid-registration">
  <form name='oidf' action='/jrecruiter-web/j_spring_openid_security_check' method='POST'>
    <fieldset id="openIdLoginSection">
          <legend>Login with OpenID Identity</legend>
          <div class="required">
            <label for="openid_identifier">Identity</label>
            <s:textfield id="openid_identifier" name="openid_identifier" required="true" maxlength="80" tabindex="1" size="30"/>
          </div>
          <div class="submit">
            <input type="submit" value="Login"/>
          </div>
    </fieldset>
  </form>              
</div>


Here is the relevant piece of my Spring context file:

<security:http  auto-config="true" access-decision-manager-ref="accessDecisionManager" >
  <security:intercept-url pattern="/s/admin/**" access="ADMIN"                        requires-channel="https"/>
  <security:intercept-url pattern="/**"         access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="any" />

  <security:form-login login-page="/login.html" default-target-url="/admin/index.html"
                       authentication-failure-url="/login.html?status=error" />
  <security:logout logout-url="/logout.html" invalidate-session="true" logout-success-url="/show.jobs.html"/>
  <security:session-management>
     <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/>
  </security:session-management>
  <security:custom-filter ref="openIDFilter"                   position="OPENID_FILTER" />
</security:http>

<bean id="openIDFilter" class="org.jrecruiter.web.security.RegistrationAwareOpenIDAuthenticationFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="consumer" ref="attributeAwareOpenIDConsumer"/>
  <property name="authenticationSuccessHandler"        ref="openIDFilterSuccess"/>
  <property name="authenticationFailureHandler"        ref="openIDFilterFailure"/>
  <property name="registrationTargetUrlRequestHandler" ref="openIDFilterRedirectToRegistration"/>
</bean>

<bean id="openIDFilterRedirectToRegistration" class="org.jrecruiter.web.security.RegistrationTargetUrlRequestHandler">
  <property name="defaultTargetUrl" value="/registration/signup.html"/>
</bean>
<bean id="openIDFilterSuccess" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
  <property name="defaultTargetUrl" value="/admin/index.html"/>
</bean>
 
<bean id="openIDFilterFailure" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
  <property name="defaultFailureUrl" value="/login.html?status=error"/>
</bean>

<bean id="attributeAwareOpenIDProvider" class="org.jrecruiter.web.security.AttributeAwareOpenIDProvider" scope="prototype">
  <constructor-arg ref="userService"/>
</bean>

<bean id="attributeAwareOpenIDConsumer" class="org.jrecruiter.web.security.AttributeAwareOpenIDConsumer"/>


I did some customization: public class AttributeAwareOpenIDConsumer extends OpenID4JavaConsumer {
  public AttributeAwareOpenIDConsumer() throws ConsumerException {
         super(Arrays.asList(UsedOpenIdAttribute.FIRST_NAME.getOpenIdAttribute(),
                                     UsedOpenIdAttribute.LAST_NAME.getOpenIdAttribute(),
                                     UsedOpenIdAttribute.EMAIL.getOpenIdAttribute(),
                                     UsedOpenIdAttribute.AX_FIRST_NAME.getOpenIdAttribute(),
                                     UsedOpenIdAttribute.AX_LAST_NAME.getOpenIdAttribute(),
                                     UsedOpenIdAttribute.NAME_PERSON.getOpenIdAttribute()));
  }
}
I also created a custom class AttributeAwareOpenIDProvider which extends org.springframework.security.openid.OpenIDAuthenticationProvider. It overrides public Authentication authenticate(Authentication authentication) Thus, I can hook into the actual authentication process and inject my own logic.

For example,  if the OpenID authentication succeeds it does not necessarily mean that your account exists, yet. Therefore, if OpenID authentication succeeds (if (status == OpenIDAuthenticationStatus.SUCCESS)), I try loading the user from my application's database (userDetailsService). If then a UsernameNotFoundException is thrown I collect a series of OpenID attributes from the org.springframework.security.openid.OpenIDAuthenticationToken. Once finished, I am throwing a custom AuthenticationSucessButMissingRegistrationException. I use it to redirect to the registration page and pre-populate the registration form with some of the collected OpenID attributes.

I hope this gives you some ideas of how you can integrate OpenID into your SpringSecurity infrastructure. I am myself still in the early learning phase regarding OpenID and I still need to figure out how to best manage multiple authentication realms within my application. But that may be a reason for another blog post.

Friday, January 1, 2010

Automating User Registrations with OpenID and Spring Security 3.0 - Part 2

This is the continuation of part 1. See also part 3.

Spring Security provides support for OpenID out of the box. It is fairly easy to setup basic OpenID authentication. It even can automatically generate the respective login forms for you. But for my use case I wanted something more elaborate. Here is a basic flow of my "Spring Security OpenID integration solution" (early working draft):

Step 1: User starts the login process using OpenID.
Note that the 'OpenID' between providers varies quite a bit.




Step 2: After pressing the Login button, Spring Security processes the request and using openid4java under the hood, you are redirected to the login page of your OpenID provider in this case Google.

 

Step 3: In step 2 you authenticated successfully (with Google in this case), but you don't have a valid account with jRecruiter itself, yet: In this instance, grab all the useful information that is available through the OpenID account/profile and then forward (Redirect) to the registration page. There pre-fill the form with the grabbed information (E.g. email, first name, last name etc.)


 


Of course I need to add some more sophistication around my user registration process. Nevertheless, I hope the general flow is clear. While OpenID is a fairly widely adopted standard, there seems to be a bit of fluctuation in regards to what data sets providers will allow you to fetch, as well as how to fetch them (e.g. different name-spaces). Thus, it looks like in order to automated an OpenID-supported registration process, you need to be aware (code for) specific providers. I need to explore that area a bit more.

In my next posting I will finally provide some source code. If find some time, take a look and play around with openid4java. The OSS project provides various examples, and the 'simple-openid' example is really helpful for understanding the actual openID registration process. Stay tuned.

Sunday, December 27, 2009

Automating User Registrations with OpenID and Spring Security 3.0 - Part 1

Having a few days of vacation is nice. Besides spending some precious time with my family, it also gave me some time to work on jRecruiter. I upgraded Spring Security to the final 3.0.0 version, which was released just a few days ago.

The upgrade process was relatively painless, though it is not a simple Jar drop-in as the packages of many of the classes changed. But it was fairly straight-forward.

The biggest hassle, was upgrading Jasypt as the latest released version is not playing nice with Spring Security 3.0, yet. But the code is already committed to Jasypt's source code repository, and with minor modifications, I was able to compile a custom version.

But while I was looking through the changes of Spring Security 3, I started reading a little bit more about its support for OpenID.Which then let to the question, whether there is a good use case for OpenID in my home project.

Places where I saw the use of OpenID are:
Here is actually a pretty good blog post regarding OpenID:

http://www.codinghorror.com/blog/archives/001121.html


Security Concerns

Then of course, there are also a few security concerns regarding allowing for OpenID authentication:
 If that's not enough:
Thus, while I probably wouldn't use OpenID for a banking application, I feel it is a nice fit for my home project, it is used by local recruiters to post job postings. Up to this point every account holder had to provide her own username (email) and a password.

None of the information stored by jRecruiter is extremely sensitive and thus, OpenID might actually help improve the user experience of people posting jobs through the system.  Over the past few years I saw a common issue that account holder are unable to remember their password, or even their username (which made me to change over to more of a email-based username approach). Ultimately, there were quite a few duplicate registrations in the past.

An interesting question though is, is it advisable to restrict access to a limited amount of OpenID providers? (Such as myOpenID, Google or Yahoo)

Use Case

Well, this is were things are getting interesting, OpenID does not only define the notion of pure authentication but it can also gives you access to various pieces of your OpenID profile (e.g. first name, last name, email address etc.). This feature seems to vary, though, between providers (Have to see how that works out)

Thus, for jRecruiter I envision the following use case. When a user starts the login process:
  1. she or he has a choice of either loggin in the traditional way using a username/password combination or 
  2. by selecting the OpenID route. 
  3. If the user logs in via OpenID and the authentication succeeds, but the user account within jRecruiter does not exists, yet, then the potential user is redirected to the registration pages and the fields of the registration form shall be pre-populated (as much as possible) using inforamtion from the user's OpenID profile. 

In my next blog installment I would like to give you some insights of how I created a first draft implementation using Spring Security 3.0. Keep in mind that this is an ongoing (learning) process...Thus, if you see issues, let me know.

Continue with part 2.