pub struct AuthzCasdoorPlugin {Show 18 fields
endpoint_addr: String,
client_id: String,
client_secret: String,
basic_auth: String,
ssl_verify: bool,
timeout: Duration,
sealer: Option<CookieSealer>,
callback_url: Option<String>,
callback_path: Option<String>,
scope: String,
cookie_name: String,
flow_cookie_name: String,
cookie_path: String,
cookie_lifetime: u64,
logout_path: Option<String>,
backend: SessionBackend,
rng: SystemRandom,
outbound: Arc<OutboundClient>,
}Expand description
Validates a Casdoor access token, and in interactive mode runs the SSO flow.
Fields§
§endpoint_addr: StringCasdoor server base URL, without a trailing slash.
client_id: StringCasdoor application client id.
client_secret: StringCasdoor application client secret.
basic_auth: StringAuthorization: Basic ... header value built from the client credentials.
ssl_verify: boolTLS certificate verification for the callout.
timeout: DurationWhole-call timeout for the callout.
sealer: Option<CookieSealer>When set, interactive SSO login is enabled and this seals/opens cookies.
callback_url: Option<String>Full callback URL registered with Casdoor (the OAuth redirect_uri).
callback_path: Option<String>Path component of callback_url, matched against the request path.
scope: StringOAuth scope requested at the authorize step (default read).
Session cookie name (interactive mode).
Transient login-flow cookie name (interactive mode).
Path attribute of the session and flow cookies (interactive mode).
Scope to a subpath (e.g. /app_a) for independent per-app sessions;
must cover callback_path. Defaults to /.
Session cookie lifetime in seconds (interactive mode).
logout_path: Option<String>Optional logout path; a request to it clears the session cookie.
backend: SessionBackendWhere the session payload lives: sealed in the cookie itself, or a
server-side store keyed by a bare id in the cookie. See
session.storage / session.store in AuthzCasdoorPlugin::from_config.
rng: SystemRandomRandomness source for the anti-CSRF state.
outbound: Arc<OutboundClient>Shared pooled outbound HTTP client.
Implementations§
Source§impl AuthzCasdoorPlugin
impl AuthzCasdoorPlugin
Sourcepub fn from_config(
config: &HashMap<String, Value>,
resources: &Arc<PluginResources>,
) -> Result<Self, String>
pub fn from_config( config: &HashMap<String, Value>, resources: &Arc<PluginResources>, ) -> Result<Self, String>
Builds the plugin from node config.
Accepted keys:
endpoint_addr(string, required): Casdoor base URL (a trailing/is trimmed).client_id(string, required): Casdoor application client id.client_secret(string, required): Casdoor application client secret. Used for HTTP Basic auth on the introspection call (stateless) and the code-exchange call (interactive).callback_url(string): OAuthredirect_uri. Required in interactive mode; accepted-but-unused in stateless mode.ssl_verify(bool, defaulttrue): verify the endpoint’s TLS certificate.timeout(integer ms, default3000): callout timeout.
Interactive-mode keys (a session secret ⇒ interactive login is enabled):
session_secret(string) orsession.secret(string): signing/encryption secret for the session and flow cookies. Setting it turns on the SSO flow.session.cookie.name(string, default"casdoor_session"): session cookie name.session.cookie.path(string, default"/"): session/flow cookiePath; scope to a subpath (e.g./app_a) for independent per-app sessions. Must cover thecallback_urlpath (rejected at load otherwise).session.cookie.lifetime(u64 seconds, default3600): cookie lifetime.scope(string, default"read"): OAuth scope requested at authorize.logout_path(string, optional): request path that clears the session cookie and redirects to/.
- id: authz
type: authz-casdoor
config:
endpoint_addr: https://casdoor.example.com
client_id: ${CASDOOR_CLIENT_ID}
client_secret: ${CASDOOR_CLIENT_SECRET}
callback_url: https://app.example.com/casdoor/callback
session_secret: ${CASDOOR_SESSION_SECRET}
scope: readSourcefn deny(
ctx: Context,
message: impl Into<String>,
) -> Result<PluginOutput, PluginExecutionError>
fn deny( ctx: Context, message: impl Into<String>, ) -> Result<PluginOutput, PluginExecutionError>
Builds the 403 denial and exits on the denied port. Reserved for
deliberate denials — a missing/invalid token, OAuth state mismatch, or
Casdoor actively refusing the decision.
Sourcefn redirect(
ctx: Context,
location: String,
set_cookies: Vec<String>,
) -> Result<PluginOutput, PluginExecutionError>
fn redirect( ctx: Context, location: String, set_cookies: Vec<String>, ) -> Result<PluginOutput, PluginExecutionError>
Builds a 302 early-exit and exits on the redirect port. Wire the
node’s redirect edge to client.in so this reaches the browser.
Sourcefn callout_error(
ctx: Context,
message: String,
) -> Result<PluginOutput, PluginExecutionError>
fn callout_error( ctx: Context, message: String, ) -> Result<PluginOutput, PluginExecutionError>
Builds a genuine infrastructure-failure Err (a Casdoor token-exchange
or introspection callout that transport-failed, timed out, or returned
an unparseable response) — exits through the error port because the
node could not do its job, unlike deny/redirect which are
deliberate, client-facing outcomes. The prepared response is the shared
502 provider_error shape, not a 403 access_denied.
Sourcefn store_error(ctx: Context, e: StoreError) -> PluginExecutionError
fn store_error(ctx: Context, e: StoreError) -> PluginExecutionError
Session-store outage: 503 through the error port. Deliberately NOT 401 — a store outage is not “unauthenticated”.
Cookie attributes: HttpOnly, SameSite=Lax, Secure only over HTTPS.
Sourceasync fn read_session(
&self,
ctx: &Context,
) -> Result<Option<CasdoorSession>, StoreError>
async fn read_session( &self, ctx: &Context, ) -> Result<Option<CasdoorSession>, StoreError>
Reads the session cookie via the configured backend, returning the
sealed session. Ok(None) = unauthenticated (no cookie/sealer, or an
unopenable/unparseable payload); Err = store outage (503 via
AuthzCasdoorPlugin::store_error), never a silent re-login.
Sourcefn read_flow(&self, ctx: &Context) -> Option<CasdoorFlow>
fn read_flow(&self, ctx: &Context) -> Option<CasdoorFlow>
Reads and opens the transient login-flow cookie.
Sourcefn attach_session(&self, ctx: &mut Context, session: &CasdoorSession)
fn attach_session(&self, ctx: &mut Context, session: &CasdoorSession)
Attaches the authenticated identity from a session to the request.
Sourceasync fn fetch_access_token(&self, code: &str) -> Result<String, String>
async fn fetch_access_token(&self, code: &str) -> Result<String, String>
Exchanges an authorization code for a Casdoor access token.
Sourceasync fn execute_interactive(
&self,
ctx: Context,
) -> Result<PluginOutput, PluginExecutionError>
async fn execute_interactive( &self, ctx: Context, ) -> Result<PluginOutput, PluginExecutionError>
Interactive SSO flow: callback → valid session → begin login.
Sourcefn is_callback(&self, ctx: &Context) -> bool
fn is_callback(&self, ctx: &Context) -> bool
True when the request is the OAuth callback (path + code + state).
Sourceasync fn handle_callback(
&self,
ctx: Context,
sealer: &CookieSealer,
) -> Result<PluginOutput, PluginExecutionError>
async fn handle_callback( &self, ctx: Context, sealer: &CookieSealer, ) -> Result<PluginOutput, PluginExecutionError>
Handles the OAuth callback: verify state, exchange code, seal a session, and redirect to the original URI.
Sourcefn begin_login(
&self,
ctx: Context,
sealer: &CookieSealer,
) -> Result<PluginOutput, PluginExecutionError>
fn begin_login( &self, ctx: Context, sealer: &CookieSealer, ) -> Result<PluginOutput, PluginExecutionError>
Begins interactive login: mint a state, stash it plus the original URI
in a short-lived flow cookie, and redirect to Casdoor’s authorize URL.
Sourceasync fn execute_stateless(
&self,
ctx: Context,
) -> Result<PluginOutput, PluginExecutionError>
async fn execute_stateless( &self, ctx: Context, ) -> Result<PluginOutput, PluginExecutionError>
Stateless bearer-token validation via introspection (default behavior).
Trait Implementations§
Source§impl Plugin for AuthzCasdoorPlugin
impl Plugin for AuthzCasdoorPlugin
Source§fn plugin_type(&self) -> &str
fn plugin_type(&self) -> &str
Source§fn execute<'life0, 'async_trait>(
&'life0 self,
ctx: Context,
) -> Pin<Box<dyn Future<Output = Result<PluginOutput, PluginExecutionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn execute<'life0, 'async_trait>(
&'life0 self,
ctx: Context,
) -> Pin<Box<dyn Future<Output = Result<PluginOutput, PluginExecutionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn reads_response_body(&self) -> bool
fn reads_response_body(&self) -> bool
context.response.body. Read moreSource§fn cache_target(&self) -> Option<CacheTarget>
fn cache_target(&self) -> Option<CacheTarget>
proxy-cache half. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for AuthzCasdoorPlugin
impl !UnwindSafe for AuthzCasdoorPlugin
impl Freeze for AuthzCasdoorPlugin
impl Send for AuthzCasdoorPlugin
impl Sync for AuthzCasdoorPlugin
impl Unpin for AuthzCasdoorPlugin
impl UnsafeUnpin for AuthzCasdoorPlugin
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more