v0.34.15
This commit is contained in:
1 parent
62b7574553
commit
e364392659
47 files changed
+2164
-257
No files matched your search
@@ -0,0 +1,176 @@
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::auth_provider::{
|
||||
testing::{context, policy, spawn_mock},
|
||||
Provider,
|
||||
};
|
||||
|
||||
fn settings(url: &str) -> Settings {
|
||||
let mut settings = Settings::default();
|
||||
settings.enabled = true;
|
||||
settings.url = url.into();
|
||||
settings.allow_private = true;
|
||||
settings
|
||||
}
|
||||
fn compile(url: &str) -> Compiled {
|
||||
settings(url).compile(&policy(), &[]).unwrap().unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_json_and_provider_path_contract_are_preserved() {
|
||||
let parsed: Settings = serde_json::from_str(
|
||||
r#"{"enabled":true,"url":"http://127.0.0.1:9300","allow_private":true}"#,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
serde_json::to_value(&parsed).unwrap()["url"],
|
||||
"http://127.0.0.1:9300"
|
||||
);
|
||||
let auth = compile("http://127.0.0.1:9300");
|
||||
assert_eq!(auth.id(), "authentik");
|
||||
assert!(auth.reserved_path("/outpost.goauthentik.io"));
|
||||
assert!(auth.reserved_path("/outpost.goauthentik.io/start"));
|
||||
assert!(!auth.reserved_path("/outpost.goauthentik.io-evil"));
|
||||
assert!(!auth.reserved_path("/other/outpost.goauthentik.io"));
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn unauthorized_redirect_uses_application_domain_not_portal_domain() {
|
||||
let (url, server) = spawn_mock(
|
||||
"401 Unauthorized",
|
||||
"Set-Cookie: authentik_session=abc; Secure; Path=/; HttpOnly\r\n",
|
||||
)
|
||||
.await;
|
||||
let auth = compile(&url);
|
||||
let incoming = HeaderMap::new();
|
||||
let response = auth
|
||||
.authorize(
|
||||
&incoming,
|
||||
&Method::POST,
|
||||
&context(&incoming, "app.other-domain.example"),
|
||||
&CancellationToken::new(),
|
||||
&CookieSink::default(),
|
||||
)
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert_eq!(response.status(), StatusCode::FOUND);
|
||||
let location = Url::parse(response.headers()[header::LOCATION].to_str().unwrap()).unwrap();
|
||||
assert_eq!(
|
||||
location.origin().ascii_serialization(),
|
||||
"https://app.other-domain.example"
|
||||
);
|
||||
assert_eq!(location.path(), "/outpost.goauthentik.io/start");
|
||||
assert_eq!(
|
||||
location.query_pairs().find(|(k, _)| k == "rd").unwrap().1,
|
||||
"https://app.other-domain.example/private?redirect=%2Fhome"
|
||||
);
|
||||
assert_eq!(
|
||||
response.headers()[header::SET_COOKIE],
|
||||
"authentik_session=abc; Secure; Path=/; HttpOnly"
|
||||
);
|
||||
server.await.unwrap();
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn forbidden_response_never_authorizes_backend() {
|
||||
let (url, server) = spawn_mock("403 Forbidden", "").await;
|
||||
let auth = compile(&url);
|
||||
let incoming = HeaderMap::new();
|
||||
let response = auth
|
||||
.authorize(
|
||||
&incoming,
|
||||
&Method::GET,
|
||||
&context(&incoming, "app.example.com"),
|
||||
&CancellationToken::new(),
|
||||
&CookieSink::default(),
|
||||
)
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert_eq!(response.status(), StatusCode::FORBIDDEN);
|
||||
server.await.unwrap();
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn verified_headers_and_refresh_cookie_are_forwarded() {
|
||||
let (url, server) = spawn_mock("200 OK", "X-Authentik-Username: allowed\r\nSet-Cookie: authentik_session=renew; Path=/; HttpOnly\r\n").await;
|
||||
let auth = compile(&url);
|
||||
let incoming = HeaderMap::new();
|
||||
let cookies = CookieSink::default();
|
||||
let identity = auth
|
||||
.authorize(
|
||||
&incoming,
|
||||
&Method::GET,
|
||||
&context(&incoming, "app.example.com"),
|
||||
&CancellationToken::new(),
|
||||
&cookies,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let mut headers = HeaderMap::new();
|
||||
identity.apply(&mut headers);
|
||||
assert_eq!(headers["x-authentik-username"], "allowed");
|
||||
let mut response = Response::new(Body::empty());
|
||||
cookies.apply(&mut response);
|
||||
assert_eq!(
|
||||
response.headers()[header::SET_COOKIE],
|
||||
"authentik_session=renew; Path=/; HttpOnly"
|
||||
);
|
||||
server.await.unwrap();
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn outpost_is_proxied_only_on_reserved_path_with_trusted_host() {
|
||||
let (url, server) = spawn_mock("302 Found", "Location: https://auth.example.com/if/flow/default/\r\nSet-Cookie: authentik=ok; Path=/\r\n").await;
|
||||
let auth = compile(&url);
|
||||
let incoming = HeaderMap::new();
|
||||
let request = Request::builder()
|
||||
.uri("/outpost.goauthentik.io/start?rd=https%3A%2F%2Fapp.example.com")
|
||||
.header("X-Forwarded-Host", "spoofed.example")
|
||||
.header("X-Authentik-Username", "forged")
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
let response = auth
|
||||
.serve_reserved(
|
||||
request,
|
||||
&context(&incoming, "app.example.com"),
|
||||
&CancellationToken::new(),
|
||||
)
|
||||
.unwrap()
|
||||
.await;
|
||||
assert_eq!(response.status(), StatusCode::FOUND);
|
||||
assert_eq!(
|
||||
response.headers()[header::SET_COOKIE],
|
||||
"authentik=ok; Path=/"
|
||||
);
|
||||
assert_eq!(
|
||||
response.headers()[header::CACHE_CONTROL],
|
||||
"private, no-store"
|
||||
);
|
||||
let request = server.await.unwrap().to_ascii_lowercase();
|
||||
assert!(request.starts_with("get /outpost.goauthentik.io/start?rd="));
|
||||
assert!(request.contains("host: app.example.com"));
|
||||
assert!(request.contains("x-forwarded-host: app.example.com"));
|
||||
assert!(!request.contains("spoofed.example"));
|
||||
assert!(!request.contains("x-authentik-username: forged"));
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn auth_check_uses_provider_specific_endpoint() {
|
||||
let (url, server) = spawn_mock("200 OK", "X-Authentik-Username: admin\r\n").await;
|
||||
let auth = compile(&url);
|
||||
let incoming = HeaderMap::new();
|
||||
let identity = auth
|
||||
.authorize(
|
||||
&incoming,
|
||||
&Method::GET,
|
||||
&context(&incoming, "app.example.com"),
|
||||
&CancellationToken::new(),
|
||||
&CookieSink::default(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let mut headers = HeaderMap::new();
|
||||
identity.apply(&mut headers);
|
||||
assert_eq!(headers["x-authentik-username"], "admin");
|
||||
assert!(server
|
||||
.await
|
||||
.unwrap()
|
||||
.to_ascii_lowercase()
|
||||
.contains("get /outpost.goauthentik.io/auth/nginx"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user