aboutsummaryrefslogtreecommitdiff
path: root/src/handlers/auth.rs
blob: 56b38f280bf6d46f5beb548492af8e60f2e79bd9 (plain) (blame)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::{
    collections::HashMap,
    fs::{self, File},
    sync::Arc, io::Read,
};

use axum::{extract::Query, middleware::Next, response::Response, Extension};
use axum_macros::debug_handler;
use chrono::{Datelike, TimeZone, Utc};
use hyper::Request;
use ring::{rand::SystemRandom, signature::Ed25519KeyPair};
use tracing::debug;
use uuid::Uuid;

use std::io::Write;

use crate::{
    errors::{NoneResult, ServiceError, StringResult, TokenResult},
    State,
};

/**
 * Takes in a request to create a new token with a secret key that gets printed
 * to stdout and, if it matches, returns a valid PASETO token that can be used
 * for future authentication
 */
#[debug_handler]
pub async fn begin(
    Query(params): Query<HashMap<String, String>>,
    Extension(state): Extension<Arc<State>>,
) -> TokenResult {
    if let Some(k) = params.get("key") {
        if k == &state.gen_key {
            let dt = Utc::now();
            let exp = Utc
                .ymd(dt.year() + 1, dt.month(), dt.day())
                .and_hms(0, 0, 0);
            let kp = load_or_gen_keypair()?;

            let token = match paseto::tokens::PasetoBuilder::new()
                .set_ed25519_key(&kp)
                .set_issued_at(Some(dt))
                .set_expiration(&exp)
                .set_issuer("solard")
                .set_audience("solard")
                .set_not_before(&Utc::now())
                .build()
            {
                Ok(token) => token,
                Err(_) => {
                    return Err(ServiceError::Generic(String::from(
                        "could not generate paseto key",
                    )));
                }
            };

            return Ok(token.to_string());
        } else {
            return Err(ServiceError::NotAuthorized);
        }
    } else {
        return Err(ServiceError::Generic("No key supplied".to_string()));
    }
}

pub async fn requires_auth<B>(req: Request<B>, next: Next<B>) -> Result<Response, ServiceError> {
    let auth_header = req
        .headers()
        .get(axum::http::header::AUTHORIZATION)
        .and_then(|h| h.to_str().ok());

    match auth_header {
        Some(h) => {
            debug!("Header: {}", h);
            let kp = load_or_gen_keypair()?;
            debug!("KP: {:?}", kp);
            match paseto::tokens::validate_public_token(h, None, &paseto::tokens::PasetoPublicKey::ED25519KeyPair(&kp), &paseto::tokens::TimeBackend::Chrono) {
                Ok(_) =>  Ok(next.run(req).await),
                Err(_) => Err(ServiceError::NotAuthorized)
            }
        }
        None => Err(ServiceError::NotAuthorized),
    }
}

fn load_or_gen_keypair() -> Result<Ed25519KeyPair, ServiceError> {
    let kp: Ed25519KeyPair;
        let mut file = match File::open(".keypair") {
            Ok(f) => f,
            Err(_) => {
                debug!("File does not exist, creating at .keypair");
                File::create(".keypair").unwrap()
            }
        };
    if let Ok(c) = fs::read(".keypair") {
        if c.len() == 0 {
            debug!("No keypair found. Generating...");


            let srand = SystemRandom::new();
            let pkcs8 = Ed25519KeyPair::generate_pkcs8(&srand)?;

            fs::write(".keypair", pkcs8.as_ref()).unwrap(); 
            debug!("Written keypair {:?} to .keypair", pkcs8.as_ref());

            kp = Ed25519KeyPair::from_pkcs8(pkcs8.as_ref())?;
        } else {

            debug!("Found keypair file, contents: {:?}", c);
            kp = Ed25519KeyPair::from_pkcs8(&c)?;
            debug!("Loaded keypair from file");
        }
    } else {
        debug!("Generating new keypair");
        let srand = SystemRandom::new();
        let pkcs8 = Ed25519KeyPair::generate_pkcs8(&srand)?;
            fs::write(".keypair", pkcs8.as_ref()).unwrap(); 
        debug!("Written keypair {:?} to .keypair", pkcs8.as_ref());

        kp = Ed25519KeyPair::from_pkcs8(pkcs8.as_ref())?;
    }

    Ok(kp)
}