fix: Direct login without password change requirement
- Set change_required=false when creating admin password in Zitadel - Admin can now login directly at /suite/login without forced password change - Create security reminder file for admin to change password later - Update console and credential file messages to reflect direct login - Password change is recommended but not enforced on first login
This commit is contained in:
parent
115b2770cb
commit
1c7a5c80b2
3 changed files with 55 additions and 39 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"base_url": "http://localhost:8300",
|
"base_url": "http://localhost:8300",
|
||||||
"default_org": {
|
"default_org": {
|
||||||
"id": "354797876871692302",
|
"id": "354799954578898958",
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"domain": "default.localhost"
|
"domain": "default.localhost"
|
||||||
},
|
},
|
||||||
|
|
@ -13,8 +13,8 @@
|
||||||
"first_name": "Admin",
|
"first_name": "Admin",
|
||||||
"last_name": "User"
|
"last_name": "User"
|
||||||
},
|
},
|
||||||
"admin_token": "oU_rp4E81exidBP-jyaGcoKI1Ckoz-_U2O4BCMPmasKHktVw0ja2hP506-Bf-MD1JsqWl2A",
|
"admin_token": "6nMpG1E-H-hqlSjrbFB5n2yx8BoEpnl3a3-F3HJoc5bvria3nwiz8vURPndzS4lQWKwaz_8",
|
||||||
"project_id": "",
|
"project_id": "",
|
||||||
"client_id": "354797877458960398",
|
"client_id": "354799955384270862",
|
||||||
"client_secret": "k4MLtkaRFuKkJwfubZCN5g7UZT8GJttzYb1Zjb48Xo3OesQPeBsVC3xjhsn8uvrL"
|
"client_secret": "z6WFb1qshdCQ1y4Gw5EpOHzARgHicz6XkrazZwJdDcxMJrc6iRdHlhf5rf5LTzgi"
|
||||||
}
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ use log::{error, info, warn};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::client::ZitadelClient;
|
use super::client::ZitadelClient;
|
||||||
|
|
||||||
|
|
@ -116,7 +117,7 @@ async fn create_bootstrap_admin(client: &ZitadelClient) -> Result<BootstrapResul
|
||||||
|
|
||||||
let initial_password = generate_secure_password();
|
let initial_password = generate_secure_password();
|
||||||
|
|
||||||
if let Err(e) = client.set_user_password(&user_id, &initial_password, true).await {
|
if let Err(e) = client.set_user_password(&user_id, &initial_password, false).await {
|
||||||
warn!("Failed to set initial password via API: {}. User may need to use password reset flow.", e);
|
warn!("Failed to set initial password via API: {}. User may need to use password reset flow.", e);
|
||||||
} else {
|
} else {
|
||||||
info!("Initial password set for admin user");
|
info!("Initial password set for admin user");
|
||||||
|
|
@ -157,9 +158,44 @@ async fn create_bootstrap_admin(client: &ZitadelClient) -> Result<BootstrapResul
|
||||||
|
|
||||||
save_setup_credentials(&result);
|
save_setup_credentials(&result);
|
||||||
|
|
||||||
|
create_password_change_reminder(&user_id);
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_password_change_reminder(user_id: &str) {
|
||||||
|
let reminder_file = dirs::home_dir()
|
||||||
|
.unwrap_or_else(|| std::path::PathBuf::from("/tmp"))
|
||||||
|
.join(".gb-admin-reminders.json");
|
||||||
|
|
||||||
|
let reminder = serde_json::json!({
|
||||||
|
"id": Uuid::new_v4().to_string(),
|
||||||
|
"type": "security",
|
||||||
|
"priority": "high",
|
||||||
|
"title": "Change initial admin password",
|
||||||
|
"description": "The admin account was created with an auto-generated password. Please change it to a secure password of your choice.",
|
||||||
|
"user_id": user_id,
|
||||||
|
"created_at": chrono::Utc::now().to_rfc3339(),
|
||||||
|
"status": "pending",
|
||||||
|
"action_url": "/settings/security"
|
||||||
|
});
|
||||||
|
|
||||||
|
let reminders = if reminder_file.exists() {
|
||||||
|
let content = fs::read_to_string(&reminder_file).unwrap_or_default();
|
||||||
|
let mut arr: Vec<serde_json::Value> = serde_json::from_str(&content).unwrap_or_default();
|
||||||
|
arr.push(reminder);
|
||||||
|
arr
|
||||||
|
} else {
|
||||||
|
vec![reminder]
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = fs::write(&reminder_file, serde_json::to_string_pretty(&reminders).unwrap_or_default()) {
|
||||||
|
warn!("Failed to save password change reminder: {}", e);
|
||||||
|
} else {
|
||||||
|
info!("Created security reminder: Change initial admin password");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn create_default_organization(client: &ZitadelClient) -> Result<String> {
|
async fn create_default_organization(client: &ZitadelClient) -> Result<String> {
|
||||||
let url = format!("{}/v2/organizations", client.api_url());
|
let url = format!("{}/v2/organizations", client.api_url());
|
||||||
|
|
||||||
|
|
@ -205,37 +241,27 @@ fn save_setup_credentials(result: &BootstrapResult) {
|
||||||
let content = format!(
|
let content = format!(
|
||||||
r#"# General Bots Initial Setup Credentials
|
r#"# General Bots Initial Setup Credentials
|
||||||
# Created: {}
|
# Created: {}
|
||||||
# DELETE THIS FILE AFTER FIRST LOGIN
|
|
||||||
|
|
||||||
╔════════════════════════════════════════════════════════════╗
|
╔════════════════════════════════════════════════════════════╗
|
||||||
║ ADMIN LOGIN CREDENTIALS (OTP) ║
|
║ 🔐 ADMIN LOGIN - READY TO USE ║
|
||||||
╠════════════════════════════════════════════════════════════╣
|
╠════════════════════════════════════════════════════════════╣
|
||||||
║ ║
|
║ ║
|
||||||
║ Username: {:<46}║
|
║ Username: {:<46}║
|
||||||
║ Password: {:<46}║
|
║ Password: {:<46}║
|
||||||
║ Email: {:<46}║
|
║ Email: {:<46}║
|
||||||
║ ║
|
║ ║
|
||||||
║ Login URL: {:<45}║
|
║ 🌐 LOGIN NOW: http://localhost:8088/suite/login ║
|
||||||
║ ║
|
║ ║
|
||||||
╚════════════════════════════════════════════════════════════╝
|
╚════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
IMPORTANT:
|
✅ Login directly - no password change required on first access
|
||||||
- This is a one-time password (OTP)
|
⚠️ SECURITY: Change this password after login (Settings > Security)
|
||||||
- You will be required to change it on first login
|
🗑️ Delete this file after saving your new password
|
||||||
- Delete this file after you have logged in successfully
|
|
||||||
|
|
||||||
Alternative access via Zitadel console:
|
|
||||||
1. Go to: {}/ui/console
|
|
||||||
2. Login with admin PAT from: ./botserver-stack/conf/directory/admin-pat.txt
|
|
||||||
3. Find user '{}' and manage settings
|
|
||||||
"#,
|
"#,
|
||||||
chrono::Utc::now().format("%Y-%m-%d %H:%M:%S UTC"),
|
chrono::Utc::now().format("%Y-%m-%d %H:%M:%S UTC"),
|
||||||
result.username,
|
result.username,
|
||||||
result.initial_password,
|
result.initial_password,
|
||||||
result.email,
|
result.email
|
||||||
result.setup_url,
|
|
||||||
result.setup_url.split("/ui/").next().unwrap_or("http://localhost:8300"),
|
|
||||||
result.username
|
|
||||||
);
|
);
|
||||||
|
|
||||||
match fs::write(&creds_path, &content) {
|
match fs::write(&creds_path, &content) {
|
||||||
|
|
@ -268,7 +294,7 @@ fn print_bootstrap_credentials(result: &BootstrapResult) {
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("╠{}╣", separator);
|
println!("╠{}╣", separator);
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("║{:^60}║", "🔐 ONE-TIME PASSWORD (OTP) FOR LOGIN:");
|
println!("║{:^60}║", "🔐 LOGIN CREDENTIALS (READY TO USE):");
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("║ {:<58}║", format!("Username: {}", result.username));
|
println!("║ {:<58}║", format!("Username: {}", result.username));
|
||||||
println!("║ {:<58}║", format!("Password: {}", result.initial_password));
|
println!("║ {:<58}║", format!("Password: {}", result.initial_password));
|
||||||
|
|
@ -285,29 +311,22 @@ fn print_bootstrap_credentials(result: &BootstrapResult) {
|
||||||
|
|
||||||
println!("╠{}╣", separator);
|
println!("╠{}╣", separator);
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("║ {:56}║", "🌐 LOGIN URL:");
|
println!("║ {:56}║", "🌐 LOGIN NOW:");
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
|
println!("║ {:56}║", "http://localhost:8088/suite/login");
|
||||||
let url_display = if result.setup_url.len() > 54 {
|
|
||||||
format!("{}...", &result.setup_url[..51])
|
|
||||||
} else {
|
|
||||||
result.setup_url.clone()
|
|
||||||
};
|
|
||||||
println!("║ {:56}║", url_display);
|
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("╠{}╣", separator);
|
println!("╠{}╣", separator);
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("║ ⚠️ {:<53}║", "IMPORTANT - SAVE THESE CREDENTIALS!");
|
println!("║ ✅ {:<54}║", "Login directly - no password change required");
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("║ {:<56}║", "• This password will NOT be shown again");
|
println!("║ {:<56}║", "⚠️ Change password after login (Settings > Security)");
|
||||||
println!("║ {:<56}║", "• You must change it on first login");
|
println!("║ {:<56}║", "📁 Credentials saved to: ~/.gb-setup-credentials");
|
||||||
println!("║ {:<56}║", "• Credentials also saved to: ~/.gb-setup-credentials");
|
|
||||||
println!("║{:^60}║", "");
|
println!("║{:^60}║", "");
|
||||||
println!("╚{}╝", separator);
|
println!("╚{}╝", separator);
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Bootstrap complete: admin user '{}' created with OTP password",
|
"Bootstrap complete: admin user '{}' created - ready for direct login",
|
||||||
result.username
|
result.username
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -519,10 +519,7 @@ async fn main() -> std::io::Result<()> {
|
||||||
use botserver::config::ConfigManager;
|
use botserver::config::ConfigManager;
|
||||||
|
|
||||||
if no_console || no_ui {
|
if no_console || no_ui {
|
||||||
env_logger::Builder::from_env(env_logger::Env::default())
|
botlib::logging::init_compact_logger_with_style("info");
|
||||||
.write_style(env_logger::WriteStyle::Always)
|
|
||||||
.init();
|
|
||||||
|
|
||||||
println!("Starting General Bots {}...", env!("CARGO_PKG_VERSION"));
|
println!("Starting General Bots {}...", env!("CARGO_PKG_VERSION"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue