Configure Angularjs and CORS correctly using Apache, running Flask api and Angularjs interface in a separate domain

This was discussed through Stackoverflow, but I could not find a solution for it to work. I even tried a lot of what was discussed in this article ( Problems with CORS. Flask ↔ AngularJS ), as it was closely related to my setup, but I'm still pretty lost.

I have a python flask api server running locally. I named this domain bac-api. This is what this vhost looks like.

<VirtualHost *:80> ServerName bac-api WSGIDaemonProcess bacapi python-path=/home/lumberjacked/workspace/bas/development/lib/python2.7/site-packages WSGIScriptAlias / /home/lumberjacked/workspace/bas/development/bac-api/bacapi.wsgi Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, application/json" Header set Access-Control-Allow-Methods "POST, GET, OPTIONS" <Directory /home/lumberjacked/workspace/bas/development/bac-api> WSGIProcessGroup bacapi WSGIApplicationGroup %{GLOBAL} Order deny,allow Allow from all </Directory> #SSLEngine on #SSLCertificateFile /etc/apache2/ssl/bac_api_ssl.crt #SSLCertificateKeyFile /etc/apache2/ssl/bac_api_ssl.key </VirtualHost> 

I have an angularjs site working as my front-end in a separate domain called manage.bac. I am writing an authentication service that connects to bac-api and sends the api keys and / or user credentials, asking the server if the user is authenticated or not.

I can hang on the server and this works and returns a response.

 curl -X POST -H "Content-Type: application/json" -d '{ "api": "7f3d6d7338b921ae4ca95cecc452ef1790005ec10c2343fabe5a59ea" }' http://bac-api/authenticated/ response -- {"authenticated": false} 

Also, by going to manage.bac and placing my email accounts email@email.com and password, I get the same answer, but I also configured it to return 401 if you did not authenticate with the saved session.

 POST http://bac-api/authenticated/ 401 (UNAUTHORIZED) bac-api/authenticated/:1 

Problems start when I switch to ssl certificates and port 443. So, if on both domains I switch vhost to port 443 and uncomment the ssl certificates. After restarting apache, there are no errors, and the domains work until a 500 error or something like that is detected. I can loop into the bac-api server using https and get a response.

 curl -k -X POST -H "Content-Type: application/json" -d '{ "api": "7f3d6d7338b921ae4ca95cecc452ef1790005ec10c2343fabe5a59ea" }' https://bac-api/authenticated/ response -- {"authenticated": false} 

But as soon as I go to https: //manage.bac and redirect to the login page, all problems begin.

As soon as I click inside the login fields, this console throws this error and I don’t know if it is connected or not.

 Blocked a frame with origin "https://manage.bac" from accessing a frame with origin "chrome-extension://hdokiejnpimakedhajhdlcegeplioahd". The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "chrome-extension". Protocols must match. 

Here is my angularjs authentication code with console.log methods outputting some things.

 $http.post('https://bac-api/login/', user) .success( function( user ) { console.log('success'); console.log(user); }) .error( function( error ) { console.log('error'); console.log(error); }); Object {email: " email@email.com ", password: "password"} authentication-service.js:36 error authentication-service.js:50 authentication-service.js:51 

When this error returns, there is nothing in the response at all. I see inside the tab of the network of chrome tools that this request receives a preliminary flight, because it sends OPTIONS to the server.

 OPTIONS /login/ HTTP/1.1 Host: bac-api User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Origin: https://manage.bac Access-Control-Request-Method: POST Access-Control-Request-Headers: content-type,x-requested-with Connection: keep-alive Pragma: no-cache Cache-Control: no-cache 

I also see that on the "Network" tab it appears as OPTIONS and it has been canceled. What I do not know what it means.

enter image description here

I configured inside angularjs with these parameters, but it seems that this does not change anything.

 config(['$httpProvider', function($httpProvider) { $httpProvider.defaults.useXDomain = true; delete $httpProvider.defaults.headers.common['X-Requested-With']; } ]); 

Also, in my application, the flask tried to implement the decorator mentioned here http://flask.pocoo.org/snippets/56/ , as well as mention stackoverflow in other posts. It does nothing either. I also assumed that since I put access headers for the api server in my vhost, I really did not need to do the same in the application. Although I could be completely wrong, because I do not know what I am doing.

Any help is really appreciated. I'm sorry if this seems like a duplicate problem, but so far I can't get it to work, and I tried every entry in stackoverflow to solve this problem.

--- Edit with updated information

This morning, as an experiment, I switched both vhosts back to port 80 and commented out all the allowed access headers. Here are my results. Reboot and try logging in.

 Failed to load resource: Origin http://manage.bac is not allowed by Access-Control-Allow-Origin. http://bac-api/authenticated/ XMLHttpRequest cannot load http://bac-api/authenticated/. Origin http://manage.bac is not allowed by Access-Control-Allow-Origin. manage.bac/:1 

So, after this error, I logged into my bac-api vhost and did not comment on Header, installed Access-Control-Allow-Origin "*" and restarted again and tried to log in. Here are the new errors that are displayed.

 OPTIONS http://bac-api/authenticated/ Request header field Content-Type is not allowed by Access-Control-Allow-Headers. angular.js:9312 (anonymous function) angular.js:9312 sendReq angular.js:9146 $http angular.js:8937 Authenticator.isLoggedIn authentication-service.js:13 RouteConfig.login.resolve.Auth state-service-provider.js:16 invoke angular.js:2902 (anonymous function) angular-ui-router.js:801 forEach angular.js:137 resolve angular-ui-router.js:797 resolveState angular-ui-router.js:813 transitionTo angular-ui-router.js:704 (anonymous function) angular-ui-router.js:615 invoke angular.js:2902 handleIfMatch angular-ui-router.js:433 rule angular-ui-router.js:452 update angular-ui-router.js:487 Scope.$broadcast angular.js:8307 afterLocationChange angular.js:5649 (anonymous function) angular.js:5637 Scope.$eval angular.js:8057 Scope.$digest angular.js:7922 Scope.$apply angular.js:8143 (anonymous function) angular.js:981 invoke angular.js:2895 resumeBootstrapInternal angular.js:979 bootstrap angular.js:993 angularInit angular.js:954 (anonymous function) angular.js:14843 c jquery-1.10.1.min.js:4 p.fireWith jquery-1.10.1.min.js:4 x.extend.ready jquery-1.10.1.min.js:4 q jquery-1.10.1.min.js:4 XMLHttpRequest cannot load http://bac-api/authenticated/. Request header field Content- Type is not allowed by Access-Control-Allow-Headers. manage.bac/:1 

So, to fix this error and allow Content-Type through I will go back to my bac-api vhost and I will add Header, set the Access-Control-Allow-Headers "Content-Type". After restarting the view on manage.bac when the page loads, those results are shown here.

 POST http://bac-api/authenticated/ 401 (UNAUTHORIZED) bac-api/authenticated/:1 

Which is good, because it means that I received a {"authenticated": false} response and sent 401 back unauthorized. If I continue and try to log in, I will get these results.

 Object {email: " email@email.com ", password: "password"} authentication-service.js:36 success authentication-service.js:40 Object {login: false} authentication-service.js:41 

This also works. Here is the angle code code that produces this output.

 $http.post('http://bac-api/login/', user) .success( function( user ) { console.log('success'); console.log(user); }) .error( function( error ) { console.log('error'); console.log(error); }); 

Now my thoughts were awesome if he worked on port 80, now I can switch it to port 443 and continue to roll. So I switch vhosts to port 443 and look at the manage.bac file again. On page loading, before trying to log in, I get these results.

enter image description here

And again, when I try to log in and submit the form, I also get these results.

 Object {email: " email@email.com ", password: "password"} authentication-service.js:36 error authentication-service.js:50 authentication-service.js:51 

Also on the Network tab enter image description here

It was just to try to give each body more information, helping me find the cause of this problem.

----- Change again with more information

Today I started trying to check this with curl and see which headers were returned with an OPTIONS request

Here is the curl request that I copied directly from the Network tab, provided that it was the same OPTIONS request that angularjs sends. First I put the OPTIONS request from the network tab, and then my curl request.

 OPTIONS https://bac-api/login/ HTTP/1.1 Access-Control-Request-Method: POST Origin: https://manage.bac Referer: https://manage.bac/ User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.76 Safari/537.36 Access-Control-Request-Headers: accept, origin, x-requested-with, content-type curl -i -k -X OPTIONS -H "Access-Control-Request-Method: POST" -H "Origin: https://manage.bac" -H "Referer: https://manage.bac/" -H "Access-Control-Request-Headers: accept, origin, content-type" https://bac-api/login/ 

Here is the answer from curl

 HTTP/1.1 200 OK Date: Tue, 01 Oct 2013 02:51:17 GMT Server: Apache/2.2.22 (Ubuntu) Allow: POST, OPTIONS Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, OPTIONS Access-Control-Max-Age: 21600 Content-Length: 0 Access-Control-Allow-Origin: * Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept Access-Control-Allow-Methods: POST, GET, OPTIONS Vary: Accept-Encoding Content-Type: text/html; charset=utf-8 

This indicates that the server is configured correctly and is responding to OPTIONS requests with the correct headers. But as I published in the above figures, when I launch it in the browser, still on the "Network" tab, it is canceled, and nothing is returned in response to the error.

+6
source share
1 answer

I was able to solve this problem, and it was the stupidest thing. I will dig out other stackoverflow posts that helped lead me to a solution. But mostly during testing, I generated self-signed certificates for local use. Obviously, both firefox and chrome automatically cancel your requests if they do not trust certificates when performing cross-domain messages. I needed to go into chrome and firefox to add certificates and mark them as trusted before they stopped canceling the request. Now everything works fine.

Also in this study, I found out that you do not need to add a helper request to Flask to add headers in your responses and in your Apache configuration. If you put them in both, they will add headings both times. In my configuration, I decided to add it to my Apache configuration, because it made my python code cleaner.

+4
source

Source: https://habr.com/ru/post/954914/


All Articles