auth: widen identity provider seam
This commit is contained in:
Generated
+10
-10
@@ -4,7 +4,7 @@ version = 4
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "admin-api"
|
name = "admin-api"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -384,7 +384,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-adapter-rest"
|
name = "crank-adapter-rest"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -399,7 +399,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-community-auth"
|
name = "crank-community-auth"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -417,7 +417,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-community-mcp"
|
name = "crank-community-mcp"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -440,7 +440,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-core"
|
name = "crank-core"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -453,7 +453,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-mapping"
|
name = "crank-mapping"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crank-core",
|
"crank-core",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -464,7 +464,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-registry"
|
name = "crank-registry"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crank-core",
|
"crank-core",
|
||||||
"crank-mapping",
|
"crank-mapping",
|
||||||
@@ -480,7 +480,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-runtime"
|
name = "crank-runtime"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -505,7 +505,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crank-schema"
|
name = "crank-schema"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crank-core",
|
"crank-core",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -1273,7 +1273,7 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mcp-server"
|
name = "mcp-server"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ resolver = "3"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.85"
|
rust-version = "1.85"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
aes-gcm = "0.10"
|
aes-gcm = "0.10"
|
||||||
|
|||||||
@@ -163,4 +163,5 @@ Progress:
|
|||||||
- Phase 1 / task `1.5`: создан crate `crank-community-mcp`; в него вынесены `build_app`, `catalog`, `jsonrpc`, `session` и `auth` из `apps/mcp-server`, а `apps/mcp-server/src/main.rs` стал thin launcher с env parsing и DI wiring
|
- Phase 1 / task `1.5`: создан crate `crank-community-mcp`; в него вынесены `build_app`, `catalog`, `jsonrpc`, `session` и `auth` из `apps/mcp-server`, а `apps/mcp-server/src/main.rs` стал thin launcher с env parsing и DI wiring
|
||||||
- Phase 1 / task `1.6`: Community test surface уже приведен к честному baseline — `test = false` удален ранее, premium-only tests вычищены, `just verify` проходит на текущем составе workspace
|
- Phase 1 / task `1.6`: Community test surface уже приведен к честному baseline — `test = false` удален ранее, premium-only tests вычищены, `just verify` проходит на текущем составе workspace
|
||||||
- Phase 1 / task `1.7`: workspace version bumped to `0.2.0`; release gate пройден (`just verify`, `npm run build`, `npm run e2e`), release commit и tag `v0.2.0` подготовлены в `crank-community`
|
- Phase 1 / task `1.7`: workspace version bumped to `0.2.0`; release gate пройден (`just verify`, `npm run build`, `npm run e2e`), release commit и tag `v0.2.0` подготовлены в `crank-community`
|
||||||
|
- Phase 2 dependency slice: `IdentityProvider` seam widened to cover `SSO/TOTP` with default `NotSupportedForProvider` methods and shared public DTOs for authorize/callback/two-factor flows; workspace version bumped to `0.3.0` for downstream enterprise consumption
|
||||||
- backward-compatible alias `CommunityMachineCredentialVerifier` сохранен, поведение Community не изменено
|
- backward-compatible alias `CommunityMachineCredentialVerifier` сохранен, поведение Community не изменено
|
||||||
|
|||||||
@@ -912,6 +912,9 @@ impl AdminService {
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(LoginOutcome::Authenticated(identity)) => Ok(identity),
|
Ok(LoginOutcome::Authenticated(identity)) => Ok(identity),
|
||||||
|
Ok(LoginOutcome::TwoFactorRequired(_)) => Err(ApiError::internal(
|
||||||
|
"two-factor login flow is not configured for this service",
|
||||||
|
)),
|
||||||
Err(error) => Err(map_identity_error(error)),
|
Err(error) => Err(map_identity_error(error)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
IssueAgentTokenRequest, IssueOneTimeAgentTokenRequest, IssuedAgentTokenResponse,
|
IssueAgentTokenRequest, IssueOneTimeAgentTokenRequest, IssuedAgentTokenResponse,
|
||||||
@@ -125,8 +126,64 @@ pub struct LoginPayload {
|
|||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct SsoAuthorizeRequest {
|
||||||
|
pub workspace_id: WorkspaceId,
|
||||||
|
pub provider_id: String,
|
||||||
|
pub base_origin: String,
|
||||||
|
pub return_to: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct SsoAuthorizeRedirect {
|
||||||
|
pub authorization_url: String,
|
||||||
|
pub state: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct SsoCallbackRequest {
|
||||||
|
pub workspace_id: WorkspaceId,
|
||||||
|
pub provider_id: String,
|
||||||
|
pub code: String,
|
||||||
|
pub base_origin: String,
|
||||||
|
pub return_to: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct TwoFactorPendingIdentity {
|
||||||
|
pub user_id: UserId,
|
||||||
|
pub workspace_id: Option<WorkspaceId>,
|
||||||
|
pub return_to: Option<String>,
|
||||||
|
pub expires_at: OffsetDateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct TwoFactorStatus {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub pending_setup: bool,
|
||||||
|
pub recovery_codes_remaining: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct TwoFactorSetup {
|
||||||
|
pub secret: String,
|
||||||
|
pub otpauth_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct TwoFactorActivation {
|
||||||
|
pub recovery_codes: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Default)]
|
||||||
|
pub struct TwoFactorChallenge {
|
||||||
|
pub code: Option<String>,
|
||||||
|
pub recovery_code: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum LoginOutcome {
|
pub enum LoginOutcome {
|
||||||
Authenticated(AuthenticatedIdentity),
|
Authenticated(AuthenticatedIdentity),
|
||||||
|
TwoFactorRequired(TwoFactorPendingIdentity),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -136,6 +193,59 @@ pub trait IdentityProvider: Send + Sync {
|
|||||||
fn kind(&self) -> IdentityProviderKind;
|
fn kind(&self) -> IdentityProviderKind;
|
||||||
|
|
||||||
async fn login_password(&self, payload: LoginPayload) -> Result<LoginOutcome, IdentityError>;
|
async fn login_password(&self, payload: LoginPayload) -> Result<LoginOutcome, IdentityError>;
|
||||||
|
|
||||||
|
async fn begin_sso(
|
||||||
|
&self,
|
||||||
|
_request: SsoAuthorizeRequest,
|
||||||
|
) -> Result<SsoAuthorizeRedirect, IdentityError> {
|
||||||
|
Err(IdentityError::NotSupportedForProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn complete_sso(
|
||||||
|
&self,
|
||||||
|
_request: SsoCallbackRequest,
|
||||||
|
) -> Result<LoginOutcome, IdentityError> {
|
||||||
|
Err(IdentityError::NotSupportedForProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_two_factor_status(
|
||||||
|
&self,
|
||||||
|
_user_id: &UserId,
|
||||||
|
) -> Result<TwoFactorStatus, IdentityError> {
|
||||||
|
Err(IdentityError::NotSupportedForProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn begin_two_factor_setup(
|
||||||
|
&self,
|
||||||
|
_user_id: &UserId,
|
||||||
|
_email: &str,
|
||||||
|
) -> Result<TwoFactorSetup, IdentityError> {
|
||||||
|
Err(IdentityError::NotSupportedForProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn activate_two_factor(
|
||||||
|
&self,
|
||||||
|
_user_id: &UserId,
|
||||||
|
_code: &str,
|
||||||
|
) -> Result<TwoFactorActivation, IdentityError> {
|
||||||
|
Err(IdentityError::NotSupportedForProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn disable_two_factor(
|
||||||
|
&self,
|
||||||
|
_user_id: &UserId,
|
||||||
|
_challenge: TwoFactorChallenge,
|
||||||
|
) -> Result<(), IdentityError> {
|
||||||
|
Err(IdentityError::NotSupportedForProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn verify_two_factor_login(
|
||||||
|
&self,
|
||||||
|
_pending: &TwoFactorPendingIdentity,
|
||||||
|
_challenge: TwoFactorChallenge,
|
||||||
|
) -> Result<AuthenticatedIdentity, IdentityError> {
|
||||||
|
Err(IdentityError::NotSupportedForProvider)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SharedIdentityProvider = Arc<dyn IdentityProvider>;
|
pub type SharedIdentityProvider = Arc<dyn IdentityProvider>;
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ pub use ext::auth::{
|
|||||||
AuthenticatedIdentity, IdentityError, IdentityProvider, IdentityProviderKind, LoginOutcome,
|
AuthenticatedIdentity, IdentityError, IdentityProvider, IdentityProviderKind, LoginOutcome,
|
||||||
LoginPayload, MachineCredentialVerifier, MachineCredentialVerifierError, MachineTokenIssuer,
|
LoginPayload, MachineCredentialVerifier, MachineCredentialVerifierError, MachineTokenIssuer,
|
||||||
NoMachineTokenIssuer, SharedIdentityProvider, SharedMachineCredentialVerifier,
|
NoMachineTokenIssuer, SharedIdentityProvider, SharedMachineCredentialVerifier,
|
||||||
SharedMachineTokenIssuer, TokenIssuerActor, TokenIssuerError, VerifiedMachineCredential,
|
SharedMachineTokenIssuer, SsoAuthorizeRedirect, SsoAuthorizeRequest, SsoCallbackRequest,
|
||||||
|
TokenIssuerActor, TokenIssuerError, TwoFactorActivation, TwoFactorChallenge,
|
||||||
|
TwoFactorPendingIdentity, TwoFactorSetup, TwoFactorStatus, VerifiedMachineCredential,
|
||||||
};
|
};
|
||||||
pub use ext::capability::{CapabilityProfile, CommunityCapabilityProfile};
|
pub use ext::capability::{CapabilityProfile, CommunityCapabilityProfile};
|
||||||
pub use ext::protocol::{
|
pub use ext::protocol::{
|
||||||
|
|||||||
Reference in New Issue
Block a user