Search code examples
angularjsamazon-s3passport.jspassport-facebookknox-amazon-s3-client

Not sending authorization header from Angular to AWS


I'm trying to build a web app that should fetch a pre-signed Amazon S3 URL, and then upload a file to that URL using Knox.

However S3 gives me this error when I try to access my bucket

<Error><Code>InvalidArgument</Code><Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message><ArgumentName>Authorization</ArgumentName><ArgumentValue>Bearer *****bearer token*****</ArgumentValue><RequestId>1AFD8C7FD2D7E667</RequestId><HostId>ID</HostId></Error>

I can see that my request to Amazon not only contains my Amazon keys, but also my Authorization Header

https://bucket.s3-eu-west-1.amazonaws.com/image.jpg?Expires=1418226249&AWSAccessKeyId=<key>&Signature=DHYCio7Oao%2BnzPWiiWkGlHb0NAU%3D

and the header Authorization:Bearer

the code looks like

  $http.post(image, data, {headers: { 'Authorization': null }, withCredentials: false}   ).success(function (url) {
        item.images[0] = url;
        $http.post('/api/item', item);
      });

How do I get rid of the Authorization token for requests not pointing to my domain?

Regards


Solution

  • You should use Interceptors and its defined as service factories that are registered with the $httpProvider by adding them to the $httpProvider.interceptors array. The factory is called and injected with dependencies (if specified) and returns the interceptor.

    I assume that my Authorization token stored into cookie and I want to pass this token as a Authorization header. So to achieve it this what i did and it work for me.

    //Token Interceptor to intercept HTTP_AUTHORIZATION token into headers.
    App.factory('TokenInterceptor', [ '$q', '$window', '$location', function ($q, $window, $location) {
    return {
        request: function (config) {
            config.headers = config.headers || {};
            if ($window.sessionStorage.token) {
                config.headers.Authorization = $window.sessionStorage.token;
            }
            return config;
        },
    
        requestError: function(rejection) {
            return $q.reject(rejection);
        },
    
        /* Set Authentication.isAuthenticated to true if 200 received */
        response: function (response) {
            if (response !== null && response.status === 200 && $window.sessionStorage.token && !$window.sessionStorage.isAuthenticated) {
                $window.sessionStorage.isAuthenticated = true;
            }
            return response || $q.when(response);
        },
    
        /* Revoke client authentication if 401 is received */
        responseError: function(rejection) {
            if (rejection !== null && rejection.status === 401 && ($window.sessionStorage.token || $window.sessionStorage.isAuthenticated)) {
                delete $window.sessionStorage.token;
                $window.sessionStorage.isAuthenticated = false;
                $location.path('/');
            }
    
            return $q.reject(rejection);
        }
    };
    }]);
    

    Once you write the above service than you must push this interceptor into $httpProvider.interceptors array like this

    $httpProvider.interceptors.push('TokenInterceptor');
    

    Now every time you make any http request this Authorization header will automatically get added into headers.

    Thanks