fix: add more oauth2 checks

This commit is contained in:
Zomatree
2025-06-29 01:12:24 +01:00
parent 11eee02cfe
commit 5a5f84f207
7 changed files with 26 additions and 8 deletions

View File

@@ -49,6 +49,7 @@ auto_derived_partial!(
auto_derived!(
#[derive(Copy, Hash)]
#[serde(rename = "lowercase")]
pub enum OAuth2Scope {
Identify,
Full,

View File

@@ -123,4 +123,14 @@ pub async fn add_code_challange(token: &str, code_challenge: &str) -> Result<()>
.map_err(|_| create_error!(InternalError))?;
Ok(())
}
pub async fn get_code_challange(token: &str) -> Result<Option<String>> {
let mut conn = redis_kiss::get_connection()
.await
.map_err(|_| create_error!(InternalError))?;
conn.get(format!("oauth2:{token}:code_challenge"))
.await
.map_err(|_| create_error!(InternalError))
}

View File

@@ -77,6 +77,7 @@ auto_derived!(
}
#[derive(Copy, Hash)]
#[cfg_attr(feature = "serde", serde(rename = "lowercase"))]
pub enum OAuth2Scope {
Identify,
Full,

View File

@@ -1,4 +1,3 @@
use revolt_database::BotOauth2;
use revolt_database::{util::reference::Reference, Database, PartialBot, User};
use revolt_models::v0::{self, DataEditBot};
use revolt_result::{create_error, Result};

View File

@@ -17,6 +17,10 @@ pub async fn auth(
user: User,
info: v0::OAuth2AuthorizationForm,
) -> Result<Json<v0::OAuth2AuthorizeAuthResponse>> {
if user.bot.is_some() {
return Err(create_error!(IsBot));
};
let bot = Reference::from_unchecked(info.client_id.clone())
.as_bot(db)
.await?;

View File

@@ -13,6 +13,10 @@ pub async fn info(
user: User,
info: v0::OAuth2AuthorizationForm,
) -> Result<Json<v0::OAuth2AuthorizeInfoResponse>> {
if user.bot.is_some() {
return Err(create_error!(IsBot));
};
let bot = Reference::from_unchecked(info.client_id.to_string()).as_bot(db).await?;
let bot_user = Reference::from_unchecked(bot.id.clone()).as_user(db).await?;
let public_bot = bot.clone().into_public_bot(bot_user);

View File

@@ -35,13 +35,9 @@ pub async fn token(
return Err(create_error!(NotAuthenticated))
}
} else if let Some((code_verifier, method)) = info.code_verifier.as_ref().zip(claims.code_challange_method) {
let mut conn = redis_kiss::get_connection()
.await
.map_err(|_| create_error!(InternalError))?;
let server_code_challenge = conn.get::<_, String>(format!("oauth2:{}:code_challenge", &info.code))
.await
.map_err(|_| create_error!(InternalError))?;
let Some(server_code_challenge) = oauth2::get_code_challange(&info.code).await? else {
return Err(create_error!(NotAuthenticated))
};
let is_valid = match method {
v0::OAuth2CodeChallangeMethod::Plain => &server_code_challenge == code_verifier,
@@ -51,6 +47,8 @@ pub async fn token(
if !is_valid {
return Err(create_error!(NotAuthenticated))
}
} else {
return Err(create_error!(NotAuthenticated))
}
if claims.client_id != info.client_id || claims.exp < Utc::now().timestamp() {
@@ -81,6 +79,7 @@ pub async fn token(
}))
},
v0::OAuth2GrantType::Implicit => {
// token is already an access token so this endpoint does not need to be called - in theory this should be unreachable
Err(create_error!(InvalidOperation))
}
}