Hello! I want to create a request guard to check for a jsonwebtoken in a cookie on a rocket server, but I am running into strange issues...
This is my cargo.toml
:
[package]
name = "bread"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dotenv = "0.15.0"
jsonwebtoken = "8.3.0"
mongodb = { version = "2.4.0", default-features = false, features = ["sync"] }
password-hash = "0.5.0"
rocket = { version = "0.5.0-rc.3", features = ["json"] }
rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["tera"] }
rust-argon2 = "1.0"
serde = "1.0.154"
This is my code:
use jsonwebtoken::{DecodingKey, EncodingKey, Validation};
use rocket::{
data::Outcome,
http::Status,
request::{FromRequest, Request},
};
use serde::{Deserialize, Serialize};
pub const ENCODING_KEY: EncodingKey = EncodingKey::from_secret("SECRET".as_bytes());
pub const DECODING_KEY: DecodingKey = DecodingKey::from_secret("SECRET".as_bytes());
#[derive(Debug, Serialize, Deserialize)]
pub struct Claims {
pub exp: usize,
pub sub: String,
}
#[rocket::async_trait]
impl<'a> FromRequest<'a> for Claims {
type Error = String;
async fn from_request(request: &'a Request<'_>) -> Outcome<Self, Self::Error> {
let cookie = request
.cookies()
.get("api-token")
.map(|cookie| cookie.value());
let token = match cookie {
Some(encoded_token) => {
jsonwebtoken::decode::<Claims>(encoded_token, &DECODING_KEY, &Validation::default())
.ok()
.map(|token| token.claims)
}
None => None,
};
match token {
Some(valid_token) => Outcome::Success(valid_token),
None => Outcome::Failure((
Status::Unauthorized,
"Invalid or missing API token!".to_string(),
)),
}
}
}
From what I can see, it looks like the examples in the rocket documentation: FromRequest in rocket::request - Rust. However, this code yields the following errors:
error[E0106]: missing lifetime specifier
--> src\api\token.rs:22:63
|
22 | async fn from_request(request: &'a Request<'_>) -> Outcome<Self, Self::Error> {
| --------------- ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
note: these named lifetimes are available to use
--> src\api\token.rs:19:6
|
19 | impl<'a> FromRequest<'a> for Claims {
| ^^
...
22 | async fn from_request(request: &'a Request<'_>) -> Outcome<Self, Self::Error> {
| ^^^^^ ^^
help: consider using one of the available lifetimes here
|
22 | async fn from_request(request: &'a Request<'_>) -> Outcome<'lifetime, Self, Self::Error> {
| ++++++++++
error[E0053]: method `from_request` has an incompatible type for trait
--> src\api\token.rs:22:5
|
22 | async fn from_request(request: &'a Request<'_>) -> Outcome<Self, Self::Error> {
| ^^^^^
| |
| expected `()`, found struct `Data`
| help: change the output type to match the trait: `Pin<Box<(dyn std::future::Future<Output = Outcome<Claims, (Status, std::string::String), ()>> + std::marker::Send + 'async_trait)>>`
|
= note: expected signature `fn(&'a rocket::Request<'life0>) -> Pin<Box<(dyn std::future::Future<Output = Outcome<Claims, (Status, std::string::String), ()>> + std::marker::Send + 'async_trait)>>`
found signature `fn(&'a rocket::Request<'life0>) -> Pin<Box<(dyn std::future::Future<Output = Outcome<Claims, (Status, std::string::String), rocket::Data<'static>>> + std::marker::Send + 'async_trait)>>`
Some errors have detailed explanations: E0053, E0106.
For more information about an error, try `rustc --explain E0053`.
error: could not compile `bread` due to 2 previous errors
The first error can be fixed by changing the function's signature to this:
async fn from_request(request: &'a Request<'_>) -> Outcome<'a, Self, Self::Error>
But the other error still persists after that:
error[E0053]: method `from_request` has an incompatible type for trait
--> src\api\token.rs:22:5
|
22 | async fn from_request(request: &'a Request<'_>) -> Outcome<'a, Self, Self::Error> {
| ^^^^^
| |
| expected `()`, found struct `Data`
| help: change the output type to match the trait: `Pin<Box<(dyn std::future::Future<Output = Outcome<Claims, (Status, std::string::String), ()>> + std::marker::Send + 'async_trait)>>`
|
= note: expected signature `fn(&'a rocket::Request<'life0>) -> Pin<Box<(dyn std::future::Future<Output = Outcome<Claims, (Status, std::string::String), ()>> + std::marker::Send + 'async_trait)>>`
found signature `fn(&'a rocket::Request<'life0>) -> Pin<Box<(dyn std::future::Future<Output = Outcome<Claims, (Status, std::string::String), rocket::Data<'a>>> + std::marker::Send + 'async_trait)>>`
For more information about this error, try `rustc --explain E0053`.
error: could not compile `bread` due to previous error
What is causing this error? Where is this rocket::Data
coming from and how can I make i into a ()
? Any idea of how to fix it? I have been sitting with this trying lots of stuff for hours... For full context, all code is available here: GitHub - BurnyLlama/bread: Bread is a social media focusing in the mental health and privacy..
Thanks in advance,
BurnyLlama