From 38eddc1cf0c8206572a864c581fafea0c000c04b Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Tue, 19 Apr 2022 09:56:51 +0200 Subject: [PATCH] Generate QrCode to enroll Authenticator App --- Cargo.lock | 384 +++++++++++++++++++++- Cargo.toml | 5 +- src/controllers/two_factors_controller.rs | 28 +- src/data/app_config.rs | 6 +- src/data/mod.rs | 3 +- src/data/totp_key.rs | 53 +++ templates/settings/add_2fa_totp_page.html | 18 +- 7 files changed, 489 insertions(+), 8 deletions(-) create mode 100644 src/data/totp_key.rs diff --git a/Cargo.lock b/Cargo.lock index 6349c38..a255b19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -237,6 +237,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "aead" version = "0.4.3" @@ -393,6 +399,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +[[package]] +name = "base32" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" + [[package]] name = "base64" version = "0.13.0" @@ -413,6 +425,7 @@ dependencies = [ "actix-identity", "actix-web", "askama", + "base32", "base64", "bcrypt", "clap", @@ -424,11 +437,13 @@ dependencies = [ "lazy-regex", "log", "mime_guess", + "qrcode-generator", "rand", "serde", "serde_json", "serde_yaml", "sha2 0.10.2", + "totp_rfc6238", "urlencoding", "uuid", ] @@ -444,6 +459,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "bit_field" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" + [[package]] name = "bitflags" version = "1.3.2" @@ -505,6 +526,12 @@ version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +[[package]] +name = "bytemuck" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" + [[package]] name = "byteorder" version = "1.4.3" @@ -611,6 +638,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "const-oid" version = "0.6.2" @@ -675,6 +708,31 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +dependencies = [ + "autocfg 1.1.0", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.8" @@ -743,6 +801,15 @@ dependencies = [ "cipher 0.3.0", ] +[[package]] +name = "deflate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" +dependencies = [ + "adler32", +] + [[package]] name = "der" version = "0.4.5" @@ -818,6 +885,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "elliptic-curve" version = "0.11.12" @@ -859,6 +932,22 @@ dependencies = [ "termcolor", ] +[[package]] +name = "exr" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cc0e06fb5f67e5d6beadf3a382fec9baca1aa751c6d5368fdeee7e5932c215" +dependencies = [ + "bit_field", + "deflate", + "flume", + "half", + "inflate", + "lebe", + "smallvec", + "threadpool", +] + [[package]] name = "ff" version = "0.11.0" @@ -884,7 +973,20 @@ dependencies = [ "cfg-if", "crc32fast", "libc", - "miniz_oxide", + "miniz_oxide 0.4.4", +] + +[[package]] +name = "flume" +version = "0.10.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843c03199d0c0ca54bc1ea90ac0d507274c28abcc4f691ae8b4eaa375087c76a" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin 0.9.3", ] [[package]] @@ -963,8 +1065,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.10.2+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -977,6 +1081,16 @@ dependencies = [ "polyval", ] +[[package]] +name = "gif" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "group" version = "0.11.0" @@ -1007,6 +1121,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.11.2" @@ -1080,6 +1200,15 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "html-escape" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e7479fa1ef38eb49fb6a42c426be515df2d063f06cb8efd3e50af073dbc26c" +dependencies = [ + "utf8-width", +] + [[package]] name = "http" version = "0.2.6" @@ -1126,6 +1255,26 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db207d030ae38f1eb6f240d5a1c1c88ff422aa005d10f8c6c6fc5e75286ab30e" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "jpeg-decoder", + "num-iter", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + [[package]] name = "include_dir" version = "0.7.2" @@ -1155,6 +1304,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inflate" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +dependencies = [ + "adler32", +] + [[package]] name = "inout" version = "0.1.2" @@ -1179,6 +1337,24 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744c24117572563a98a7e9168a5ac1ee4a1ca7f702211258797bbe0ed0346c3c" +dependencies = [ + "rayon", +] + +[[package]] +name = "js-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "jwt-simple" version = "0.10.9" @@ -1250,9 +1426,15 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] +[[package]] +name = "lebe" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" + [[package]] name = "libc" version = "0.2.121" @@ -1319,6 +1501,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "mime" version = "0.3.16" @@ -1351,6 +1542,15 @@ dependencies = [ "autocfg 1.1.0", ] +[[package]] +name = "miniz_oxide" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.2" @@ -1374,6 +1574,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + [[package]] name = "nom" version = "7.1.1" @@ -1432,6 +1641,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-rational" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.14" @@ -1544,6 +1764,26 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.8" @@ -1591,6 +1831,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "png" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide 0.5.1", +] + [[package]] name = "polyval" version = "0.5.3" @@ -1642,6 +1894,23 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "qrcode-generator" +version = "4.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b1c0d1ea2ed9730a4037bf2dbc12b4b5c15679171adca65792657d1bd65ef6f" +dependencies = [ + "html-escape", + "image", + "qrcodegen", +] + +[[package]] +name = "qrcodegen" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" + [[package]] name = "quote" version = "1.0.17" @@ -1681,6 +1950,30 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" +dependencies = [ + "autocfg 1.1.0", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f51245e1e62e1f1629cbfec37b5793bbabcaeb90f30e94d2ba03564687353e4" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.12" @@ -1718,6 +2011,21 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "rsa" version = "0.5.0" @@ -1753,6 +2061,12 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1915,6 +2229,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.4.1" @@ -2004,6 +2327,26 @@ dependencies = [ "syn", ] +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiff" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cfada0986f446a770eca461e8c6566cb879682f7d687c8348aa0c857bd52286" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "time" version = "0.3.9" @@ -2092,6 +2435,15 @@ dependencies = [ "serde", ] +[[package]] +name = "totp_rfc6238" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e7d63d8bc3098dd14e5f1a107979a38e06b3263f1230a3cd717615fab4e615e" +dependencies = [ + "ring", +] + [[package]] name = "tracing" version = "0.1.32" @@ -2171,6 +2523,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.2.2" @@ -2189,6 +2547,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b90931029ab9b034b300b797048cf23723400aa757e8a2bfb9d748102f9821" +[[package]] +name = "utf8-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + [[package]] name = "uuid" version = "0.8.2" @@ -2270,6 +2634,22 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +[[package]] +name = "web-sys" +version = "0.3.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "weezl" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 760ec49..3bd98c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,4 +27,7 @@ base64 = "0.13.0" jwt-simple = "0.10.9" digest = "0.10.3" sha2 = "0.10.2" -lazy-regex = "2.3.0" \ No newline at end of file +lazy-regex = "2.3.0" +totp_rfc6238 = "0.5.0" +base32 = "0.4.0" +qrcode-generator = "4.1.4" \ No newline at end of file diff --git a/src/controllers/two_factors_controller.rs b/src/controllers/two_factors_controller.rs index 117241c..c33bf88 100644 --- a/src/controllers/two_factors_controller.rs +++ b/src/controllers/two_factors_controller.rs @@ -1,10 +1,13 @@ use std::ops::Deref; -use actix_web::{HttpResponse, Responder}; +use actix_web::{HttpResponse, Responder, web}; use askama::Template; +use qrcode_generator::QrCodeEcc; use crate::controllers::settings_controller::BaseSettingsPage; +use crate::data::app_config::AppConfig; use crate::data::current_user::CurrentUser; +use crate::data::totp_key::TotpKey; use crate::data::user::User; #[derive(Template)] @@ -18,6 +21,9 @@ struct TwoFactorsPage<'a> { #[template(path = "settings/add_2fa_totp_page.html")] struct AddTotpPage { _p: BaseSettingsPage, + qr_code: String, + account_name: String, + secret_key: String, } @@ -36,7 +42,22 @@ pub async fn two_factors_route(user: CurrentUser) -> impl Responder { /// Configure a new TOTP authentication factor -pub async fn add_totp_factor_route(user: CurrentUser) -> impl Responder { +pub async fn add_totp_factor_route(user: CurrentUser, app_conf: web::Data) -> impl Responder { + let key = TotpKey::new_random(); + + let qr_code = qrcode_generator::to_png_to_vec( + key.url_for_user(&user, &app_conf), + QrCodeEcc::Low, + 1024, + ); + let qr_code = match qr_code { + Ok(q) => q, + Err(e) => { + log::error!("Failed to generate QrCode! {:?}", e); + return HttpResponse::InternalServerError().body("Failed to generate QrCode!"); + } + }; + HttpResponse::Ok() .body(AddTotpPage { _p: BaseSettingsPage::get( @@ -44,5 +65,8 @@ pub async fn add_totp_factor_route(user: CurrentUser) -> impl Responder { &user, None, None), + qr_code: base64::encode(qr_code), + account_name: key.account_name(&user, &app_conf), + secret_key: key.get_secret(), }.render().unwrap()) } \ No newline at end of file diff --git a/src/data/app_config.rs b/src/data/app_config.rs index 87a7d22..a822e05 100644 --- a/src/data/app_config.rs +++ b/src/data/app_config.rs @@ -2,7 +2,7 @@ use std::path::{Path, PathBuf}; use clap::Parser; -use crate::constants::{CLIENTS_LIST_FILE, USERS_LIST_FILE}; +use crate::constants::{APP_NAME, CLIENTS_LIST_FILE, USERS_LIST_FILE}; /// Basic OIDC provider #[derive(Parser, Debug, Clone)] @@ -53,4 +53,8 @@ impl AppConfig { format!("{}/{}", self.website_origin, uri) } } + + pub fn domain_name(&self) -> &str { + self.website_origin.split('/').skip(2).next().unwrap_or(APP_NAME) + } } diff --git a/src/data/mod.rs b/src/data/mod.rs index b158b61..edf61a6 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -10,4 +10,5 @@ pub mod jwt_signer; pub mod id_token; pub mod code_challenge; pub mod open_id_user_info; -pub mod access_token; \ No newline at end of file +pub mod access_token; +pub mod totp_key; \ No newline at end of file diff --git a/src/data/totp_key.rs b/src/data/totp_key.rs new file mode 100644 index 0000000..cc61608 --- /dev/null +++ b/src/data/totp_key.rs @@ -0,0 +1,53 @@ +use base32::Alphabet; +use rand::Rng; + +use crate::data::app_config::AppConfig; +use crate::data::user::User; + +const BASE32_ALPHABET: Alphabet = Alphabet::RFC4648 { padding: true }; +const NUM_DIGITS: i32 = 6; +const PERIOD: i32 = 30; + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +pub struct TotpKey { + encoded: String, +} + +impl TotpKey { + /// Generate a new TOTP key + pub fn new_random() -> Self { + let random_bytes = rand::thread_rng().gen::<[u8; 10]>(); + TotpKey { + encoded: base32::encode(BASE32_ALPHABET, &random_bytes) + } + } + + /// Get QrCode URL for user + /// + /// Based on https://github.com/google/google-authenticator/wiki/Key-Uri-Format + pub fn url_for_user(&self, u: &User, conf: &AppConfig) -> String { + format!( + "otpauth://totp/{}:{}?secret={}&issuer={}&algorithm=SHA1&digits={}&period={}", + urlencoding::encode(&conf.domain_name()), + urlencoding::encode(&u.username), + self.encoded, + urlencoding::encode(&conf.domain_name()), + NUM_DIGITS, + PERIOD, + ) + } + + /// Get account name + pub fn account_name(&self, u: &User, conf: &AppConfig) -> String { + format!( + "{}:{}", + urlencoding::encode(conf.domain_name()), + urlencoding::encode(&u.username) + ) + } + + /// Get current secret in base32 format + pub fn get_secret(&self) -> String { + self.encoded.to_string() + } +} \ No newline at end of file diff --git a/templates/settings/add_2fa_totp_page.html b/templates/settings/add_2fa_totp_page.html index fc7d906..1401201 100644 --- a/templates/settings/add_2fa_totp_page.html +++ b/templates/settings/add_2fa_totp_page.html @@ -1,6 +1,22 @@ {% extends "base_settings_page.html" %} {% block content %} -TODO : show a form to add a new TOTP password +

On this page you can configure a new Authenticator app. Please use the authenticator app to scan the QR code.

+ +

Note: if you have not an authenticator app yet, you might want to use + FreeOTP + Authenticator for example.

+ + + +

If you can't scan the QrCode, please use the following parameters instead:

+ + +

Once you have scanned the QrCode, please generate a first QrCode and type it below:

+ +TODO : add form {% endblock content %}