BACKGROUND:
GAE has a Authenticating Users on App Engine Using Firebase tutorial where you deploy a little note-taking app called firenotes (code at github). It has a frontend which 'talks' to firebase for authentication and lets users see their notes. It has a backend, which uses flask to verify authentication state and return user profile information and notes.
I am trying to make the same app with the same architecture but using webapp2.
THE PROBLEM
The firebase authentication works, I made few changes. It was easy.
However, the backend does NOT return the notes to the frontend. It fails because CORS policy blocks the request to the backend from being read. I am stuck having tried many alternatives and tampered a lot.
Here is how I am trying to handle CORS. A very straight forward webapp2 handler with a get method, a put method and a preflight options method and respective headers:
class Notes(webapp2.RequestHandler):
def options(self):
self.response.headers['Access-Control-Allow-Origin'] = 'http://localhost:8080'
self.response.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization, Access-Control-Allow-Origin'
self.response.headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE'
def get(self):
self.response.headers.add_header('Access-Control-Allow-Origin',
'http://localhost:8080')
self.response.headers['Content-Type'] = 'application/json'
auth_request = google.auth.transport.requests.Request()
# Verify Firebase auth.
id_token = self.request.headers['Authorization'].split(' ').pop()
claims = google.oauth2.id_token.verify_firebase_token(id_token, auth_request)
#more code...
def post(self):
self.response.headers.add_header('Access-Control-Allow-Origin', 'http://localhost:8080')
self.response.headers['Content-Type'] = 'application/json'
# Verify Firebase auth.
id_token = self.request.headers['Authorization'].split(' ').pop()
auth_request = google.auth.transport.requests.Request()
claims = google.oauth2.id_token.verify_firebase_token(id_token, auth_request)
if not claims:
return 'Unauthorized', 401
#more code
But it doesn't work!
I can write new notes and I verify they have been included in the datastore as expected. But they are never exhibited by the frontend. Instead, here is what Firefox dev tools shows me:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8081/notes. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
But how can Access-Control-Allow_Origin be missing if I included it in my handler??
And all three requests - GET, PUT and OPTIONS - return code 200 OK.
What am I missing??
NOTE 1
This warning appears 2 times during the firebase sign in and then once for each time user clicks to include a new note. So it seems to be the case that it appears each time an jquery ajax call is made by the frontend to the backend (localhost:8081/notes).
NOTE 2
I haven't modified the javascript in the frontend. I figured that webapp2 should be able to do what ever flask/flask_cors are doing, so the js should stay the same.
I think adding the following:
self.response.headers.add_header("Access-Control-Allow-Origin", "*")
instead of
self.response.headers['Access-Control-Allow-Origin'] = 'http://localhost:8080'
in your handler would solve the issue.