licorna
licorna

Reputation: 5880

How to implement own OpenIDConsumer on Spring Security?

I want to implement a new OpenIDConsumer for Spring Security OpenID. I implemented OpenIDConsumer in a class and then added the corresponding configuration to applicationContext-security.xml, but my code doesn't seems to be executed at all.

This is the relevant part from applicationContext-security.xml:

<http auto-config="false">
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <openid-login login-page="/auth/login"
            authentication-failure-url="/auth/login?login_error=true">
        <attribute-exchange>
            <openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/>
        </attribute-exchange>
    </openid-login>
</http>
<b:bean id="openIdConsumer" class="sample.OpenIDTestConsumer">
    <b:property name="email" value="email"/>
</b:bean>

Now, the class sample.OpenIDTestConsumer is initialized but it is not used by Spring Security, and the original class is used instead I think OpenID4JavaConsumer.

The sample.OpenIDTestConsumer class implements the OpenIDConsumer interface and it is initialized and the setEmail method is set, but it doesn't execute the beginConsumption or endConsumption methods, that's why I think it is just created because of applicationContext-security.xml bean definition but is not used.

The question is: How can I glue or set a custom class to work as the OpenIDConsumer and not use the Spring implementation?

Upvotes: 1

Views: 1025

Answers (2)

Rob Winch
Rob Winch

Reputation: 21720

Another solution is to use a tip from the FAQ and use a BeanPostProcessor. The result might look something like this:

public class CustomOpenidConsumerBeanPostProcessor implements BeanPostProcessor {
    private OpenIDConsumer openidConsumer;

    public Object postProcessAfterInitialization(Object bean, String name) {
        if (bean instanceof OpenIDCOnsumer) {
           return openidConsumer;
        }
        return bean;
    }

    public Object postProcessBeforeInitialization(Object bean, String name) {
        return bean;
    }

    public void setOpenidConsumer(OpenIDConsumer openidConsumer) {
        this.openidConsumer = openidConsumer;
    }
}

Then your configuration would include the following:

<b:bean class="CustomOpenidConsumerBeanPostProcessor">
    <b:property name="openidConsumer" ref="openIdConsumer"/>
  </b:bean>
<b:bean id="openIdConsumer" class="sample.OpenIDTestConsumer">
   <!-- config attribute exchange here -->
   <b:property name="email" value="email"/>
</b:bean>

Upvotes: 2

nosebrain
nosebrain

Reputation: 1082

By default Spring Security registers an OpenIDAuthenticationFilter with an OpenID4JavaConsumer when using the security namespace configuration. You can not define a custom consumer with the namespace. A solution would be to use a custom filter and configure the OpenIDAuthenticationFilter by hand in your applicationContext-security.xml:

<http ...>
   ...
   <custom-filter position="OPENID_FILTER" ref="openIdFilter" />
</http>
<b:bean id="openIdFilter" class="org.springframework.security.openid.OpenIDAuthenticationFilter">
   <b:property name="consumer" ref="openidConsumer" />
   <!-- customize your filter (authentication failure url, login-page, … -->
</b:bean>
<b:bean id="openIdConsumer" class="sample.OpenIDTestConsumer">
   <!-- config attribute exchange here -->
   <b:property name="email" value="email"/>
</b:bean>

Upvotes: 2

Related Questions