hive_client/client/authentication/challenge/
mod.rs1use crate::AuthenticationError;
2use crate::authentication::user::UntrustedDevice;
3use crate::client::authentication::{HiveAuth, Tokens};
4use aws_sdk_cognitoidentityprovider::operation::respond_to_auth_challenge::RespondToAuthChallengeOutput;
5use aws_sdk_cognitoidentityprovider::types::{
6 AuthenticationResultType, ChallengeNameType, NewDeviceMetadataType,
7};
8use std::collections::HashMap;
9use std::fmt::Debug;
10
11mod device_password_verifier;
12mod device_srp_auth;
13mod password_verifier;
14mod sms_mfa;
15
16#[derive(Debug)]
17#[non_exhaustive]
18pub enum ChallengeRequest {
21 SmsMfa,
27
28 #[doc(hidden)]
32 PasswordVerifier,
33
34 Unsupported(String),
37}
38
39#[derive(Debug)]
40#[non_exhaustive]
41pub enum ChallengeResponse {
43 SmsMfa(String),
46 #[doc(hidden)]
47 PasswordVerifier(HashMap<String, String>),
48 #[doc(hidden)]
49 DeviceSrpAuth,
50 #[doc(hidden)]
51 DevicePasswordVerifier(HashMap<String, String>),
52}
53
54impl HiveAuth {
55 pub(crate) async fn respond_to_challenge(
56 &self,
57 challenge_response: ChallengeResponse,
58 ) -> Result<(Tokens, Option<UntrustedDevice>), AuthenticationError> {
59 let response = {
60 let mut session = self.session.write().await;
61 let session = session
62 .as_mut()
63 .ok_or(AuthenticationError::NoAuthenticationInProgress)?;
64
65 log::info!(
66 "Responding to challenge with response: {:?}",
67 &challenge_response
68 );
69
70 let response = match challenge_response {
71 ChallengeResponse::PasswordVerifier(parameters) => {
72 password_verifier::respond_to_challenge(
73 &self.cognito,
74 &self.user_srp_client,
75 self.device_srp_client.as_ref(),
76 session,
77 parameters,
78 )
79 .await?
80 }
81 ChallengeResponse::DeviceSrpAuth => {
82 device_srp_auth::handle_challenge(
83 &self.cognito,
84 self.device_srp_client
85 .as_ref()
86 .ok_or(AuthenticationError::NoAuthenticationInProgress)?,
87 session,
88 )
89 .await?
90 }
91 ChallengeResponse::DevicePasswordVerifier(parameters) => {
92 device_password_verifier::handle_challenge(
93 &self.cognito,
94 self.device_srp_client
95 .as_ref()
96 .ok_or(AuthenticationError::NoAuthenticationInProgress)?,
97 session,
98 parameters,
99 )
100 .await?
101 }
102 ChallengeResponse::SmsMfa(code) => {
103 sms_mfa::handle_challenge(
104 &self.cognito,
105 self.device_srp_client.as_ref(),
106 session,
107 &code,
108 )
109 .await?
110 }
111 };
112
113 session.1.clone_from(&response.session);
116
117 response
118 };
119
120 self.handle_challenge_response(response).await
121 }
122
123 async fn handle_challenge_response(
124 &self,
125 response: RespondToAuthChallengeOutput,
126 ) -> Result<(Tokens, Option<UntrustedDevice>), AuthenticationError> {
127 match &response.challenge_name {
128 None => {
129 if let Some(AuthenticationResultType {
130 id_token: Some(id_token),
131 access_token: Some(access_token),
132 refresh_token: Some(refresh_token),
133 expires_in,
134 new_device_metadata,
135 ..
136 }) = response.authentication_result
137 {
138 let mut untrusted_device: Option<UntrustedDevice> = None;
139 if let Some(NewDeviceMetadataType {
140 device_key: Some(device_key),
141 device_group_key: Some(device_group_key),
142 ..
143 }) = new_device_metadata
144 {
145 untrusted_device =
146 Some(UntrustedDevice::new(&device_group_key, &device_key));
147 }
148
149 Ok((
150 Tokens::new(id_token, access_token, refresh_token, expires_in),
151 untrusted_device,
152 ))
153 } else {
154 Err(AuthenticationError::InvalidAccessToken)
155 }
156 }
157 Some(ChallengeNameType::DeviceSrpAuth) => {
158 Box::pin(self.respond_to_challenge(ChallengeResponse::DeviceSrpAuth)).await
159 }
160 Some(ChallengeNameType::DevicePasswordVerifier) => {
161 Box::pin(
162 self.respond_to_challenge(ChallengeResponse::DevicePasswordVerifier(
163 response.challenge_parameters.unwrap_or_default(),
164 )),
165 )
166 .await
167 }
168 Some(ChallengeNameType::SmsMfa) => {
169 Err(AuthenticationError::NextChallenge(ChallengeRequest::SmsMfa))
170 }
171 Some(name) => Err(AuthenticationError::UnsupportedChallenge(name.to_string())),
172 }
173 }
174}