5

I'm having issues trying to get a token from my flask-sentinel app with my front-end.

To make the AJAX requests from my front-end to my Python Eve API server I use the superagent module.

While using a Basic Authentication I don't have any issue getting data from my endpoints. See code below:

superagent
    .get( 'http://192.168.1.x:5000/endpoint' )
    .auth( this.params.username, this.params.password )
    .on( 'error', this.onError )
    .then( this.onSuccess );

If I try to request a token to the /oauth/token endpoint with this code:

superagent
    .post( 'http://192.168.1.x:5000/oauth/token' )
    .set( 'Content-Type', 'application/x-www-form-urlencoded' )
    .send( 'grant_type=password&client_id='+this.params.client_id+'&username='+this.params.username+'&password='+this.params.password )
    .on( 'error', this.onError )
    .then( this.onTokenReceived );

I get a CORS error:

Access to XMLHttpRequest at 'http://192.168.1.x:5000/oauth/token' from origin 'http://192.168.1.y:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Here are the settings of my application (omitting the database and domain settings):

SENTINEL_X_DOMAINS           = ['http://192.168.1.y:3000']
SENTINEL_X_HEADERS           = ['Authorization','Content-type','If-Match','Access-Control-Allow-Origin']
SENTINEL_X_EXPOSE_HEADERS    = SENTINEL_X_HEADERS
SENTINEL_RESOURCE_METHODS    = ['GET','HEAD','PUT','PATCH','POST','DELETE','OPTIONS']
SENTINEL_PUBLIC_METHODS      = SENTINEL_RESOURCE_METHODS
SENTINEL_X_ALLOW_CREDENTIALS = True

X_DOMAINS           = ['http://192.168.1.y:3000']
X_ALLOW_CREDENTIALS = True
X_HEADERS           = ['Authorization','Content-type','If-Match','Access-Control-Allow-Origin']
RESOURCE_METHODS    = ['GET','HEAD','PUT','PATCH','POST','DELETE','OPTIONS']

Can you please guide me in getting what I'm doing wrong?

Thank you in advance!

Andrea Silvestri
  • 1,082
  • 4
  • 14
  • 41

3 Answers3

0

It's possible that because the content-type is not text/plain, the browser is issuing an OPTIONS request. and as stated in the console error the response does not set the 'Access-Control-Allow-Origin' header.

From looking at Eve's docs, it seems you need to set the X_EXPOSE_HEADERS variable with ['Access-Control-Allow-Origin'] that:

"Allows API maintainers to specify which headers are exposed within a CORS response. Allowed values are: None or a list of headers names. Defaults to None."

The browser expects to receive the 'Access-Control-Allow-Origin', thus the failure. Try to allow this header in the response from the API

0e1val
  • 481
  • 3
  • 6
  • 1
    Thank you for your answer, I tested that solution and unfortunately it does not work. I have managed to make it work in another way. I will make an answer as soon as I have some time. – Andrea Silvestri Feb 07 '19 at 09:13
0

In your Flask app, try setting the 'Access-Control-Allow-Origin' header in your response, i.e.,

response.headers.add('Access-Control-Allow-Origin', '*')

That should most likely solve the issue.

0

I have sorted out how to fix this though I am not completely satisfied.

Here the steps I've followed:

  • I have forked the Flask Sentinel repository
  • I have installed Flas-CORS with Pip
  • I have edited the flask_sentinel/flask_sentinel.py file by importing flask_cors
  • Before this line I've inserted this piece of code:
CORS(app, origins=['http://192.168.1.y:3000','https://192.168.1.y:3000'])
  • I went back to my Eve project and installed Flask-Sentinel through my forked repository with Pip instead of the original one
Andrea Silvestri
  • 1,082
  • 4
  • 14
  • 41
  • 1
    Instead of forking and editing `flask-sentinel` itself, you could import the `ResourceOwnerPasswordCredentials`, subclass it, and in the `__init__` method of your subclass you could do the `CORS` initiation and then run the `__init__` method of the superclass. You can then use your subclass instead of `ResourceOwnerPasswordCredentials` directly. – Luis Orduz Feb 07 '19 at 15:26