14

Following is my sample Spring Security configuration.

I want all /api to return HTTP 401 code instead of redirecting 302 to login page.

Also I want to keep the redirect feature for old web pages.

<security:http auto-config='true' use-expressions="true" >
    <security:intercept-url pattern="/api*" access="hasRole('USER')" />
    <security:intercept-url pattern="/oldweb*" access="hasRole('USER')" />

    <security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/home"/>    
</security:http>

3 Answers 3

19

I came to more simpler solution. In Spring Boot and Java config you just have to register additional entry point in addition to default one. And because all your rest-services resides in "/api" name space, you could use AntPathRequestMatcher("/api/**") to match necessary requests.

So, final solution is:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.exceptionHandling()
                    //Actually Spring already configures default AuthenticationEntryPoint - LoginUrlAuthenticationEntryPoint
                    //This one is REST-specific addition to default one, that is based on PathRequest
                    .defaultAuthenticationEntryPointFor(getRestAuthenticationEntryPoint(), new AntPathRequestMatcher("/api/**"));
    }

    private AuthenticationEntryPoint getRestAuthenticationEntryPoint() {
        return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Would it still support Bearer token authentication or does it requires user to authenticate before on a web page?
@OndřejStašek This only refers to how the authentication fail is treated, it doesn't change the auth methods.
I'm not sure if this works so directly. The behavior of ExceptionHandlingConfigurer is not exactly what could be expected. I'd to create the DelegatingAuthenticationEntryPoint by myself, to ensure the apart from adding the HttpStatusEntryPoint for the specified pattern, it was setting the defaultEntryPoint as still the LoginUrlAuthenticationEntryPoint (or my custom one).
Great answer. I needed something for my spring application to connect a mobile application to. Returning these status codes resolve alot of my issues.
5

You need to have a custom authentication entry point.

public class CustomEntryPoint extends LoginUrlAuthenticationEntryPoint {

    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    private static final String X_REQUESTED_WITH = "X-Requested-With";

    public CustomEntryPoint(String loginFormUrl) {
        super(loginFormUrl);
    }

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {
        if (XML_HTTP_REQUEST.equals(request.getHeader(X_REQUESTED_WITH))) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        } else {
            super.commence(request, response, exception);
        }
    }    
}

Finally change your config to this:

<security:http auto-config='true' use-expressions="true" entry-point-ref="customEntryPoint">
    <security:intercept-url pattern="/api*" access="hasRole('USER')" />
    <security:intercept-url pattern="/oldweb*" access="hasRole('USER')" />

    <security:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/home"/>

    <beans:bean id="customEntryPoint" class="CustomEntryPoint">
        <beans:constructor-arg value="/login"/>
    </beans:bean>    
</security:http>

1 Comment

Creating a DelegatingAuthenticationEntryPoint, where you can have patterns and a default handler is more clear.
0

When text/html is not acceptable, return 401.

@EnableWebSecurity
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        // ...
        final RequestMatcher matcher = new NegatedRequestMatcher(
            new MediaTypeRequestMatcher(MediaType.TEXT_HTML));

        http.exceptionHandling()
            .defaultAuthenticationEntryPointFor(
                new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), matcher);

    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.