fix: add more oauth2 checks
This commit is contained in:
@@ -49,6 +49,7 @@ auto_derived_partial!(
|
|||||||
|
|
||||||
auto_derived!(
|
auto_derived!(
|
||||||
#[derive(Copy, Hash)]
|
#[derive(Copy, Hash)]
|
||||||
|
#[serde(rename = "lowercase")]
|
||||||
pub enum OAuth2Scope {
|
pub enum OAuth2Scope {
|
||||||
Identify,
|
Identify,
|
||||||
Full,
|
Full,
|
||||||
|
|||||||
@@ -124,3 +124,13 @@ pub async fn add_code_challange(token: &str, code_challenge: &str) -> Result<()>
|
|||||||
|
|
||||||
Ok(())
|
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))
|
||||||
|
}
|
||||||
@@ -77,6 +77,7 @@ auto_derived!(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Hash)]
|
#[derive(Copy, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", serde(rename = "lowercase"))]
|
||||||
pub enum OAuth2Scope {
|
pub enum OAuth2Scope {
|
||||||
Identify,
|
Identify,
|
||||||
Full,
|
Full,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use revolt_database::BotOauth2;
|
|
||||||
use revolt_database::{util::reference::Reference, Database, PartialBot, User};
|
use revolt_database::{util::reference::Reference, Database, PartialBot, User};
|
||||||
use revolt_models::v0::{self, DataEditBot};
|
use revolt_models::v0::{self, DataEditBot};
|
||||||
use revolt_result::{create_error, Result};
|
use revolt_result::{create_error, Result};
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ pub async fn auth(
|
|||||||
user: User,
|
user: User,
|
||||||
info: v0::OAuth2AuthorizationForm,
|
info: v0::OAuth2AuthorizationForm,
|
||||||
) -> Result<Json<v0::OAuth2AuthorizeAuthResponse>> {
|
) -> Result<Json<v0::OAuth2AuthorizeAuthResponse>> {
|
||||||
|
if user.bot.is_some() {
|
||||||
|
return Err(create_error!(IsBot));
|
||||||
|
};
|
||||||
|
|
||||||
let bot = Reference::from_unchecked(info.client_id.clone())
|
let bot = Reference::from_unchecked(info.client_id.clone())
|
||||||
.as_bot(db)
|
.as_bot(db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ pub async fn info(
|
|||||||
user: User,
|
user: User,
|
||||||
info: v0::OAuth2AuthorizationForm,
|
info: v0::OAuth2AuthorizationForm,
|
||||||
) -> Result<Json<v0::OAuth2AuthorizeInfoResponse>> {
|
) -> 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 = 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 bot_user = Reference::from_unchecked(bot.id.clone()).as_user(db).await?;
|
||||||
let public_bot = bot.clone().into_public_bot(bot_user);
|
let public_bot = bot.clone().into_public_bot(bot_user);
|
||||||
|
|||||||
@@ -35,13 +35,9 @@ pub async fn token(
|
|||||||
return Err(create_error!(NotAuthenticated))
|
return Err(create_error!(NotAuthenticated))
|
||||||
}
|
}
|
||||||
} else if let Some((code_verifier, method)) = info.code_verifier.as_ref().zip(claims.code_challange_method) {
|
} else if let Some((code_verifier, method)) = info.code_verifier.as_ref().zip(claims.code_challange_method) {
|
||||||
let mut conn = redis_kiss::get_connection()
|
let Some(server_code_challenge) = oauth2::get_code_challange(&info.code).await? else {
|
||||||
.await
|
return Err(create_error!(NotAuthenticated))
|
||||||
.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 is_valid = match method {
|
let is_valid = match method {
|
||||||
v0::OAuth2CodeChallangeMethod::Plain => &server_code_challenge == code_verifier,
|
v0::OAuth2CodeChallangeMethod::Plain => &server_code_challenge == code_verifier,
|
||||||
@@ -51,6 +47,8 @@ pub async fn token(
|
|||||||
if !is_valid {
|
if !is_valid {
|
||||||
return Err(create_error!(NotAuthenticated))
|
return Err(create_error!(NotAuthenticated))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return Err(create_error!(NotAuthenticated))
|
||||||
}
|
}
|
||||||
|
|
||||||
if claims.client_id != info.client_id || claims.exp < Utc::now().timestamp() {
|
if claims.client_id != info.client_id || claims.exp < Utc::now().timestamp() {
|
||||||
@@ -81,6 +79,7 @@ pub async fn token(
|
|||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
v0::OAuth2GrantType::Implicit => {
|
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))
|
Err(create_error!(InvalidOperation))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user