Comments (16)
Not sure if this helps, but.. try adding an await statement
@api.get("", response=Test, auth=ApiKey())
async def test(request):
await request.auth <<<
return 200, {"msg": "hello!"}
from django-ninja.
@vitalik I'd like to help with this. I don't understand what's wrong with #202 though. It seems that it's very similar to the code above plus taking care of async auth on not-async operation and vice versa. If I understand what needs to be changed compared to #202, I'd be happy to prepare PR with code, tests and docs changes.
One of the main reasons I chose django-ninja
was it's support for async views and I'd like to broaden the async experience even further. Right now, I can't use built-in auth
at all and I'm doomed to calling my async auth function in each view, which is repetitive and prone to errors.
from django-ninja.
For the full copypasta
@api.get("", response=Test, auth=ApiKey())
async def test(request):
api_key = await request.auth
if not api_key:
raise AuthenticationError()
return 200, {"msg": "hello!"}
from django-ninja.
Thanks @changhyun-an and @maxmorlocke!
I build a decorator from your code :) This should reduce some boilerplate in case of many endpoints
def await_auth(f):
@functools.wraps(f)
async def decorator(*args, **kwargs):
auth = await args[0].auth # args[0] is always the request instance injected from ninja
if not auth :
raise AuthenticationError()
args[0].auth = auth
return await f(*args, **kwargs)
return decorator
Usage:
api = NinjaAPI(auth=ApiKey(), ...)
@api.post(...)
@await_auth
async def create(request, data: Input):
....
from django-ninja.
Yes, in nutshell this is the code I'm targeting for...
but there are few things to deal with - like if you have async auth, but not-async operation or vice-versa
from django-ninja.
Is there any chance for this issue to be resolved soon? I'm quite fond of django-ninja, it's just this issue that I find a bit unsettling.
from django-ninja.
I tried async-auth with v1.0 beta2 but it didn't work, and I finally came across this issue...
could you provide your example code ?
from django-ninja.
@skokado please check with latest version
pip install django-ninja==1.0rc0
from django-ninja.
any news on this ?
from django-ninja.
Not sure if this helps, but.. try adding an await statement
@api.get("", response=Test, auth=ApiKey()) async def test(request): await request.auth <<< return 200, {"msg": "hello!"}
ah, that's the magic of the event loop. Thank you, it really works.
from django-ninja.
While @changhyun-an 's answer works with a single authentication mechanism, I am having issues with multiple authentication classes.
I have a JWTAuth
and an APITokenAuth
. Using the await request.auth
technqiue, if the first auth class returns None
, the second is not tried and auth fails.
I could combine both authentication classes in one, but I prefer to keep them separate.
Does anyone have an idea about this ?
from django-ninja.
I tried async-auth with v1.0 beta2 but it didn't work, and I finally came across this issue...
I saw "async authentication fully supported on all layers" in the Release Note, but is the async-auth roadmap still in progress?
https://github.com/vitalik/django-ninja/releases/tag/v1.0b2
If so, I'd be very happy to mention that in the documentation, also link to this PR :)
Thank you
from django-ninja.
@vitalik Sorry 🙇 I was using 0.22.2, I broke my local environment without realizing.
It works as I expected with 1.0b2.
But one more, when failed Authentication caused by no token provided, then occurs 500 error
Here's my example code.
from ninja import NinjaAPI
from ninja.security import HttpBearer
api = NinjaAPI()
class MyAuth(HttpBearer):
async def authenticate(self, request, token):
if token == "secret":
request.user = MyUser(id=1, name="Foo")
return token
return None
@api.get("/me", auth=MyAuth())
async def me_view(request):
return {"hello": "world"}
curl -X 'GET' \
'http://localhost:8000/me' \
-H 'accept: */*'
Traceback:
Traceback (most recent call last):
File "/home/skokado/workspace/django-ninja-tutorial/venv/lib/python3.11/site-packages/ninja/operation.py", line 304, in _run_authentication
result = await callback(request)
^^^^^^^^^^^^^^^^^^^^^^^
TypeError: object NoneType can't be used in 'await' expression
It does not solve by registering @api.exception_handler
By incorrect token then can get 401 response
curl -X 'GET' \
'http://localhost:8000/api/me' \
-H 'accept: */*' \
-H 'Authorization: Bearer dummy'
# => {"detail": "Unauthorized"}
That does not occur when using sync-auth
from django-ninja.
@vitalik Works as expected, thank you for fixing.
from django-ninja.
@vitalik Sorry for repetitive, but I found new Warning in case non-empty token request at only first time.
It does not matter the authenticate attempt would be succeede or not.
Sample code is same as above #44 (comment)
$ curl -X 'GET' \
'http://localhost:8000/api/me' \
-H 'accept: */*' \
-H 'Authorization: Bearer secret'
/home/skokado/workspace/django-ninja/ninja/operation.py:311: RuntimeWarning: coroutine 'MyAuth.authenticate' was never awaited
result = await callback(request)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
{"hello": "world"}
At here, callback
is called twice
django-ninja/ninja/operation.py
Lines 308 to 310 in cd66ac8
from django-ninja.
Created a PR for this #44 (comment)
from django-ninja.
Related Issues (20)
- [BUG] Pydantic 2.7.0 incompatibily HOT 4
- [BUG] ModelSchema with ManyToManyField won't work under async views HOT 5
- How do you use aliases with nested objects
- [BUG] HOT 1
- [BUG] ModelSchema does not mark field as required if it has a default value
- [BUG] Swagger uses wrong endpoints for dynamically generated routers HOT 2
- Async reverse relationship HOT 4
- [BUG] Handler functions with same path but different http method can't use different path variable names
- [BUG] cdn error. HOT 3
- [BUG] paginate decorator with custom HTTP status `response={200: ..., 201: ...}` doesn't work HOT 3
- [BUG] Bearer authentication example from documentation doesn't work HOT 1
- `get_openapi_schema` outputs types using `anyOf` style - doesn't work with the Swift OpenAPI generator
- Error when trying to do django runserver -> pydantic.errors.PydanticSchemaGenerationError HOT 1
- [BUG] Using `pydantic.Json[SomeModel]` in a query param fails
- [BUG] Async Error Handlers Return Unawaited Coroutines Instead of HttpResponse in Django Ninja
- Dependency Injection support with `anydi`
- [BUG] `models.URLField` serialized & validated as `str`
- Exceptions log level HOT 1
- [BUG] CustomParser request header issue when sending json and file
- [BUG] `ModelSchema` produces `id > (integer | null)` openapi
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-ninja.