Closed ollyde closed 9 months ago
Also, for some reason the authentication isn't working, the headers never get sent.
let _ = match headers.get("device-id") {
Some(device_id) => device_id,
None => {
eprintln!("device-id header is required, headers are: {:?}", headers);
// Throw API error
let api_error = ApiError {
message: "device-id header is required".to_string(),
status: "no-device-id".to_string(),
};
res.render(api_error);
return;
}
};
Please give a minimum reproducible example.
@chrislearn it's the basic OpenAPI example with these add_security_scheme added. The headers are ignored from the Swagger docs
I ask your example because you said "for some reason the authentication isn't working, the headers never get sent.", I'm not very clear about the specific situation on your end. I can't understand what's going on just by posting a piece of code.
@chrislearn here you go, is this ok, or do you want a Github?
#[handler]
async fn hello(req: &mut Request) {
// There's no device id
let _ = match headers.get("device-id") {
Some(device_id) => device_id,
None => {
eprintln!("device-id header is required, headers are: {:?}", headers);
}
};
Ok("---")
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
let api_subrouter = Router::with_path("api")
.get(hello);
let router = Router::new()
.hoop(logger::logger_middleware)
.push(api_subrouter);
// Get the cargo version
let version = env!("CARGO_PKG_VERSION");
// OpenAPI with secruity headers
let open_api = OpenApi::new("test api", version)
.merge_router(&router)
.add_security_scheme(
"device-id",
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::with_description(
"device-id",
&"The device id, from the device".to_string(),
))),
)
.add_security_scheme(
"authorization",
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::with_description(
"authorization",
&"The JWT token, optional".to_string(),
))),
);
let router = router
.push(open_api.into_router("/api-doc/openapi.json"))
.push(SwaggerUi::new("/api-doc/openapi.json").into_router("ui"));
let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
Server::new(acceptor).serve(router).await;
}
You need to add security setting to endpoint:
#[endpoint(security(("device-id" = [], "authorization" = [])))]
async fn hello(req: &mut Request) {
// There's no device id
let id = req.header::<String>("device-id");
println!("device-id: {:?}", id);
}
If you want your authorization data persisted, you can use persist_authorization
@chrislearn I have to add this to every endpoint, what if we have 700 that are all under the same authorization schema? This should be a route setting?
After branch oapi-router
merged.
You can use router.oapi_security
or router.oapi_securitys
to set securities.
All endpoints in the router and it's descents will inherit these security requirements.
@chrislearn great thanks Chris
@chrislearn I mean how are we supposed to read this?
This line for example
pub fn new<N: Into<String>, S: IntoIterator<Item = I>, I: Into<String>>(name: N, scopes: S) -> Self {
It's really difficult to read, part of mpl SecurityRequirement
We used to do this? How would do the same?
let open_api = OpenApi::new(app_name, version)
.merge_router(&router)
.add_server(salvo::oapi::Server::new(env_vars().api_url.to_string()).description("API Url"))
.add_security_scheme(
"device-id",
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::with_description(
"device-id",
&"The device id, from the device".to_string(),
))),
)
.add_security_scheme(
"authorization",
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::with_description(
"authorization",
&"The JWT token, optional".to_string(),
))),
);
@chrislearn For example, it says the field is private here
let mut security_req = SecurityRequirement {
value: BTreeMap::new(),
};
security_req
.value
.insert("authorization".to_string(), Vec::new());
// The API routes
let mut api_subrouter = Router::with_path("api")
.hoop(auth_middleware)
.push(auth_routes())
.push(file_routes())
.push(notification_routes())
.push(admin_routes())
.oapi_securities(security);
For anyone else that might get stuck, here we go (confusing inputs..)
// Create multiple SecurityRequirement objects
let auth_requirement = SecurityRequirement::new(
"authorization".to_string(),
Vec::<String>::new().into_iter(),
);
let device_id_requirement =
SecurityRequirement::new("device-id".to_string(), Vec::<String>::new().into_iter());
let security_requirements = vec![auth_requirement, device_id_requirement];
// The API routes
let mut api_subrouter = Router::with_path("api")
.hoop(auth_middleware)
.push(auth_routes())
.push(file_routes())
.push(notification_routes())
.push(admin_routes())
.oapi_securities(security_requirements);
I'm adding a Security schema to OpenAPI, but it seems there's no way to add defaults, everything is lost on reload.
Would be nice to add defaults.