Replaced /api/auth response with cookies

This commit is contained in:
Antoine Gersant 2020-01-12 17:01:30 -08:00
parent 360d864148
commit eca4f68834
5 changed files with 56 additions and 34 deletions

1
Cargo.lock generated
View file

@ -1491,6 +1491,7 @@ dependencies = [
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
"simplelog 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"unix-daemonize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -37,6 +37,7 @@ serde_derive = "1.0"
serde_json = "1.0"
simplelog = "0.7"
thiserror = "1.0"
time = "0.1"
toml = "0.5"
[dependencies.rocket_contrib]

View file

@ -2,7 +2,7 @@
"openapi": "3.0.0",
"info": {
"description": "",
"version": "3.0",
"version": "4.0",
"title": "Polaris",
"termsOfService": ""
},
@ -182,7 +182,7 @@
"tags": [
"Other"
],
"summary": "Returns information about user permissions and a session cookie for future authenticated requests.",
"summary": "Signs in a user. Response has Set-Cookie headers for the session, username and admin permission of the user.",
"operationId": "postAuth",
"requestBody": {
"required": true,
@ -196,14 +196,7 @@
},
"responses": {
"200": {
"description": "Successful operation",
"content": {
"application/json": {
"schema": {
"$ref": "#components/schemas/AuthOutput"
}
}
}
"description": "Successful operation"
},
"401": {
"description": "Invalid credentials"
@ -874,14 +867,6 @@
}
}
},
"AuthOutput": {
"type": "object",
"properties": {
"admin": {
"type": "boolean"
}
}
},
"CollectionFile": {
"oneOf": [
{

View file

@ -12,6 +12,7 @@ use std::str;
use std::str::FromStr;
use std::sync::Arc;
use thiserror::Error;
use time::Duration;
use crate::config::{self, Config, Preferences};
use crate::db::DB;
@ -24,9 +25,11 @@ use crate::user;
use crate::utils;
use crate::vfs::VFSSource;
const CURRENT_MAJOR_VERSION: i32 = 3;
const CURRENT_MINOR_VERSION: i32 = 1;
const CURRENT_MAJOR_VERSION: i32 = 4;
const CURRENT_MINOR_VERSION: i32 = 0;
const COOKIE_SESSION: &str = "session";
const COOKIE_USERNAME: &str = "username";
const COOKIE_ADMIN: &str = "admin";
pub fn get_routes() -> Vec<rocket::Route> {
routes![
@ -86,11 +89,32 @@ struct Auth {
username: String,
}
fn get_session_cookie(username: &str) -> Cookie<'static> {
Cookie::build(COOKIE_SESSION, username.to_owned())
fn add_session_cookies(cookies: &mut Cookies, username: &str, is_admin: bool) -> () {
let duration = Duration::days(1);
let session_cookie = Cookie::build(COOKIE_SESSION, username.to_owned())
.same_site(rocket::http::SameSite::Lax)
.http_only(true)
.finish()
.max_age(duration)
.finish();
let username_cookie = Cookie::build(COOKIE_USERNAME, username.to_owned())
.same_site(rocket::http::SameSite::Lax)
.http_only(false)
.max_age(duration)
.path("/")
.finish();
let is_admin_cookie = Cookie::build(COOKIE_ADMIN, format!("{}", is_admin))
.same_site(rocket::http::SameSite::Lax)
.http_only(false)
.max_age(duration)
.path("/")
.finish();
cookies.add_private(session_cookie);
cookies.add(username_cookie);
cookies.add(is_admin_cookie);
}
impl<'a, 'r> FromRequest<'a, 'r> for Auth {
@ -116,7 +140,11 @@ impl<'a, 'r> FromRequest<'a, 'r> for Auth {
_ => return Outcome::Failure((Status::InternalServerError, ())),
};
if user::auth(db.deref().deref(), &username, &password).unwrap_or(false) {
cookies.add_private(get_session_cookie(&username));
let is_admin = match user::is_admin(db.deref().deref(), &username) {
Ok(a) => a,
Err(_) => return Outcome::Failure((Status::InternalServerError, ())),
};
add_session_cookies(&mut cookies, &username, is_admin);
return Outcome::Success(Auth {
username: username.to_string(),
});
@ -256,17 +284,13 @@ fn auth(
db: State<'_, Arc<DB>>,
credentials: Json<AuthCredentials>,
mut cookies: Cookies<'_>,
) -> std::result::Result<Json<AuthOutput>, APIError> {
) -> std::result::Result<(), APIError> {
if !user::auth::<DB>(&db, &credentials.username, &credentials.password)? {
return Err(APIError::IncorrectCredentials);
}
cookies.add_private(get_session_cookie(&credentials.username));
let auth_output = AuthOutput {
admin: user::is_admin::<DB>(&db, &credentials.username)?,
};
Ok(Json(auth_output))
let is_admin = user::is_admin::<DB>(&db, &credentials.username)?;
add_session_cookies(&mut cookies, &credentials.username, is_admin);
Ok(())
}
#[get("/browse")]

View file

@ -58,7 +58,7 @@ fn version() {
let response_body = response.body_string().unwrap();
let response_json: api::Version = serde_json::from_str(&response_body).unwrap();
assert_eq!(response_json, api::Version { major: 3, minor: 1 });
assert_eq!(response_json, api::Version { major: 4, minor: 0 });
}
#[test]
@ -271,7 +271,18 @@ fn auth() {
.body(serde_json::to_string(&credentials).unwrap())
.dispatch();
assert_eq!(response.status(), Status::Ok);
assert_eq!(response.cookies()[0].name(), "session");
assert!(response
.cookies()
.iter()
.any(|cookie| cookie.name() == "username"));
assert!(response
.cookies()
.iter()
.any(|cookie| cookie.name() == "admin"));
assert!(response
.cookies()
.iter()
.any(|cookie| cookie.name() == "session"));
}
}