Closed bigblind closed 9 years ago
It's interesting because it permit to use any framework.
But I'm wondering, apart from Oauthlib/Flask-Oauthlib, is there another alternative ?
Maybe we can be more opiniated and integrate Flask-oauthlib ?
Hi @noirbizarre Sorry for my late reply.
I think it'd be good to allow people to document their API's security, without requiring a specific framework. However, having integration points where we can hook up other libraries would be cool. i'm using flask-oauthlib in my current project, and I don't think there's any other good one currently. points where we could integrate, are automatically getting the URLs for authorization and token endpoints, and automatically applying the require_oauth
decorator when scopes are required.
I read the doc but I am wondering how security currently works in flask-restplus. I would like to add LDAP and token security and I do no get how to start doing so. Thx.
@noirbizarre I'm still trying to add security to my flask-restplus project and haven't yet found any decent exemple to do so. I would like to add a api-token or oauth2 authentication to my API. I've been fiddling with the 'security' api parameter but so far I came up with nothing.
Can someone add an exemple of sucha setup in the documentation ?
Hi !
I documented a little bit more authorizations: http://flask-restplus.readthedocs.org/en/latest/documenting.html#documenting-autorizations
Everything is already supported into flask-restplus.
This is manual right now, but maybe in a futur it can handle OAuthlib to automatically extract OAuth information (and avoid duplicating declaration)
I added the following to my app:
authorizations = {
'apikey': {
'type': 'apiKey',
'in': 'header',
'name': 'X-API-KEY'
}
}
api = Api(
app,
version='1.0',
title='Assistant API',
description='Access data from the comfort of a RESTfull API.',
authorizations=authorizations,
security='apikey'
)
The generated JSON seams to be correct:
{
...
"security": [
{
"apikey": [ ]
}
],
"securityDefinitions": {
"apikey": {
"in": "header",
"name": "X-API-KEY",
"type": "apiKey"
}
},
...
}
But swagger-ui does not reflect any authentication, the API works without the token and the UI does not show any informations. Is it the normal behavior ?
Security implementation is up to the developer right now.
You can right something like that:
def auth_required(func):
func = api.doc(security='apikey')(func)
def check_auth(*args, **kwargs):
if 'X-API-KEY' not in request.headers:
api.abort('401', 'API key required')
key = request.headers['X-API-KEY']
// Check key validity
return func(*args, **kwargs)
return check_auth
Then you only have to decorate the required method like this:
class MyResource(Resource):
@auth_required
def post(self):
pass
They will be documented and checked.
The other alternative, if you're API always require a token, is to use the API decorators
parameter so all you resource will be decorated:
api = Api(app, decorators=[auth_required])
On the Swagger UI side, you need to use this: https://github.com/swagger-api/swagger-ui#user-content-header-parameters or this: https://github.com/swagger-api/swagger-ui#user-content-custom-header-parameters---for-basic-auth-etc But you're right, maybe I should integrate this automatically, find a way to configure it.
+1 for this integration.
@noirbizarre -- Do you have any tips about best to interact with "the Swagger UI side" via the Flask RestPlus framework? It's not immediately obvious how one should "get at" swagger to enable something like https://github.com/swagger-api/swagger-ui#user-content-header-parameters.
@noirbizarre ive implemented youre suggestion and auth works nicely. On the other hand the summary and description does not load/work anymore for the methods. u have any suggestion how to solve it? if u need more information please let me know
@noirbizarre I'm trying to implement the following at namespace level with
ns = Namespace('namespace name', description='my description',decorators=[auth_required])
My namespace doesn't seem to be picking up my decorator. Any ideas?
When using api.expect()
payload validation seems to happen before the auth_required
decorator is ran.
This leads to weird errors, where an unauthorized user can check which fields the payload can take by submitting empty payloads, because he gets the validation error instead of the auth error.
Has anyone faced this problem before?
PS: this happens when fields are required=True
@theholy7 Do you have the @expect before or after @auth_required when decorating your function?
I tried both ways and still got the error @honolulubill . But I created my own Resource
and overwrote one of the functions:
class AuthorizedResource(Resource):
"""
We created this AuthorizedResource from Resource
because the user authorization was being made after payload
validation. This way a non-auth'ed user was able to sniff the
payload that was required by the endpoint.
By wrapping dispatch_request with the requires_auth function,
we check for user authentication first.
"""
@requires_auth
def pre_dispatch_request(self):
"""
This method only exists so extended classes can do custom validations & checks that happen
after authorization and before dispatch_request.
"""
pass
def dispatch_request(self, *args, **kwargs):
self.pre_dispatch_request()
validate_content_type()
return super().dispatch_request(*args, **kwargs)
What I'm proposing, and willing to implement and contribute is a
SecurityRequirement
class, possibly with subclasses likeOAuth2SecurityRequirement
. defining an api with these requirements would look like this:Note that oauth2 requirement instances are callable, so you can pass in required scopes.
I'd be very much willing to implementthis and contribute the code back to this project if you're interested.