feat(auth): expose auth_provider in UserDto and guard password ops for OIDC users
- Add auth_provider field to UserDto, derived from oidc_provider
("local" for password users, provider name for OIDC users)
- Block change_password() for OIDC users with clear error message
- Block admin_reset_password() for OIDC users
Fixes #122, Fixes #123
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ pub struct UserDto {
|
|||||||
pub updated_at: DateTime<Utc>,
|
pub updated_at: DateTime<Utc>,
|
||||||
pub last_login_at: Option<DateTime<Utc>>,
|
pub last_login_at: Option<DateTime<Utc>>,
|
||||||
pub active: bool,
|
pub active: bool,
|
||||||
|
pub auth_provider: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<User> for UserDto {
|
impl From<User> for UserDto {
|
||||||
@@ -29,6 +30,10 @@ impl From<User> for UserDto {
|
|||||||
updated_at: user.updated_at(),
|
updated_at: user.updated_at(),
|
||||||
last_login_at: user.last_login_at(),
|
last_login_at: user.last_login_at(),
|
||||||
active: user.is_active(),
|
active: user.is_active(),
|
||||||
|
auth_provider: user
|
||||||
|
.oidc_provider()
|
||||||
|
.unwrap_or("local")
|
||||||
|
.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -490,6 +490,15 @@ impl AuthApplicationService {
|
|||||||
// Get user
|
// Get user
|
||||||
let mut user = self.user_storage.get_user_by_id(user_id).await?;
|
let mut user = self.user_storage.get_user_by_id(user_id).await?;
|
||||||
|
|
||||||
|
// Block password changes for OIDC-provisioned users
|
||||||
|
if user.is_oidc_user() {
|
||||||
|
return Err(DomainError::new(
|
||||||
|
ErrorKind::AccessDenied,
|
||||||
|
"Auth",
|
||||||
|
"Password changes are not available for SSO/OIDC accounts. Your password is managed by your identity provider.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Verify current password using the injected hasher
|
// Verify current password using the injected hasher
|
||||||
let is_valid = self
|
let is_valid = self
|
||||||
.password_hasher
|
.password_hasher
|
||||||
@@ -780,6 +789,16 @@ impl AuthApplicationService {
|
|||||||
user_id: &str,
|
user_id: &str,
|
||||||
new_password: &str,
|
new_password: &str,
|
||||||
) -> Result<(), DomainError> {
|
) -> Result<(), DomainError> {
|
||||||
|
// Block password reset for OIDC-provisioned users
|
||||||
|
let user = self.user_storage.get_user_by_id(user_id).await?;
|
||||||
|
if user.is_oidc_user() {
|
||||||
|
return Err(DomainError::new(
|
||||||
|
ErrorKind::InvalidInput,
|
||||||
|
"Auth",
|
||||||
|
"Cannot reset password for SSO/OIDC accounts. The user's password is managed by their identity provider.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
if new_password.len() < 8 {
|
if new_password.len() < 8 {
|
||||||
return Err(DomainError::new(
|
return Err(DomainError::new(
|
||||||
ErrorKind::InvalidInput,
|
ErrorKind::InvalidInput,
|
||||||
|
|||||||
Reference in New Issue
Block a user