Allow local access tokens to be used with OIDC backends (closes #1311 closes stalwartlabs/webadmin#52)

This commit is contained in:
mdecimus
2025-07-25 21:06:23 +02:00
parent 02f6a114e0
commit 654f296d45
37 changed files with 369 additions and 278 deletions

View File

@@ -4,16 +4,15 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use std::sync::Arc;
use common::auth::AccessToken;
use common::{HttpAuthCache, Server, auth::AuthRequest, listener::limiter::InFlight};
use http_proto::{HttpRequest, HttpSessionData};
use hyper::header;
use mail_parser::decoders::base64::base64_decode;
use mail_send::Credentials;
use common::auth::AccessToken;
use std::future::Future;
use std::sync::Arc;
use std::time::{Duration, Instant};
pub trait Authenticator: Sync + Send {
fn authenticate_headers(
@@ -34,19 +33,20 @@ impl Authenticator for Server {
if let Some((mechanism, token)) = req.authorization() {
// Check if the credentials are cached
if let Some(http_cache) = self.inner.cache.http_auth.get(token) {
let access_token = self.get_access_token(http_cache.account_id).await?;
// Make sure the revision is still valid
if access_token.revision == http_cache.revision {
// Enforce authenticated rate limit
return self
.is_http_authenticated_request_allowed(&access_token)
.await
.map(|in_flight| (in_flight, access_token));
} else {
// If the revision is not valid, remove the cached credentials
self.inner.cache.http_auth.remove(token);
if http_cache.expires <= Instant::now() {
let access_token = self.get_access_token(http_cache.account_id).await?;
if access_token.revision == http_cache.revision {
// Enforce authenticated rate limit
return self
.is_http_authenticated_request_allowed(&access_token)
.await
.map(|in_flight| (in_flight, access_token));
}
}
// If the revision is not valid, remove the cached credentials
self.inner.cache.http_auth.remove(token);
}
let credentials = if mechanism.eq_ignore_ascii_case("basic") {
@@ -100,6 +100,8 @@ impl Authenticator for Server {
HttpAuthCache {
account_id: access_token.primary_id(),
revision: access_token.revision,
expires: Instant::now()
+ Duration::from_secs(self.core.oauth.oauth_expiry_token),
},
);

View File

@@ -12,7 +12,7 @@ use common::{
};
use directory::{
Permission, QueryBy, Type,
Permission, QueryParams, Type,
backend::internal::{
PrincipalField, PrincipalSet, lookup::DirectoryStore, manage::ManageDirectory,
},
@@ -113,7 +113,7 @@ impl ClientRegistrationHandler for Server {
// Fetch client registration
let found_registration = if let Some(client) = self
.store()
.query(QueryBy::Name(client_id), false)
.query(QueryParams::name(client_id).with_return_member_of(false))
.await
.caused_by(trc::location!())?
.filter(|p| p.typ() == Type::OauthClient)