Mukesh
Mukesh

Reputation: 125

How to return 401 authentication from flask API?

I have developed an API in flask which is using HttpBasicAuth to authenticate users. API is working absolutely fine in fiddler and returning 401 when we pass wrong credential but when I am using the same on login page I am getting extra pop up from browser. I really don't want to see this extra pop-up which is asking for credential (default behaviour of browser when returning

401

with

WWW-Authenticate: Basic realm="Authentication Required"

).

It is working fine when deployed locally but not working when hosted on remote server.

How can we implement 401 which will not let browser to display popup asking for credentials.

Upvotes: 5

Views: 19552

Answers (3)

CodeMed
CodeMed

Reputation: 9191

The following works. See docs.

from flask import Flask, abort

app = Flask(__name__)

@app.route('/api/endpoint/', methods=['GET'])
  abort(401, description="Error message you want the reader to receive.")

Upvotes: 1

Quentin Mayo
Quentin Mayo

Reputation: 410

So, flask return statements are actually processed again before sending the data off to the client. You can actually send a tuple of two elements as a return statement. The second element is the status (https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) If you are using the auth library, you can change this:

@auth.error_handler
def unauthorized():
    response = jsonify({'message':'Failed'})
    return response

To this:

@auth.error_handler
def unauthorized():
    response = jsonify({'message':'A winner is you'})
    return response, 404

If you don't want the popup message, change 401 to anything else.

Upvotes: 9

Miguel Grinberg
Miguel Grinberg

Reputation: 67509

This is a common problem when working with REST APIs and browser clients. Unfortunately there is no clean way to prevent the browser from displaying the popup. But there are tricks that you can do:

  • You can return a non-401 status code. For example, return 403. Technically it is wrong, but if you have control of the client-side API, you can make it work. The browser will only display the login dialog when it gets a 401.

  • Another maybe a bit cleaner trick is to leave the 401 in the response, but not include the WWW-Authenticate header in your response. This will also stop the login dialog from appearing.

  • And yet another (that I haven't tried myself, but have seen mentioned elsewhere) is to leave the 401 and the WWW-Authenticate, but change the auth method from Basic to something else that is unknown to the browser (i.e. not Basic and not Digest). For example, make it CustomBasic.

Upvotes: 3

Related Questions