Show OTP code validity in frontends
This commit is contained in:
@@ -111,39 +111,15 @@ pub fn run(terminal: &mut DefaultTerminal) -> io::Result<()> {
|
||||
apply_authentication_event(&mut app, coordinator, &executor, &mut git_control, event);
|
||||
}
|
||||
|
||||
let unix_seconds = current_unix_seconds().map_err(io::Error::other)?;
|
||||
app.observe_time(unix_seconds);
|
||||
schedule_totp_refresh(&mut app, authentication.as_ref(), &executor);
|
||||
|
||||
let size = terminal.size()?;
|
||||
app.resize(size.width, size.height);
|
||||
terminal.draw(|frame| ui::draw_with_color_capability(frame, &app, color_capability))?;
|
||||
if !event::poll(TICK_INTERVAL)? {
|
||||
app.tick();
|
||||
if let Some((entry, field)) = app.begin_totp_refresh() {
|
||||
if let (Some(handle), Some(config)) = (
|
||||
authentication
|
||||
.as_ref()
|
||||
.and_then(AuthenticationCoordinator::handle),
|
||||
app.config().cloned(),
|
||||
) {
|
||||
let token = app.begin_request();
|
||||
executor.submit(token, move || {
|
||||
execute_otp_ui(
|
||||
&config,
|
||||
crate::app::OtpUiRequest {
|
||||
request: ironstorage::command::OtpRequest::Code(
|
||||
ironstorage::command::OtpCodeRequest {
|
||||
entry,
|
||||
clipboard: false,
|
||||
},
|
||||
),
|
||||
confirmed_hotp: false,
|
||||
field: Some(field),
|
||||
},
|
||||
handle,
|
||||
)
|
||||
});
|
||||
} else {
|
||||
app.authentication_failed("authentication lease expired".to_owned());
|
||||
}
|
||||
}
|
||||
if let Some(coordinator) = authentication.as_mut() {
|
||||
if let Some(event) = coordinator.poll_lease() {
|
||||
apply_authentication_event(
|
||||
@@ -265,6 +241,46 @@ pub fn run(terminal: &mut DefaultTerminal) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn current_unix_seconds() -> Result<u64, std::time::SystemTimeError> {
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map(|duration| duration.as_secs())
|
||||
}
|
||||
|
||||
fn schedule_totp_refresh(
|
||||
app: &mut App,
|
||||
authentication: Option<&AuthenticationCoordinator>,
|
||||
executor: &AsyncExecutor,
|
||||
) {
|
||||
let Some((entry, field)) = app.begin_totp_refresh() else {
|
||||
return;
|
||||
};
|
||||
let (Some(handle), Some(config)) = (
|
||||
authentication.and_then(AuthenticationCoordinator::handle),
|
||||
app.config().cloned(),
|
||||
) else {
|
||||
app.authentication_failed("authentication lease expired".to_owned());
|
||||
return;
|
||||
};
|
||||
let token = app.begin_request();
|
||||
executor.submit(token, move || {
|
||||
execute_otp_ui(
|
||||
&config,
|
||||
crate::app::OtpUiRequest {
|
||||
request: ironstorage::command::OtpRequest::Code(
|
||||
ironstorage::command::OtpCodeRequest {
|
||||
entry,
|
||||
clipboard: false,
|
||||
},
|
||||
),
|
||||
confirmed_hotp: false,
|
||||
field: Some(field),
|
||||
},
|
||||
handle,
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_terminal_ownership_lost(
|
||||
app: &mut App,
|
||||
authentication: &mut Option<AuthenticationCoordinator>,
|
||||
@@ -822,23 +838,20 @@ fn execute_otp_ui(
|
||||
if uri.kind() == OtpKind::Hotp && !request.confirmed_hotp {
|
||||
return Err("HOTP generation requires explicit confirmation".to_owned());
|
||||
}
|
||||
let unix_seconds = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.map_err(|_| "the system clock is before the Unix epoch".to_owned())?
|
||||
.as_secs();
|
||||
let unix_seconds = current_unix_seconds()
|
||||
.map_err(|_| "the system clock is before the Unix epoch".to_owned())?;
|
||||
let outcome = service
|
||||
.code_automatic(&code_request.entry, unix_seconds, None, &mut provider)
|
||||
.map_err(|error| error.to_string())?;
|
||||
let remaining_seconds = outcome.remaining_at(unix_seconds);
|
||||
let counter = outcome.counter();
|
||||
let validity = outcome.validity();
|
||||
let code = ironstorage::repository::SecretBytes::new(outcome.code().expose().to_vec());
|
||||
let tree = counter.map(|_| load_tree(config)).transpose()?;
|
||||
let tree = validity.counter().map(|_| load_tree(config)).transpose()?;
|
||||
Ok(AsyncPayload::OtpCodeFinished {
|
||||
entry: code_request.entry,
|
||||
field,
|
||||
code,
|
||||
remaining_seconds,
|
||||
counter,
|
||||
validity,
|
||||
observed_at: unix_seconds,
|
||||
clipboard: code_request.clipboard,
|
||||
tree,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user