Allow nonces in OAuth code requests

This commit is contained in:
mdecimus
2024-10-07 10:53:18 +02:00
parent 33a59cd8ef
commit cf093c061b
3 changed files with 29 additions and 16 deletions

View File

@@ -82,6 +82,7 @@ impl OAuthApiHandler for Server {
OAuthCodeRequest::Code { OAuthCodeRequest::Code {
client_id, client_id,
redirect_uri, redirect_uri,
nonce,
} => { } => {
// Validate clientId // Validate clientId
if client_id.len() > CLIENT_ID_MAX_LEN { if client_id.len() > CLIENT_ID_MAX_LEN {
@@ -109,6 +110,7 @@ impl OAuthApiHandler for Server {
status: OAuthStatus::Authorized, status: OAuthStatus::Authorized,
account_id: access_token.primary_id(), account_id: access_token.primary_id(),
client_id, client_id,
nonce,
params: redirect_uri.unwrap_or_default(), params: redirect_uri.unwrap_or_default(),
}) })
.serialize(); .serialize();
@@ -189,8 +191,8 @@ impl OAuthApiHandler for Server {
session: HttpSessionData, session: HttpSessionData,
) -> trc::Result<HttpResponse> { ) -> trc::Result<HttpResponse> {
// Parse form // Parse form
let client_id = FormData::from_request(req, MAX_POST_LEN, session.session_id) let mut form_data = FormData::from_request(req, MAX_POST_LEN, session.session_id).await?;
.await? let client_id = form_data
.remove("client_id") .remove("client_id")
.filter(|client_id| client_id.len() <= CLIENT_ID_MAX_LEN) .filter(|client_id| client_id.len() <= CLIENT_ID_MAX_LEN)
.ok_or_else(|| { .ok_or_else(|| {
@@ -198,6 +200,7 @@ impl OAuthApiHandler for Server {
.into_err() .into_err()
.details("Client ID is missing.") .details("Client ID is missing.")
})?; })?;
let nonce = form_data.remove("nonce");
// Generate device code // Generate device code
let device_code = thread_rng() let device_code = thread_rng()
@@ -225,6 +228,7 @@ impl OAuthApiHandler for Server {
status: OAuthStatus::Pending, status: OAuthStatus::Pending,
account_id: u32::MAX, account_id: u32::MAX,
client_id, client_id,
nonce,
params: device_code.clone(), params: device_code.clone(),
}) })
.serialize(); .serialize();

View File

@@ -40,6 +40,7 @@ pub struct OAuthCode {
pub status: OAuthStatus, pub status: OAuthStatus,
pub account_id: u32, pub account_id: u32,
pub client_id: String, pub client_id: String,
pub nonce: Option<String>,
pub params: String, pub params: String,
} }
@@ -146,6 +147,8 @@ pub enum OAuthCodeRequest {
Code { Code {
client_id: String, client_id: String,
redirect_uri: Option<String>, redirect_uri: Option<String>,
#[serde(default)]
nonce: Option<String>,
}, },
Device { Device {
code: String, code: String,

View File

@@ -43,6 +43,7 @@ pub trait TokenHandler: Sync + Send {
issuer: String, issuer: String,
nonce: Option<String>, nonce: Option<String>,
with_refresh_token: bool, with_refresh_token: bool,
with_id_token: bool,
) -> impl Future<Output = trc::Result<OAuthResponse>> + Send; ) -> impl Future<Output = trc::Result<OAuthResponse>> + Send;
} }
@@ -64,11 +65,10 @@ impl TokenHandler for Server {
.await; .await;
if grant_type.eq_ignore_ascii_case("authorization_code") { if grant_type.eq_ignore_ascii_case("authorization_code") {
response = if let (Some(code), Some(client_id), Some(redirect_uri), nonce) = ( response = if let (Some(code), Some(client_id), Some(redirect_uri)) = (
params.get("code"), params.get("code"),
params.get("client_id"), params.get("client_id"),
params.get("redirect_uri"), params.get("redirect_uri"),
params.get("nonce"),
) { ) {
// Obtain code // Obtain code
match self match self
@@ -106,7 +106,8 @@ impl TokenHandler for Server {
oauth.account_id, oauth.account_id,
&oauth.client_id, &oauth.client_id,
issuer, issuer,
nonce.map(Into::into), oauth.nonce,
true,
true, true,
) )
.await .await
@@ -130,11 +131,9 @@ impl TokenHandler for Server {
} else if grant_type.eq_ignore_ascii_case("urn:ietf:params:oauth:grant-type:device_code") { } else if grant_type.eq_ignore_ascii_case("urn:ietf:params:oauth:grant-type:device_code") {
response = TokenResponse::error(ErrorType::ExpiredToken); response = TokenResponse::error(ErrorType::ExpiredToken);
if let (Some(device_code), Some(client_id), nonce) = ( if let (Some(device_code), Some(client_id)) =
params.get("device_code"), (params.get("device_code"), params.get("client_id"))
params.get("client_id"), {
params.get("nonce"),
) {
// Obtain code // Obtain code
if let Some(auth_code) = self if let Some(auth_code) = self
.core .core
@@ -167,7 +166,8 @@ impl TokenHandler for Server {
oauth.account_id, oauth.account_id,
&oauth.client_id, &oauth.client_id,
issuer, issuer,
nonce.map(Into::into), oauth.nonce,
true,
true, true,
) )
.await .await
@@ -204,6 +204,7 @@ impl TokenHandler for Server {
None, None,
token_info.expires_in token_info.expires_in
<= self.core.oauth.oauth_expiry_refresh_token_renew, <= self.core.oauth.oauth_expiry_refresh_token_renew,
false,
) )
.await .await
.map(TokenResponse::Granted) .map(TokenResponse::Granted)
@@ -265,6 +266,7 @@ impl TokenHandler for Server {
issuer: String, issuer: String,
nonce: Option<String>, nonce: Option<String>,
with_refresh_token: bool, with_refresh_token: bool,
with_id_token: bool,
) -> trc::Result<OAuthResponse> { ) -> trc::Result<OAuthResponse> {
Ok(OAuthResponse { Ok(OAuthResponse {
access_token: self access_token: self
@@ -289,12 +291,16 @@ impl TokenHandler for Server {
} else { } else {
None None
}, },
id_token: match self.issue_id_token(account_id.to_string(), issuer, client_id, nonce) { id_token: if with_id_token {
Ok(id_token) => Some(id_token), match self.issue_id_token(account_id.to_string(), issuer, client_id, nonce) {
Err(err) => { Ok(id_token) => Some(id_token),
trc::error!(err); Err(err) => {
None trc::error!(err);
None
}
} }
} else {
None
}, },
scope: None, scope: None,
}) })