summaryrefslogtreecommitdiff
path: root/src/request_handler/handler_login.rs
blob: aa93e9686c427c9d1bfed96a9ad83c0a282294ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::io;
use std::borrow::Cow;

use tokio::prelude::*;

use http::{Request, Response, StatusCode, Method};
use http::header::{SET_COOKIE, COOKIE};
use url::form_urlencoded;

use ::ApplicationState;
use ::totp;
use super::*;

pub(in super) fn GET<'a>(header_infos: &HeaderExtract, state: &ApplicationState, path_rest: &'a str)
                         -> Response<String> {
    if is_logged_in(&header_infos.cookies, &state.cookie_store) {
        Response::builder().set_defaults().body(views::login_is_logged_in()).unwrap()
    } else {
        Response::builder().set_defaults().body(views::login_login_form(path_rest)).unwrap()
    }
}

fn test_secrets(secrets: &Vec<&str>, token: &String) -> bool {
    secrets.iter()
        .any(|secret| {
            match totp::verify(secret, token) {
                Ok(true) => true,
                Ok(false) => false,
                Err(e) => {
                    error!("Error from totp::verify: {}", e);
                    false
                }
            }
        })
}

pub(in super) fn POST<'a>(header_infos: &HeaderExtract, state: &ApplicationState, req: &Request<Bytes>)
                          -> Response<String> {
    let mut token = None;
    let mut redirect = None;
    for (key, val) in form_urlencoded::parse(req.body()) {
        if key == "token" {
            token = Some(val.into_owned())
        } else if key == "redirect" {
            redirect = Some(val.into_owned())
        }
    }
    if token.is_none() {
        return error_handler_internal("missing argument 'token'".to_string());
    }
    let redirect = redirect.unwrap_or(Default::default());

    if header_infos.totp_secrets.is_empty() {
        return error_handler_internal("no secrets configured".to_string());
    }

    if test_secrets(&header_infos.totp_secrets, &token.unwrap()) {
        let cookie_value = state.cookie_store.create_authenticated_cookie();
        let cookie = CookieBuilder::new(COOKIE_NAME, cookie_value.to_string())
            .http_only(true)
            .path("/")
            .max_age(state.cookie_max_age)
            .finish();
        warn!("Authenticated user with cookie {}", cookie);
        Response::builder()
            .set_defaults()
            .header(SET_COOKIE, cookie.to_string())
            .body(views::login_auth_success(&redirect)).unwrap()
    } else {
        Response::builder()
            .set_defaults()
            .body(views::login_auth_fail()).unwrap()
    }
}