mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
feat(users): add endpoint for terminate auth select (#5135)
This commit is contained in:
@ -10,16 +10,17 @@ use crate::user::{
|
|||||||
dashboard_metadata::{
|
dashboard_metadata::{
|
||||||
GetMetaDataRequest, GetMetaDataResponse, GetMultipleMetaDataPayload, SetMetaDataRequest,
|
GetMetaDataRequest, GetMetaDataResponse, GetMultipleMetaDataPayload, SetMetaDataRequest,
|
||||||
},
|
},
|
||||||
AcceptInviteFromEmailRequest, AuthorizeResponse, BeginTotpResponse, ChangePasswordRequest,
|
AcceptInviteFromEmailRequest, AuthSelectRequest, AuthorizeResponse, BeginTotpResponse,
|
||||||
ConnectAccountRequest, CreateInternalUserRequest, CreateUserAuthenticationMethodRequest,
|
ChangePasswordRequest, ConnectAccountRequest, CreateInternalUserRequest,
|
||||||
DashboardEntryResponse, ForgotPasswordRequest, GetSsoAuthUrlRequest,
|
CreateUserAuthenticationMethodRequest, DashboardEntryResponse, ForgotPasswordRequest,
|
||||||
GetUserAuthenticationMethodsRequest, GetUserDetailsResponse, GetUserRoleDetailsRequest,
|
GetSsoAuthUrlRequest, GetUserAuthenticationMethodsRequest, GetUserDetailsResponse,
|
||||||
GetUserRoleDetailsResponse, InviteUserRequest, ListUsersResponse, ReInviteUserRequest,
|
GetUserRoleDetailsRequest, GetUserRoleDetailsResponse, InviteUserRequest, ListUsersResponse,
|
||||||
RecoveryCodes, ResetPasswordRequest, RotatePasswordRequest, SendVerifyEmailRequest,
|
ReInviteUserRequest, RecoveryCodes, ResetPasswordRequest, RotatePasswordRequest,
|
||||||
SignInResponse, SignUpRequest, SignUpWithMerchantIdRequest, SsoSignInRequest,
|
SendVerifyEmailRequest, SignInResponse, SignUpRequest, SignUpWithMerchantIdRequest,
|
||||||
SwitchMerchantIdRequest, TokenOrPayloadResponse, TokenResponse, TwoFactorAuthStatusResponse,
|
SsoSignInRequest, SwitchMerchantIdRequest, TokenOrPayloadResponse, TokenResponse,
|
||||||
UpdateUserAccountDetailsRequest, UpdateUserAuthenticationMethodRequest, UserFromEmailRequest,
|
TwoFactorAuthStatusResponse, UpdateUserAccountDetailsRequest,
|
||||||
UserMerchantCreate, VerifyEmailRequest, VerifyRecoveryCodeRequest, VerifyTotpRequest,
|
UpdateUserAuthenticationMethodRequest, UserFromEmailRequest, UserMerchantCreate,
|
||||||
|
VerifyEmailRequest, VerifyRecoveryCodeRequest, VerifyTotpRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ApiEventMetric for DashboardEntryResponse {
|
impl ApiEventMetric for DashboardEntryResponse {
|
||||||
@ -83,7 +84,8 @@ common_utils::impl_misc_api_event_type!(
|
|||||||
CreateUserAuthenticationMethodRequest,
|
CreateUserAuthenticationMethodRequest,
|
||||||
UpdateUserAuthenticationMethodRequest,
|
UpdateUserAuthenticationMethodRequest,
|
||||||
GetSsoAuthUrlRequest,
|
GetSsoAuthUrlRequest,
|
||||||
SsoSignInRequest
|
SsoSignInRequest,
|
||||||
|
AuthSelectRequest
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
|
|||||||
@ -372,3 +372,8 @@ pub struct SsoSignInRequest {
|
|||||||
pub struct AuthIdQueryParam {
|
pub struct AuthIdQueryParam {
|
||||||
pub auth_id: Option<String>,
|
pub auth_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct AuthSelectRequest {
|
||||||
|
pub id: String,
|
||||||
|
}
|
||||||
|
|||||||
@ -2312,3 +2312,41 @@ pub async fn sso_sign(
|
|||||||
|
|
||||||
auth::cookies::set_cookie_response(response, token)
|
auth::cookies::set_cookie_response(response, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn terminate_auth_select(
|
||||||
|
state: SessionState,
|
||||||
|
user_token: auth::UserFromSinglePurposeToken,
|
||||||
|
req: user_api::AuthSelectRequest,
|
||||||
|
) -> UserResponse<user_api::TokenResponse> {
|
||||||
|
let user_from_db: domain::UserFromStorage = state
|
||||||
|
.global_store
|
||||||
|
.find_user_by_id(&user_token.user_id)
|
||||||
|
.await
|
||||||
|
.change_context(UserErrors::InternalServerError)?
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let user_authentication_method = state
|
||||||
|
.store
|
||||||
|
.get_user_authentication_method_by_id(&req.id)
|
||||||
|
.await
|
||||||
|
.change_context(UserErrors::InternalServerError)?;
|
||||||
|
|
||||||
|
let current_flow = domain::CurrentFlow::new(user_token, domain::SPTFlow::AuthSelect.into())?;
|
||||||
|
let mut next_flow = current_flow.next(user_from_db.clone(), &state).await?;
|
||||||
|
|
||||||
|
// Skip SSO if continue with password(TOTP)
|
||||||
|
if next_flow.get_flow() == domain::UserFlow::SPTFlow(domain::SPTFlow::SSO)
|
||||||
|
&& user_authentication_method.auth_type != common_enums::UserAuthType::OpenIdConnect
|
||||||
|
{
|
||||||
|
next_flow = next_flow.skip(user_from_db, &state).await?;
|
||||||
|
}
|
||||||
|
let token = next_flow.get_token(&state).await?;
|
||||||
|
|
||||||
|
auth::cookies::set_cookie_response(
|
||||||
|
user_api::TokenResponse {
|
||||||
|
token: token.clone(),
|
||||||
|
token_type: next_flow.get_flow().into(),
|
||||||
|
},
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
@ -1417,7 +1417,8 @@ impl User {
|
|||||||
.service(
|
.service(
|
||||||
web::resource("/list").route(web::get().to(list_user_authentication_methods)),
|
web::resource("/list").route(web::get().to(list_user_authentication_methods)),
|
||||||
)
|
)
|
||||||
.service(web::resource("/url").route(web::get().to(get_sso_auth_url))),
|
.service(web::resource("/url").route(web::get().to(get_sso_auth_url)))
|
||||||
|
.service(web::resource("/select").route(web::post().to(terminate_auth_select))),
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
|
|||||||
@ -232,7 +232,8 @@ impl From<Flow> for ApiIdentifier {
|
|||||||
| Flow::UpdateUserAuthenticationMethod
|
| Flow::UpdateUserAuthenticationMethod
|
||||||
| Flow::ListUserAuthenticationMethods
|
| Flow::ListUserAuthenticationMethods
|
||||||
| Flow::GetSsoAuthUrl
|
| Flow::GetSsoAuthUrl
|
||||||
| Flow::SignInWithSso => Self::User,
|
| Flow::SignInWithSso
|
||||||
|
| Flow::AuthSelect => Self::User,
|
||||||
|
|
||||||
Flow::ListRoles
|
Flow::ListRoles
|
||||||
| Flow::GetRole
|
| Flow::GetRole
|
||||||
|
|||||||
@ -876,3 +876,22 @@ pub async fn list_user_authentication_methods(
|
|||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn terminate_auth_select(
|
||||||
|
state: web::Data<AppState>,
|
||||||
|
req: HttpRequest,
|
||||||
|
json_payload: web::Json<user_api::AuthSelectRequest>,
|
||||||
|
) -> HttpResponse {
|
||||||
|
let flow = Flow::AuthSelect;
|
||||||
|
|
||||||
|
Box::pin(api::server_wrap(
|
||||||
|
flow,
|
||||||
|
state.clone(),
|
||||||
|
&req,
|
||||||
|
json_payload.into_inner(),
|
||||||
|
|state, user, req, _| user_core::terminate_auth_select(state, user, req),
|
||||||
|
&auth::SinglePurposeJWTAuth(TokenPurpose::AuthSelect),
|
||||||
|
api_locking::LockAction::NotApplicable,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|||||||
@ -51,9 +51,8 @@ impl SPTFlow {
|
|||||||
) -> UserResult<bool> {
|
) -> UserResult<bool> {
|
||||||
match self {
|
match self {
|
||||||
// Auth
|
// Auth
|
||||||
// AuthSelect and SSO flow are not enabled, once the terminate SSO API is ready, we can enable these flows
|
Self::AuthSelect => Ok(true),
|
||||||
Self::AuthSelect => Ok(false),
|
Self::SSO => Ok(true),
|
||||||
Self::SSO => Ok(false),
|
|
||||||
// TOTP
|
// TOTP
|
||||||
Self::TOTP => Ok(!path.contains(&TokenPurpose::SSO)),
|
Self::TOTP => Ok(!path.contains(&TokenPurpose::SSO)),
|
||||||
// Main email APIs
|
// Main email APIs
|
||||||
@ -311,6 +310,26 @@ impl NextFlow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn skip(self, user: UserFromStorage, state: &SessionState) -> UserResult<Self> {
|
||||||
|
let flows = self.origin.get_flows();
|
||||||
|
let index = flows
|
||||||
|
.iter()
|
||||||
|
.position(|flow| flow == &self.get_flow())
|
||||||
|
.ok_or(UserErrors::InternalServerError)?;
|
||||||
|
let remaining_flows = flows.iter().skip(index + 1);
|
||||||
|
for flow in remaining_flows {
|
||||||
|
if flow.is_required(&user, &self.path, state).await? {
|
||||||
|
return Ok(Self {
|
||||||
|
origin: self.origin.clone(),
|
||||||
|
next_flow: *flow,
|
||||||
|
user,
|
||||||
|
path: self.path,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(UserErrors::InternalServerError.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<UserFlow> for TokenPurpose {
|
impl From<UserFlow> for TokenPurpose {
|
||||||
|
|||||||
@ -155,7 +155,7 @@ pub enum Flow {
|
|||||||
PaymentsStart,
|
PaymentsStart,
|
||||||
/// Payments list flow.
|
/// Payments list flow.
|
||||||
PaymentsList,
|
PaymentsList,
|
||||||
// Payments filters flow
|
/// Payments filters flow
|
||||||
PaymentsFilters,
|
PaymentsFilters,
|
||||||
#[cfg(feature = "payouts")]
|
#[cfg(feature = "payouts")]
|
||||||
/// Payouts create flow
|
/// Payouts create flow
|
||||||
@ -412,7 +412,7 @@ pub enum Flow {
|
|||||||
UserFromEmail,
|
UserFromEmail,
|
||||||
/// Begin TOTP
|
/// Begin TOTP
|
||||||
TotpBegin,
|
TotpBegin,
|
||||||
// Reset TOTP
|
/// Reset TOTP
|
||||||
TotpReset,
|
TotpReset,
|
||||||
/// Verify TOTP
|
/// Verify TOTP
|
||||||
TotpVerify,
|
TotpVerify,
|
||||||
@ -422,20 +422,22 @@ pub enum Flow {
|
|||||||
RecoveryCodeVerify,
|
RecoveryCodeVerify,
|
||||||
/// Generate or Regenerate recovery codes
|
/// Generate or Regenerate recovery codes
|
||||||
RecoveryCodesGenerate,
|
RecoveryCodesGenerate,
|
||||||
// Terminate two factor authentication
|
/// Terminate two factor authentication
|
||||||
TerminateTwoFactorAuth,
|
TerminateTwoFactorAuth,
|
||||||
// Check 2FA status
|
/// Check 2FA status
|
||||||
TwoFactorAuthStatus,
|
TwoFactorAuthStatus,
|
||||||
// Create user authentication method
|
/// Create user authentication method
|
||||||
CreateUserAuthenticationMethod,
|
CreateUserAuthenticationMethod,
|
||||||
// Update user authentication method
|
/// Update user authentication method
|
||||||
UpdateUserAuthenticationMethod,
|
UpdateUserAuthenticationMethod,
|
||||||
// List user authentication methods
|
/// List user authentication methods
|
||||||
ListUserAuthenticationMethods,
|
ListUserAuthenticationMethods,
|
||||||
/// Get sso auth url
|
/// Get sso auth url
|
||||||
GetSsoAuthUrl,
|
GetSsoAuthUrl,
|
||||||
/// Signin with SSO
|
/// Signin with SSO
|
||||||
SignInWithSso,
|
SignInWithSso,
|
||||||
|
/// Auth Select
|
||||||
|
AuthSelect,
|
||||||
/// List initial webhook delivery attempts
|
/// List initial webhook delivery attempts
|
||||||
WebhookEventInitialDeliveryAttemptList,
|
WebhookEventInitialDeliveryAttemptList,
|
||||||
/// List delivery attempts for a webhook event
|
/// List delivery attempts for a webhook event
|
||||||
|
|||||||
Reference in New Issue
Block a user