From da7566b2d09585fe6b1b60ce2a792dbfdba2892e Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 24 Jun 2023 21:55:54 -0700 Subject: [PATCH] Add WebFinger response for OIDC --- src/activitypub/webfinger.rs | 42 +++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/activitypub/webfinger.rs b/src/activitypub/webfinger.rs index a014aa0..a619813 100644 --- a/src/activitypub/webfinger.rs +++ b/src/activitypub/webfinger.rs @@ -10,10 +10,15 @@ use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; static ACCT: Lazy = Lazy::new(|| format!("blog@{}", *DOMAIN)); +const OIDC_SUBJECT: &'static str = "me@shadowfacts.net"; pub async fn handle(req: Request) -> Response { - if is_resource_blog(req).await { - Json(WebfingerResponse::new()).into_response() + let resource = resource(req).await; + if resource.as_deref() == Some(&*ACCT) { + Json(WebfingerResponse::blog()).into_response() + } else if resource.as_deref() == Some(&OIDC_SUBJECT) { + // used for tailscale OIDC + Json(WebfingerResponse::oidc()).into_response() } else { // mastodon responds with 400 and an empty body, so we do too StatusCode::BAD_REQUEST.into_response() @@ -43,18 +48,16 @@ pub async fn handle_interact( .into_response() } -async fn is_resource_blog(req: Request) -> bool { +async fn resource(req: Request) -> Option { let mut parts = RequestParts::new(req); - if let Ok(Query(params)) = parts.extract::>().await { - let resource = if params.resource.starts_with("acct:") { - ¶ms.resource[5..] + let params = parts.extract::>().await; + params.ok().map(|Query(params)| { + if params.resource.starts_with("acct:") { + params.resource[5..].into() } else { - ¶ms.resource - }; - resource == ACCT.as_str() - } else { - false - } + params.resource + } + }) } async fn query(acct: &str) -> anyhow::Result { @@ -89,7 +92,7 @@ pub struct WebfingerResponse { } impl WebfingerResponse { - fn new() -> Self { + fn blog() -> Self { Self { subject: ACCT.to_owned(), links: vec![Link { @@ -101,6 +104,18 @@ impl WebfingerResponse { }], } } + + fn oidc() -> Self { + Self { + subject: OIDC_SUBJECT.to_owned(), + links: vec![Link { + rel: "http://openid.net/specs/connect/1.0/issuer".to_owned(), + payload: LinkPayload::Href { + href: "https://auth.shadowfacts.net/application/o/tailscale/".to_owned(), + }, + }], + } + } } #[derive(Debug, PartialEq, Serialize, Deserialize)] @@ -115,6 +130,7 @@ pub struct Link { pub enum LinkPayload { Webfinger { r#type: String, href: String }, OStatusSubscribe { template: String }, + Href { href: String }, } #[cfg(test)]