| 302 | } |
| 303 | |
| 304 | pub fn parse_oauth_callback_query(query: &str) -> Result<OAuthCallbackParams, String> { |
| 305 | let mut params = BTreeMap::new(); |
| 306 | for pair in query.split('&').filter(|pair| !pair.is_empty()) { |
| 307 | let (key, value) = pair |
| 308 | .split_once('=') |
| 309 | .map_or((pair, ""), |(key, value)| (key, value)); |
| 310 | params.insert(percent_decode(key)?, percent_decode(value)?); |
| 311 | } |
| 312 | Ok(OAuthCallbackParams { |
| 313 | code: params.get("code").cloned(), |
| 314 | state: params.get("state").cloned(), |
| 315 | error: params.get("error").cloned(), |
| 316 | error_description: params.get("error_description").cloned(), |
| 317 | }) |
| 318 | } |
| 319 | |
| 320 | fn generate_random_token(bytes: usize) -> io::Result<String> { |
| 321 | let mut buffer = vec![0_u8; bytes]; |