问题
I'm using the awesome Eve REST-framework for creating a CRUD API with JWT authentication. I've looked at the tutorials posted here but I'm receiving a 401 error when doing a POST request to my endpoints that require token auth.
I've read this SO question: Issue with the Python Eve TokenAuth Feature but I'm pretty sure the token is Base64 encoded.
This is the response I'm getting back from the server when doing a cURL GET request:
curl -H "Authorization: <MYTOKEN>" -i http://MY_IP/users/548f6ecd64e6d12236c9576b
---- Response ----
HTTP/1.1 401 UNAUTHORIZED
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 16 Dec 2014 10:49:25 GMT
Content-Type: application/json
Content-Length: 91
Connection: keep-alive
WWW-Authenticate: Basic realm:"eve"
{"_status": "ERR", "_error": {"message": "Please provide proper credentials", "code": 401}}
Below is my code:
app.py
from eve import Eve
from eve.auth import TokenAuth
import jwt
class RolesAuth(TokenAuth):
def check_auth(self, token, allowed_roles, resource, method):
users = app.data.driver.db['users']
# Add check of user credentials by decoding JWT
user = users.find_one({'token': token})
return user
def add_token(documents):
for document in documents:
payload = {'username': document['username']}
document["token"] = jwt.encode(payload, 'secret')
if __name__ == '__main__':
app = Eve(auth=RolesAuth)
app.on_insert_users += add_token
app.run()
settings.py
users_schema = {
'username': {
'type': 'string',
'required': True,
},
'password': {
'type': 'string',
'required': True,
},
'email': {
'type': 'string',
'minlength': 1,
'maxlength': 200,
'required': True,
},
'token': {
'type': 'string',
},
'created': {
'type': 'datetime',
}
}
users = {
'cache_control': '',
'cache_expires': 0,
'extra_response_fields': ['token'],
'public_methods': ['POST'],
'schema': users_schema
}
DOMAIN = {
'users': users,
}
I have a token stored in my MongoDB for the user and I'm making the request with Postman and I'm including the token in the Authorization header like so:
Authorization: <USERTOKEN>
Any thoughts on why this gives me a 401.
Thanks!
回答1:
I tested your code but, for simplicity, I got rid of jwt.encode
:
def add_token(documents):
for document in documents:
payload = {'username': document['username']}
document["token"] = 'hello'
I POSTed a new user to /users
and then did a GET to the same endpoint with Postman: it works like a charm (200
). Then I did the same test with curl
:
curl -H "Authorization: Basic Y2lhbzo=" -i http://localhost:5000/users
That also retuns a 200
. As you can see the Auth header is encoded (copy & paste from Postman request preview). Just make sure you are passing the right stuff, maybe set a breakpoint in check_auth
to validate what's coming into it and wether the db lookup is successful or not.
Hope this helps in diagnosing your issue.
PS: please note that in curl the Authorization header also has a Basic
statement before the token, which seems to be lacking in your code snippet.
UPDATE
For the sake of it I also installed PyJWT and tested your code and... it works just fine on my end. Must be something wrong with your request.
UPDATE2
One thing that might not be so obvious is that you still need to append an (encoded) :
to your auth header (it's Basic Auth and it parses both username and pw). That's why in the above example you have a =
at the end of the encoded 'hello'.
来源:https://stackoverflow.com/questions/27501022/401-when-trying-to-authenticate-user-in-eve-flask-framework