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
125
126
127
128
129
130
131
132
|
use crate::error::{handle_rejection, Error};
use crate::schema::{Db, Transaction};
use std::convert::Infallible;
// use anyhow::{anyhow, Context, Result};
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
// use std::fmt::Display;
// use thiserror::Error;
use warp::header::headers_cloned;
use warp::http::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use warp::http::StatusCode;
use warp::reject;
use warp::reject::Reject;
use warp::reject::Rejection;
use warp::Filter;
const BEARER: &str = "Bearer ";
const PUBLIC_KEY_PEM: &str = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4nU0G4WjkmcQUx0hq6LQ
uV5Q+ACmUFL/OjoYMDwC/O/6pCd1UZgCfgHN2xEffDPznzcTn8OiFRxr4oWyBiny
rUpnY4mhy0SQUwoeCw7YkcHAyhCjNT74aR/ohX0MCj0qRRdbt5ZQXM/GC3HJuXE1
ptSuhFgQxziItamn8maoJ6JUSVEXVO1NOrrjoM3r7Q+BK2B+sX4/bLZ+VG5g1q2n
EbFdTHS6pHqtZNHQndTmEKwRfh0RYtzEzOXuO6e1gQY42Tujkof40dhGCIU7TeIG
GHwdFxy1niLkXwtHNjV7lnIOkTbx6+sSPamRfQAlZqUWM2Lf5o+7h3qWP3ENB138
sQIDAQAB
-----END PUBLIC KEY-----";
// const private_key_pem: &str = "-----BEGIN RSA PRIVATE KEY-----
// MIIEpAIBAAKCAQEA4nU0G4WjkmcQUx0hq6LQuV5Q+ACmUFL/OjoYMDwC/O/6pCd1
// UZgCfgHN2xEffDPznzcTn8OiFRxr4oWyBinyrUpnY4mhy0SQUwoeCw7YkcHAyhCj
// NT74aR/ohX0MCj0qRRdbt5ZQXM/GC3HJuXE1ptSuhFgQxziItamn8maoJ6JUSVEX
// VO1NOrrjoM3r7Q+BK2B+sX4/bLZ+VG5g1q2nEbFdTHS6pHqtZNHQndTmEKwRfh0R
// YtzEzOXuO6e1gQY42Tujkof40dhGCIU7TeIGGHwdFxy1niLkXwtHNjV7lnIOkTbx
// 6+sSPamRfQAlZqUWM2Lf5o+7h3qWP3ENB138sQIDAQABAoIBAD23nYTmrganag6M
// wPFrBSGP79c3Lhx0EjUHQjJbGKFgsdltG48qM3ut+DF9ACy0Z+/7bbC7+39vaIOq
// 1jLR2d6aiYTaLKseO4s2FawD1sgamvU3BZPsXn0gAhnnU5Gyy8Nas1dccvhoc9wI
// neaZUPrvucQ90AzLfo6r9yacDbYHB1lOyomApUvpJxOgHISGEtc9qGPDrdH19aF0
// 8fCv2bbQRh+TChgN3IB0o5w0wXaI7YAyAouAv/AzHCoEMpt7OGjFTkjh/ujlPL9O
// +FLuJNsQRHDN0gJo2pcvwGwDCsioMixQ9bZ7ZrUu2BNpEQygyeSbj9ZI1iRvhosO
// JU3rwEECgYEA9MppTYA6A9WQbCCwPH1QMpUAmPNVSWVhUVag4lGOEhdCDRcz9ook
// DohQMKctiEB1luKuvDokxo0uMOfMO9/YwjsRB7qjQip7Th1zMJIjD+A+juLzHK4r
// /RiRtWYGAnF8mptDvE+93JsPb3C/lQLvIhio5GQYWBqPJu6SpeosIskCgYEA7NPi
// Gbffzr2UQhW8BNKmctEEh8yFRVojFo3wwwWxSNUVXGSmSm31CL+Q8h817R+2OkPV
// 1ZMUOBU4UJiqFt28kIvTDFqbAJlJQGCpY2mY7OLQiD2A+TVLcFrHmoCaPfCAK1Qd
// hQ0PmFK7Mf8qClpA3E5chop/WfKQfiu46sZv1qkCgYAhGdXPcw1lQ1W6KVlrdI6J
// qHhiNlVMDXdxZkNvFxQdAiQeXQrbxaZGiMw/J/wSNpUwCAsUzM/4QVMDrfSCDCzl
// ZtNQtj4pTlFKKNVQthIjrXEIJUw2jp7IJLBfVSJu5iWxSlmId0f3MsiNizN81N69
// P5Rm/doE3+KHoy8VXGsHcQKBgQCkNh62enqjHWypjex6450qS6f6iWN3PRLLVsw0
// TcQpniZblCaBwVCAKmRUnjOEIdL2/4ZLutnwMTaFG/YEOOfAylMiY8jKV38lNmD9
// X4D78CFr9klxgvS2CRwSE03f2NzmLkLxuKaxldvaxPTfjMkgeO1LFMlNExYBhkuH
// 7uQpUQKBgQCKX6qMNh2gSdgG7qyxfTFZ4y5EGOBoKe/dE+IcVF3Vnh6DZVbCAbBL
// 5EdFWZSrCnDjA4xiKW55mwp95Ud9EZsZAb13L8V9t82eK+UDBoWlb7VRNYpda/x1
// 5/i4qQJ28x2UNJDStpYFpnp4Ba1lvXjKngIbDPkjU+hbBJ+BNGAIeg==
// -----END RSA PRIVATE KEY-----";
/// sub: Subject, user identifier
/// exp: Expiration date, Unix Time, epoch
/// puk: Public Key? Not 100% on this
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
exp: usize,
puk: String,
}
// #[derive(Error, Debug)]
// pub enum Nope {
// #[error("Invalid header")]
// InvalidHeader {
// expected: String,
// found: String,
// },
// }
// impl warp::reject::Reject for Nope {}
#[derive(Error, Debug)]
pub enum DataStoreError {
#[error("invalid header")]
InvalidHeader {},
}
impl Reject for DataStoreError {}
// impl From<LessThanTenError> for Rejection {
// fn from(other: LessThanTenError) -> Self {
// warp::reject::custom(other)
// }
// }
pub fn with_auth(
db: Db,
t: Transaction,
) -> impl Filter<Extract = (String,), Error = Rejection> + Clone {
headers_cloned()
.map(move |headers: HeaderMap<HeaderValue>| (db.clone(), headers))
.and_then(authorize)
.recover(handle_rejection())
}
async fn authorize((db, headers): (Db, HeaderMap<HeaderValue>)) -> Result<String, Infallible> {
match jwt_from_header(&headers) {
Ok(jwt) => {
let decoded = decode::<Claims>(
&jwt,
// TODO: what key are we using here? pass db/pw store here to get the claimant's public key <10-04-21, yigit> //
&DecodingKey::from_rsa_pem(PUBLIC_KEY_PEM.as_bytes()).unwrap(),
&Validation::new(Algorithm::HS512),
)
.map_err(|_| reject::custom(Error::JWTTokenError))
.unwrap();
Ok(decoded.claims.puk)
}
Err(e) => return (StatusCode::UNAUTHORIZED, e.to_string()),
// warp error
}
}
fn jwt_from_header(headers: &HeaderMap<HeaderValue>) -> Result<String, Error> {
let header = match headers.get(AUTHORIZATION) {
Some(v) => v,
None => return Err(Error::NoAuthHeaderError),
};
let auth_header = match std::str::from_utf8(header.as_bytes()) {
Ok(v) => v,
Err(_) => return Err(Error::NoAuthHeaderError),
};
if !auth_header.starts_with(BEARER) {
return Err(Error::InvalidAuthHeaderError);
}
Ok(auth_header.trim_start_matches(BEARER).to_owned())
}
|