SpringSecurity: Authenticating & Authorizing AJAX Requests

This is my second post on Spring Security (first being this) and I will try to be more detailed here. Please keep sharing your feedback with me so that I could improve myself.

After all of the lengthy setups, primary value that we get from Spring Security (or any other security framework) is the ability to authenticate and authorize each request that application receives. First I will try to explain a bit the processes of authentication and authorization.

Authentication

In almost every webapp, there are some pages (or resources) available for everyone, while some other pages are available only for logged-in users. So if a user is not logged into the system and tries to request a secure page, usually you would want them to be redirected to login page. If they login successfully, you will redirect them back to the original page they requested.

Authorization

It is quite possible that you maintain different authorities for different users in your system. For example, some of your secure pages are requestable by every loggedin user, but you have kept some other only for admin users. So whenever a logged-in user requests a page, you will first verify if they have the authority to open this page. If yes, you will send them the page, otherwise you will redirect them to another page which will tell them that the requested page is forbidden for them.

Normal Non-AJAX Requests

Authenticating and authorizing normal (non-AJAX) requests is a pretty straight forward task and can be achieved with very little configuration. However it is out of scope of current post.

AJAX Requests

Authenticating and authorizing AJAX requests is also a simple task, however it requires bit deeper understanding of the framework. Before we jump into the implementation, let’s first define desired behavior when AJAX requests are authenticated and authorized.

Desired Behavior

When authentication fails for an AJAX request, you cannot redirect the user to the login page (at least from within the server). Therefore, if such thing happens, we would like to show user an alert message telling them that they need to login before they could send this AJAX request. For their convenience, we could add a “Redirect to login” button in the alert box which could save them a few clicks.

Similarly, authorization failure of an AJAX request should open a popup telling user that they do not have enough privileges to request current resource.

To achieve this behavior, we will need to write some code for both server-side and client-side:

Umar Ashfaq

Umar Ashfaq is a full-stack web developer. His core strengths are Java (Spring, Hibernate stack) and JavaScript (both client-side and server-side). Follow him on twitter @umarashfaq87

More Posts

Follow Me:
TwitterFacebookLinkedIn

No related posts.

11 Comments

  • 1
    Igor Kolomiets
    August 14, 2012 - 12:52 am | Permalink

    I faced a similar problem with GWT RPC calls when instead of expected GWT-RPC protocol payload server responded with “HTTP redirect” to login page that made GWT fail to parse such response and complain with nonsense errors (“index -1 is out of range”) instead.

    The way I solved the problem was

    1) Identify GWT-RPC request (so for non-RPC calls HTTP redirect still be used)

    2) Make server respond with a standard HTTP 403 status which can be properly caught and handled by GWT.

    The hardest was to identify GWT-RPC calls. I did that by using DelegatingAuthenticationEntryPoint class and “hasHeader()” Spring expression clause to check request’s “Content-Type” against “text/x-gwt-rpc” value. To make SpringSecurity respond with HTTP 403 a standard Http403ForbiddenEntryPoint class entry-point should be used.

    Here’s how it looks in spring config xml:

    ….

    • 2
      Igor Kolomiets
      August 14, 2012 - 12:56 am | Permalink

      Another take to post example xml:

      ......

  • 3
    Igor Kolomiets
    August 14, 2012 - 1:16 am | Permalink

    Ok, I give up. If someone could explain how to embed xml into wordpress posts I’ll gladly do so.

    • 4
      August 14, 2012 - 4:27 am | Permalink

      Hi Igor, thanks for sharing your experience. You can wrap your code in [sourcecode language=”xml”][/sourcecode] tag.

  • 5
    Igor Kolomiets
    August 14, 2012 - 7:23 pm | Permalink

    Umar, thanks for your tip! Here goes another try

        <http use-expressions="true" entry-point-ref="daep">
             <!-- omitted -->
        </http>
    
        <beans:bean id="daep" class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
            <beans:constructor-arg>
                <beans:map>
                    <!-- for GWT RPC requests return HTTP 403 since redirect to login page doesn't make sense  -->
                    <beans:entry key="hasHeader('Content-Type','text/x-gwt-rpc')" value-ref="http403ForbiddenEntryPoint"/>
                </beans:map>
            </beans:constructor-arg>
            <beans:property name="defaultEntryPoint" ref="loginUrlAuthenticationEntryPoint"/>
        </beans:bean>
    
        <beans:bean id="http403ForbiddenEntryPoint"
                    class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
    
        <beans:bean id="loginUrlAuthenticationEntryPoint"
                    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
            <beans:property name="loginFormUrl" value="/login.html"/>
        </beans:bean>
    
  • 6
    August 16, 2012 - 7:39 am | Permalink

    Igor, although overriding AuthenticationEntryPoint is the easiest thing to do, it comes with a side-effect:

    When you login after being denied a secure resource, you are redirected back to the secure resource. For example,

    1. You requested an AJAX URL without authentication.
    2. Server responded with a message requesting you to login first.
    3. You go to login page, enter your credentials and request login.
    4. Instead of redirecting to a nice HTML page, you will see an AJAX response printed on the screen which was actually the response from AJAX URL in step 1.

  • 7
    Igor Kolomiets
    August 16, 2012 - 7:13 pm | Permalink

    Umar,

    What you have described is not my case. When authenticated session has expired and you still try to use application, then the very first interaction with server (and in my case all interations with server is done through GWT RPC) will result in HTTP 403. This error code is treated uniformely by application’s GWT AsyncCallback implementation which will bring up a nice “Session has expired. Please login.” pop-up dialog and once aknowledged it will redirect user to application’s login page (it will be client-side issued redirect, not server-side issued redirect).

  • 8
    August 16, 2012 - 7:25 pm | Permalink

    Igor, I see your point and it looks interesting. Thanks for sharing.

  • 9
    jackyrong
    January 10, 2013 - 7:00 pm | Permalink

    HI,I AM A NEY GUY FOR spring security 3,can you wrap the whole project code for us to download?thank you verymuch!

  • Leave a Reply

    Your email address will not be published. Required fields are marked *

    *

    Wrap your code in [sourcecode language="java"][/sourcecode] tag (you can replace "java" with language you are using).