oidc-test-client/src/state_manager.rs
Pierre Hubert 9a3c44e840
All checks were successful
continuous-integration/drone/push Build is passing
Can complete authentication
2023-04-28 08:55:58 +02:00

73 lines
1.5 KiB
Rust

use std::error::Error;
use std::fmt;
use crate::crypto_wrapper::CryptoWrapper;
use crate::remote_ip::RemoteIP;
use crate::time_utils::time;
use crate::Res;
use bincode::{Decode, Encode};
use std::net::IpAddr;
pub struct StateManager;
static mut WRAPPER: Option<CryptoWrapper> = None;
#[derive(Encode, Decode, Debug)]
struct State {
ip: IpAddr,
expire: u64,
}
impl State {
pub fn new(ip: IpAddr) -> Self {
Self {
ip,
expire: time() + 15 * 60,
}
}
}
#[derive(Debug, Copy, Clone)]
enum StateError {
InvalidIp,
Expired,
}
impl Error for StateError {}
impl fmt::Display for StateError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "StateManager error {:?}", self)
}
}
impl StateManager {
pub fn init() {
unsafe {
WRAPPER = Some(CryptoWrapper::new_random());
}
}
/// Generate a new state
pub fn gen_state(ip: &RemoteIP) -> Res<String> {
let state = State::new(ip.0);
unsafe { WRAPPER.as_ref().unwrap() }.encrypt(&state)
}
/// Validate generated state
pub fn validate_state(ip: &RemoteIP, state: &str) -> Res {
let state: State = unsafe { WRAPPER.as_ref().unwrap() }.decrypt(state)?;
if state.ip != ip.0 {
return Err(Box::new(StateError::InvalidIp));
}
if state.expire < time() {
return Err(Box::new(StateError::Expired));
}
Ok(())
}
}