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
extern crate base64;
extern crate openssl;
extern crate serde_json;

use jsonwebtoken::{decode, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
use std::str;

use self::openssl::symm::*;

//Global error + conversions
#[derive(Serialize, Deserialize, Debug)]
pub enum KRNAuthErrors {
    TokenInvalid,
}

#[derive(Debug, Serialize, Deserialize)]
struct KRNClaims {
    aud: String,
    sub: String,
    exp: usize,
    iat: usize,
    jti: String,
    payload: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct KRNAuth {
    pub name: String,
    pub crypt_key: String,
    pub hmac_secret: String,
    pub rest_key: String,
    pub rsa_key: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct KRNUser {
    pub nick_name: String,
    pub email: String,
    pub first_name: String,
    pub last_name: String,
    pub flags: i64,
    pub id: String,
    pub int_id: i64,
}

impl KRNAuth {
    pub fn deep_validate(&self, passport: String) -> Result<String, KRNAuthErrors> {
        let url = format!(
            "https://trinity.krone.at/deep-validate?token={}",
            passport
        );
        let client = reqwest::blocking::Client::new();
        let resp = client.post(url).send().unwrap();

        if resp.status() == 200 {
            Ok(resp.text().unwrap().to_string())
        } else {
            Err(KRNAuthErrors::TokenInvalid)
        }
    }
    pub fn validate(self, passport: String) -> Result<KRNUser, KRNAuthErrors> {
        let token_parts: Vec<&str> = passport.split(":").collect();

        let decoded = decode::<KRNClaims>(
            &token_parts[1],
            &DecodingKey::from_secret(self.hmac_secret.as_ref()),
            &Validation::default(),
        )
        .unwrap();

        let payload = self
            .decode_payload(decoded.claims.payload.to_string())
            .unwrap();
        Ok(payload)
    }
    pub fn decode_payload(self, payload: String) -> Result<KRNUser, KRNAuthErrors> {
        let payload_base64 = base64::decode(&payload).unwrap();

        let iv_size = 16;
        let iv = &payload_base64[0..iv_size];
        let enc_data = &payload_base64[iv_size..];
        let mut decrypter = Crypter::new(
            Cipher::aes_256_cbc(),
            Mode::Decrypt,
            &self.crypt_key.as_bytes(),
            Some(&iv),
        )
        .unwrap();
        decrypter.pad(false);
        let mut decrypted = vec![0u8; 400];
        decrypter
            .update(&enc_data, decrypted.as_mut_slice())
            .unwrap();

        let decrypted_json = str::from_utf8(&decrypted[0..enc_data.len()]).unwrap();

        // WHAT IS THIS?
        let s = decrypted_json.replace("\u{6}", "");

        let v: serde_json::Value = serde_json::from_str(&s).unwrap();

        let u = KRNUser {
            nick_name: v["NickName"].to_string(),
            email: v["Email"].to_string(),
            first_name: v["FirstName"].to_string(),
            last_name: v["LastName"].to_string(),
            flags: v["Flags"].as_i64().unwrap(),
            int_id: v["IntID"].as_i64().unwrap(),
            id: v["ID"].to_string(),
        };
        Ok(u)
    }
}