12

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?

brevleq
  • 2,081
  • 10
  • 53
  • 97

3 Answers3

5

Have you installed and configured cordova plugin whitelist that is mandatory for CORS query since Cordova 5.0.0

install it :

cordova plugin add cordova-plugin-whitelist

configure config.xml

You can keep your current setup with * or change for more restrictive rules

add a html policy on index.html, you shall add a Policy also. To authorise everything, here it is :

 <meta http-equiv="Content-Security-Policy" content="default-src *;
 style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'
 'unsafe-eval'"

To verify that you have properly the plugin installed, check it into your cordova plugins with the following command:

cordova plugins 

You shall see the cordova-plugin-whitelist in it.

Secondly, you may need to add withCredentials to your $http (and therefore $resource) queries :

  .config(function($httpProvider) {
        $httpProvider.defaults.withCredentials = true;
    });
aorfevre
  • 5,034
  • 3
  • 21
  • 51
  • if you did not use ionic to generate the project then @aofevre is most likely correct. If you use ionic they now include the plugin into the project. – Jess Patton Jun 30 '15 at 15:26
  • where have you seen that ionic wrap the cordova plugin whitelist ? So far, I see that it shal lbe installed manually (http://docs.ionic.io/v1.0/docs/cordova-whitelist). – aorfevre Jun 30 '15 at 15:29
  • I have add the cordova command into response to verify that the whitelist plugin is well installed; but I still can't find any indication if ionic includes already this plugin;) – aorfevre Jun 30 '15 at 15:31
  • 1
    if you run ionic start test blank (starting a new blank ionic project) look in the plugins folder! BAM! the whitelist plugin is there – Jess Patton Jun 30 '15 at 15:34
  • As @JessPatton told, the whitelist plugin is installed by default in Ionic. I added the meta tag, but the result is the same. I've added the headers of the requests in the question, perhaps there is something I'm not seeing. – brevleq Jun 30 '15 at 22:41
  • So you should have in config.xml + META policy setted up into your index.html; right ? – aorfevre Jun 30 '15 at 22:44
3

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.

brevleq
  • 2,081
  • 10
  • 53
  • 97
1

The CORS spec is all-or-nothing. It only supports *, null or the exact domain: http://www.w3.org/TR/cors/#access-control-allow-origin-response-header

I don't think you can specify port numbers as its value.

ThiagoPXP
  • 5,362
  • 3
  • 31
  • 44
  • I've escaped : character for port, according with [angularjs $resource doc](https://docs.angularjs.org/api/ngResource/service/$resource) – brevleq Jun 30 '15 at 22:42