From 6da087e17f4693642215eb170334354b040b4bcd Mon Sep 17 00:00:00 2001 From: Brent Schroeter Date: Mon, 21 Apr 2025 21:43:20 -0700 Subject: [PATCH] fix slack bot installation bugs --- src/slack_auth.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/slack_auth.rs b/src/slack_auth.rs index fc6c46e..dba1477 100644 --- a/src/slack_auth.rs +++ b/src/slack_auth.rs @@ -105,6 +105,7 @@ async fn start_login( }; const SCOPE_CHANNELS_READ: &str = "channels:read"; + const SCOPE_CHAT_WRITE: &str = "chat:write"; const SCOPE_CHAT_WRITE_PUBLIC: &str = "chat:write.public"; let (auth_url, _csrf_token) = app_state @@ -112,6 +113,8 @@ async fn start_login( .authorize_url(|| csrf_token) .add_scopes([ oauth2::Scope::new(SCOPE_CHANNELS_READ.to_owned()), + // chat:write must be added in order to add chat:write.public + oauth2::Scope::new(SCOPE_CHAT_WRITE.to_owned()), oauth2::Scope::new(SCOPE_CHAT_WRITE_PUBLIC.to_owned()), ]) .set_redirect_uri(Cow::Owned( @@ -139,9 +142,9 @@ async fn start_login( #[derive(Debug, Deserialize)] struct AuthRequestQuery { - code: String, - /// CSRF token - state: String, + code: Option, + state: Option, + error: Option, } /// HTTP get handler for /callback @@ -173,6 +176,23 @@ async fn callback( .await .unwrap()?; + if let Some(message) = query.error { + tracing::warn!("slack oauth error: {}", message); + // This likely indicates that the user has pressed the "Return to + // Shout.dev" button in the Slack OAuth flow. + return Ok(Redirect::to(&format!( + "{}/en/teams/{}/channels/{}", + base_path, team_id, channel_id + ))); + } + + let oauth_code = query.code.ok_or(AppError::BadRequest( + "OAuth code from Slack is missing.".to_owned(), + ))?; + let oauth_state = query.state.ok_or(AppError::BadRequest( + "OAuth state from Slack is missing.".to_owned(), + ))?; + let slack_data: SlackBackendConfig = channel .backend_config .try_into() @@ -181,7 +201,7 @@ async fn callback( let true_csrf_token = slack_data.oauth_state.ok_or(AppError::BadRequest( "No active Slack auth flow.".to_owned(), ))?; - if true_csrf_token.secret() != &query.state { + if true_csrf_token.secret() != &oauth_state { tracing::debug!("oauth csrf tokens did not match"); return Err(AppError::Forbidden( "Slack OAuth CSRF tokens do not match.".to_owned(), @@ -191,7 +211,7 @@ async fn callback( tracing::debug!("exchanging authorization code"); let response = app_state .slack_oauth_client - .exchange_code(AuthorizationCode::new(query.code)) + .exchange_code(AuthorizationCode::new(oauth_code)) .set_redirect_uri(Cow::Owned( RedirectUrl::new(format!( "{}{}/en/teams/{}/channels/{}/slack-auth/callback",