-
-
Notifications
You must be signed in to change notification settings - Fork 4
Authentication #164
Hello Tunay. I hope you're doing well.
It's so quiet here; I'll start a new discussion 😀
I've just implemented a basic authentication, following the example project under "https://github.com/Tuntii/RustAPI-examples/tree/main/auth-api".
Unfortunately, I keep getting the error:
{"error":{"type":"unauthorized","message":"No authenticated user. Did you forget to add JwtLayer middleware?"},"error_id":"err_3f3b5304cda046d18900fec6327bfa0d"}Any Ideas? Did I forget something?
You can test it with my code on codeberg under the branch "authentication"
All reactions
-
👀 2
Replies: 2 comments 5 replies
Hey @Tuntii.
Any ideas?
All reactions
-
🚀 1
I was dealing with family issues and my own business. I know how to fix the issue; I'll take a look at Codeberg. I was having the same problem in the example
All reactions
Hi Tunay,
I hope you and your family are doing well. Have you had a chance to take a look at the problem yet?
Take your time, but I hope you don’t give up on the project. I really like it.
All the best,
Peter
All reactions
-
👀 1
Hi Peter! Sorry for the long delay, and thanks for your patience.
I tracked this down, and the problem is most likely not your token generation or the AuthUser extractor itself.
The issue is the skip_paths(...) configuration. Right now the JWT layer treats skip entries as path prefixes, so if "/" is included, it matches every route including /protected/profile.
That means the middleware skips JWT validation for the protected routes as well, so no validated claims are inserted into the request. Then AuthUser<Claims> fails with:
No authenticated user. Did you forget to add JwtLayer middleware?
Immediate fix
Please remove "/" from the skip list and keep only the truly public paths, for example:
.layer( JwtLayer::<Claims>::new(JWT_SECRET) .skip_paths(vec!["/health", "/docs", "/auth/login"]) )
After that, the protected routes should start receiving the authenticated claims correctly, assuming you are sending:
Authorization: Bearer <token>
Why this was confusing
The error message makes it look like the middleware is missing, but in this case the middleware is present it is just skipping the protected route because of the root path entry.
Maintainer-side follow-up
I’ve also fixed this on the framework side so that "/" only matches the exact root path instead of every route, and I added regression coverage for it.
So the short version is:
- your auth flow is basically correct,
- the misleading part is the
skip_pathsbehavior, - and removing
"/"from that list should solve the problem immediately.
If you want, paste your middleware setup here and I can sanity-check it line by line.
All reactions
Hi Tunay,
It's great to hear from you. I'll take a look at it in the next few days and get back to you.
All reactions
-
❤️ 1
Hi Tunay.
I have removed / from skip_path, now it works. 😁
Am I correct in thinking that, once the JWT layer is added, all endpoints require authentication, except for those listed in skip_path?
It would be nice if all endpoints were accessible without authentication, and only those with the AuthUser extractor were protected. Is that possible?
All reactions
Hi Peter, glad you got it working! 🎉
Your understanding is correct. JwtLayer is an opt-out guard: once added, every request must carry a valid Bearer token unless the path is listed in skip_paths.
The pattern you're describing opt-in auth, where only handlers that declare AuthUser<T> are gated is a different design. Right now it's not directly supported, but there are two practical paths:
Option 1: Use skip_paths for your public routes (current, works today):
.layer(JwtLayer::<Claims>::new(secret).skip_paths(vec!["/health", "/docs", "/api/v1/public"]))
Option 2: Feature request: "optional" / "soft" JWT mode
A JwtLayer::optional() mode could validate and inject claims when a token is present, but let requests through without one. Handlers with AuthUser<T> would then enforce the gate themselves (they already return 401 if no claims are in extensions). This would enable exactly the behavior you described.
If Option 2 sounds useful, feel free to open a feature request. it's a reasonable addition and the groundwork (ValidatedClaims in extensions, AuthUser returning ApiError::unauthorized) is already there.