2

We are building an Angular Material application, consuming a RESTful Spring MVC API, with Spring Security & OAUTH2.

For testing purpose, we gave ROLE_ANONYMOUS access to our /users endpoint:

<intercept-url pattern="/users" method="POST" access="ROLE_ANONYMOUS"/>

But when we try to send a JSON by POST, we still get a 401 response from the server.

  • This is not happening with non-angular clients like Postman.
  • If we disable the Spring Security filter, everything works fine.
  • GET requests to the same endpoint also work fine.

This is our app.config:

  angular.module('App')
    .constant('RESOURCES', (function () {
                var resource = 'http://localhost:8080';
                return {
                  USERS: resource + '/users'
                }
              })());

And the factory doing the POST method:

  app.factory('LoginUser', ['RESOURCES', '$resource', function (RESOURCES, $resource) {
    return $resource(RESOURCES.USERS, null, {
                       add: {method: 'POST'}
                     });
  }]);

And the signup method in the controller:

  function signup(user) {
    LoginUser.add({}, JSON.stringify(user));
  }

We have the SimpleCORSFilter setup in the server following the Spring guide.

You can see the comparison between the postman POST and the AngularJS POST here:

screenshot

The header marked in red is a custom one we have to add in Postman in order to avoid a 415 unsupported media type.

We tried to put custom headers in the POST request in AngularJS, but it doesn't seem to be working:

.config(function ($httpProvider) {
    $httpProvider.defaults.headers.put['Content-Type'] = $httpProvider.defaults.headers.post['Content-Type'] =
        'application/json; charset=UTF-8';
});
Leo Lozes
  • 1,358
  • 1
  • 15
  • 33
  • If I correctly understand the only use case that do not work is when you need authentication in a request coming from angular. Because it works when you do not need authentication (GET requests not intercepted), or when you do not use angular. I would say that your angular front end do not correctly manage authentication. But without knowing more, I cannot guess more ! – Serge Ballesta Apr 28 '15 at 17:57
  • Hi Serge! Globally, the WS has authentication, but the endpoint we are accessing has a ROLE_ANONYMOUS access, therefore we think no authentication should be required. It works when we do a POST request from Postman or Java clients, the only one that is not working is AngularJS. – Leo Lozes Apr 28 '15 at 18:01
  • As I said, I cannot guess. You could try to spy the content of requests sent from AngularJS and Postman with a tool like [wireshark](http://www.wireshark.org) – Serge Ballesta Apr 28 '15 at 20:21
  • We added the requests of AngularJS and Postman, and didn't see any real problems (besides the content-type not being specified in Angular, that we tried to add without success). – Leo Lozes Apr 29 '15 at 11:47

1 Answers1

3

Ok, after reviewing the screenshot, we noticed the method was OPTIONS instead of POST.

The problem was not in the headers (we were checking those so much that we weren't seeing the obvious), but in the pre-flight request OPTIONS due to CORS. Here's a nice article about it. Our Spring Security was configured for the POST method, but not for the OPTIONS. We changed it and now it works like a charm:

  <intercept-url pattern="/users" method="POST" access="ROLE_ANONYMOUS"/>
  <intercept-url pattern="/users" method="OPTIONS" access="ROLE_ANONYMOUS"/>
Leo Lozes
  • 1,358
  • 1
  • 15
  • 33