Mark
Mark

Reputation: 858

AngularJS CORS with Authorization header

Sorry for yet another question about Angular and CORS but I just can't pin down where the issue lies. My basic setup is a pure angular standalone website, so no Express or any server-side component, that talks to a Java based API on another server. The API is built using JAX-RS and lives in a JBoss 7.1.3 application server. I have access to the code for both the angular and the java.

On the API side, CORS is enabled using the popular thetransactioncompany CORS filter shown below.

<filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
    <init-param>
        <param-name>cors.supportedMethods</param-name>
        <param-value>GET, POST, HEAD, PUT, DELETE, OPTIONS</param-value>
    </init-param>
    <init-param>
        <param-name>cors.supportedHeaders</param-name>
        <param-value>Origin, Accept, Content-Type, X-Requested-With, Cookie,content-type</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CORS</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

The way the API works is by providing a username and password to an endpoint that returns a token, this token is then included in the Authorization header in every subsequent request. The first part of the process works fine, I can provide valid credentials and receive a token, but then any subsequent request never works. So in my Angular service I have the following login method that fetches me a token then attempts to get the current logged in user.

login: function(username, password){

        var deferred = $q.defer();

        $http({
            method: 'POST',
            url: 'http://localhost:8080/website-api/rest/account/token',
            headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json'},
            transformRequest: function(obj) {
                var str = [];
                for(var p in obj){
                    str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p])); 
                }
                return str.join('&');
            },
            data: {username: username, password: password }
        })
        .success(function(token) {

            $log.info(token.jwt);

            var requestConfig = {
                headers: {
                    'Authorization': token.jwt,
                    'Accept': 'application/json',
                    'X-Testing': 'Testing'
                }
            };

            $http.get('http://localhost:8080/website-api/rest/users/current', requestConfig)
                .success(function(user) {

                    $log.info('Retrieved User');
                    user.sessionToken = token.jwt;
                    deferred.resolve(user);

                })
                .error(function(data, status, headers, config) {

                    $log.info(data);
                    $log.info(status);
                    $log.info(headers);
                    $log.info(config);
                });

        })
        .error(function(data, status, headers, config) {

            $log.info(data);
            $log.info(status);
            $log.info(headers);
            $log.info(config);
        });

        return deferred.promise;
    }

The first request works perfectly, the second fails with the error:

XMLHttpRequest cannot load http://localhost:8080/website-api/rest/users/current. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access.

I can't figure out if the setup of the CORS filter on the API is the cause of my issue or theres something I'm not doing correctly when sending the request from Angular. I suspect it is Angular because I can use the third party services Postman and Hurl.it to test my API endpoints and they return the user object as intended.

Any help will be much appreciated!

Upvotes: 2

Views: 1853

Answers (1)

Mark
Mark

Reputation: 858

Based on a hunch from reading this post, I have noticed that not only did I have Content-Type defined twice in my list of accepted headers, but I didn't have Authorization set as an allowed header. The CORS filter rejects any incoming requests, that contain headers that aren't allowed, causing my 403 error.

Upvotes: 1

Related Questions