diff --git a/crates/core/src/handlers/oauth2/authorization.rs b/crates/core/src/handlers/oauth2/authorization.rs index f0c5906b..d020881e 100644 --- a/crates/core/src/handlers/oauth2/authorization.rs +++ b/crates/core/src/handlers/oauth2/authorization.rs @@ -29,10 +29,10 @@ use mas_data_model::{ }; use mas_templates::{FormPostContext, Templates}; use oauth2_types::{ - errors::{ErrorResponse, InvalidGrant, InvalidRequest, OAuth2Error}, + errors::{ErrorResponse, InvalidGrant, InvalidRequest, LoginRequired, OAuth2Error}, pkce, requests::{ - AccessTokenResponse, AuthorizationRequest, AuthorizationResponse, ResponseMode, + AccessTokenResponse, AuthorizationRequest, AuthorizationResponse, Prompt, ResponseMode, ResponseType, }, scope::ScopeToken, @@ -389,17 +389,37 @@ async fn get( let next = ContinueAuthorizationGrant::from_authorization_grant(grant); - if let Some(user_session) = maybe_session { - step(next, user_session, txn).await - } else { - // If not, redirect the user to the login page - txn.commit().await.wrap_error()?; + match (maybe_session, params.auth.prompt) { + (None, Some(Prompt::None)) => { + // If there is no session and prompt=none was asked, go back to the client + txn.commit().await.wrap_error()?; + Ok(ReplyOrBackToClient::Error(Box::new(LoginRequired))) + } + (Some(_), Some(Prompt::Login | Prompt::Consent | Prompt::SelectAccount)) => { + // We're already logged in but login|consent|select_account was asked, reauth + // TODO: better pages here + txn.commit().await.wrap_error()?; - let next: PostAuthAction<_> = next.into(); - let next: LoginRequest<_> = next.into(); - let next = next.build_uri().wrap_error()?; + let next: PostAuthAction<_> = next.into(); + let next: ReauthRequest<_> = next.into(); + let next = next.build_uri().wrap_error()?; - Ok(ReplyOrBackToClient::Reply(Box::new(see_other(next)))) + Ok(ReplyOrBackToClient::Reply(Box::new(see_other(next)))) + } + (Some(user_session), _) => { + // Other cases where we already have a session + step(next, user_session, txn).await + } + (None, _) => { + // Other cases where we don't have a session, ask for a login + txn.commit().await.wrap_error()?; + + let next: PostAuthAction<_> = next.into(); + let next: LoginRequest<_> = next.into(); + let next = next.build_uri().wrap_error()?; + + Ok(ReplyOrBackToClient::Reply(Box::new(see_other(next)))) + } } } diff --git a/crates/oauth2-types/src/errors.rs b/crates/oauth2-types/src/errors.rs index 918aed5e..6d23c63f 100644 --- a/crates/oauth2-types/src/errors.rs +++ b/crates/oauth2-types/src/errors.rs @@ -252,6 +252,62 @@ pub mod rfc6749 { } } +pub mod oidc_core { + + oauth2_error! { + InteractionRequired, + "interaction_required" => + "The Authorization Server requires End-User interaction of some form to proceed." + } + + oauth2_error! { + LoginRequired, + "login_required" => + "The Authorization Server requires End-User authentication." + } + + oauth2_error! { + AccountSelectionRequired, + "account_selection_required" + } + + oauth2_error! { + ConsentRequired, + "consent_required" + } + + oauth2_error! { + InvalidRequestUri, + "invalid_request_uri" => + "The request_uri in the Authorization Request returns an error or contains invalid data. " + } + + oauth2_error! { + InvalidRequestObject, + "invalid_request_object" => + "The request parameter contains an invalid Request Object." + } + + oauth2_error! { + RequestNotSupported, + "request_not_supported" => + "The provider does not support use of the request parameter." + } + + oauth2_error! { + RequestUriNotSupported, + "request_uri_not_supported" => + "The provider does not support use of the request_uri parameter." + } + + oauth2_error! { + RegistrationNotSupported, + "registration_not_supported" => + "The provider does not support use of the registration parameter." + } +} + +pub use oidc_core::*; pub use rfc6749::*; #[cfg(test)] diff --git a/crates/oauth2-types/src/requests.rs b/crates/oauth2-types/src/requests.rs index 770b9675..c7ae41a3 100644 --- a/crates/oauth2-types/src/requests.rs +++ b/crates/oauth2-types/src/requests.rs @@ -168,6 +168,8 @@ pub struct AuthorizationRequest { display: Option, + pub prompt: Option, + #[serde(default)] #[serde_as(as = "Option")] pub max_age: Option,