Search code examples
angularjsspring-securitycorsionic-frameworkcsrf

Using CORS and CSRF together in Ionic app


I'm developing a android app using Ionic Framework based in a AngularJS web site I developed using Jhipster. As I already have server code running in my web application, I've choose Ionic to work as UI and call server when needed, but I'm having some issues in my development enviroment.

  1. As I run my application using Ionic serve, I need use CORS to make requests to server.
  2. My web application was developed using CSRF token with Spring Security

I'm using Apache CORS filter configured this way:

private void initCORSFilter(ServletContext servletContext, EnumSet<DispatcherType> disps) {
    FilterRegistration.Dynamic corsFilter = servletContext.addFilter("cors", new CorsFilter());
    Map<String, String> parameters = new HashMap<>();
    parameters.put("cors.allowed.origins", "http://localhost:3000");
    parameters.put("cors.allowed.headers", "x-auth-token, x-requested-with, Content-Type, Accept, cache-control, x-csrf-token, Origin, Access-Control-Request-Method, Access-Control-Request-Headers");
    parameters.put("cors.allowed.methods", "POST, PUT, GET, DELETE");
    parameters.put("cors.exposed.headers", "Access-Control-Allow-Origin, Access-Control-Allow-Credentials");
    parameters.put("cors.support.credentials", "true");
    corsFilter.setInitParameters(parameters);
    corsFilter.addMappingForUrlPatterns(disps, true, "/*");
}

then I used angular-csrf-cross-domain plugin to help with cross domain csrf requests:

.config(function ($urlRouterProvider,csrfCDProvider) {
    $urlRouterProvider.otherwise('/');
    //enable CSRF
    csrfCDProvider.setHeaderName('X-CSRF-TOKEN');
    csrfCDProvider.setCookieName('CSRF-TOKEN');
});

Then I try send a post request to my local server:

angular.module('consamiApp')
.factory('Register', function ($resource) {
    //globalURL is https://localhost:8080
    return $resource(globalURL+'api/register', {}, {
    });
});
.
.
.
createAccount: function (account, callback) {
    var cb = callback || angular.noop;

    return Register.save(account,
        function () {
            return cb(account);
        },
        function (err) {
            this.logout();
            return cb(err);
    }.bind(this)).$promise;
}

However I'm getting this message in firefox console:

Cross-origin locked request: The same origin policy (Same Origin Policy) prevents reading the remote resource in https://localhost:8080/api/register. (Reason: CORS heading 'Access-Control-Allow-Origin' is not present)

NEW INFORMATION

AngularJs make 2 CORS requests to the server when I submit the form I'm testing: OPTIONS and POST, the results of the requests are 200 OK and 403 Forbidden. These are the headers of the 2 requests and responses:

OPTIONS Request headers:

Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

OPTIONS Answer headers:

Access-Control-Allow-Origin: http://localhost:3000
Content-Length: 0
Date: Tue, 30 Jun 2015 22:07:58 GMT
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=485A653AEAC8B8756DD3057BBF7FB862; Path=/; Secure; HttpOnly
CSRF-TOKEN=e8b3396c-63b2-47bf-9ad6-c1454628eb3b; Path=/
X-Application-Context: application:dev:8080
access-control-allow-credentials: true
access-control-allow-headers: origin,access-control-request-headers,x-requested-with,x-csrf-token,content-type,access-control-request-method,cache-control,x-auth-token,accept
access-control-allow-methods: POST
access-control-max-age: 1800

POST Request Headers:

Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: application/json, text/plain, */*
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/json;charset=utf-8
Referer: http://localhost:3000/
Content-Length: 109
Origin: http://localhost:3000
Cookie: _ga=GA1.1.123103160.1428358695; connect.sid=s%3AwD4KP4WBfhGO0JpFND3LpCzW.augts9fos9NMaZw%2B7XrNuilgaM8ocwSxaEUeDlIaVJ4; JSESSIONID=93200F4F4AFCEB28F10B130841808621
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

POST Answer Headers:

Content-Type: application/json;charset=UTF-8
Date: Tue, 30 Jun 2015 22:07:58 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked

Is there something I didn't noticed? The Ionic's official blog says I should not worry about CORS issue when deploying the app, however at least for tests, I really need solve this problems. Could you give me any options?


Solution

  • When I edited the question and saw the OPTIONS response header with HttpOnly clause, I started believe that the problem was with self signed certificate I'm using in development enviroment.

    Set-Cookie: JSESSIONID=485A653AEAC8B8756DD3057BBF7FB862; Path=/; Secure; HttpOnly

    So I've decided disable https protocol in the web server and it worked correctly. Thanks for your help.