diff --git a/README.md b/README.md index 883f133..7493003 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ siweoidc.example.com/r* siweoidc.example.com/a* siweoidc.example.com/t* siweoidc.example.com/j* +siweoidc.example.com/c* siweoidc.example.com/.w* ``` diff --git a/src/axum_lib.rs b/src/axum_lib.rs index b2690db..9450e19 100644 --- a/src/axum_lib.rs +++ b/src/axum_lib.rs @@ -1,7 +1,7 @@ use anyhow::{anyhow, Result}; use async_redis_session::RedisSessionStore; use axum::{ - extract::{self, Extension, Form, Query, TypedHeader}, + extract::{self, Extension, Form, Path, Query, TypedHeader}, http::{ header::{self, HeaderMap}, StatusCode, @@ -56,6 +56,7 @@ impl IntoResponse for CustomError { CustomError::Unauthorized(_) => { (StatusCode::UNAUTHORIZED, self.to_string()).into_response() } + CustomError::NotFound => (StatusCode::NOT_FOUND, self.to_string()).into_response(), CustomError::Redirect(uri) => Redirect::to( uri.parse().unwrap(), // .map_err(|e| anyhow!("Could not parse URI: {}", e))?, @@ -286,6 +287,13 @@ async fn userinfo( }) } +async fn clientinfo( + Path(client_id): Path, + Extension(redis_client): Extension, +) -> Result, CustomError> { + Ok(oidc::clientinfo(client_id, &redis_client).await?.into()) +} + async fn healthcheck() {} pub async fn main() { @@ -392,6 +400,7 @@ pub async fn main() { .route(oidc::AUTHORIZE_PATH, get(authorize)) .route(oidc::REGISTER_PATH, post(register)) .route(oidc::USERINFO_PATH, get(userinfo).post(userinfo)) + .route(&format!("{}/:id", oidc::CLIENTINFO_PATH), get(clientinfo)) .route(oidc::SIGNIN_PATH, get(sign_in)) .route("/health", get(healthcheck)) .layer(AddExtensionLayer::new(private_key)) diff --git a/src/oidc.rs b/src/oidc.rs index 0300406..ca56f9a 100644 --- a/src/oidc.rs +++ b/src/oidc.rs @@ -50,6 +50,7 @@ pub const AUTHORIZE_PATH: &str = "/authorize"; pub const REGISTER_PATH: &str = "/register"; pub const USERINFO_PATH: &str = "/userinfo"; pub const SIGNIN_PATH: &str = "/sign_in"; +pub const CLIENTINFO_PATH: &str = "/clientinfo"; pub const SIWE_COOKIE_KEY: &str = "siwe"; #[cfg(not(target_arch = "wasm32"))] @@ -73,6 +74,8 @@ pub enum CustomError { BadRequestToken(TokenError), #[error("{0}")] Unauthorized(String), + #[error("Not found")] + NotFound, #[error("{0:?}")] Redirect(String), #[error(transparent)] @@ -561,6 +564,17 @@ pub async fn register( .set_client_secret(Some(ClientSecret::new(secret.to_string())))) } +pub async fn clientinfo( + client_id: String, + db_client: &DBClientType, +) -> Result { + let client_entry = db_client + .get_client(client_id) + .await? + .ok_or_else(|| CustomError::NotFound)?; + Ok(client_entry.metadata) +} + #[derive(Deserialize)] pub struct UserInfoPayload { pub access_token: Option, diff --git a/src/worker_lib.rs b/src/worker_lib.rs index 1397858..6e47398 100644 --- a/src/worker_lib.rs +++ b/src/worker_lib.rs @@ -28,6 +28,7 @@ impl From for Result { } CustomError::BadRequestToken(e) => Response::from_json(&e).map(|r| r.with_status(400)), CustomError::Unauthorized(_) => Response::error(&error.to_string(), 401), + CustomError::NotFound => Response::error(&error.to_string(), 404), CustomError::Redirect(uri) => Response::redirect(uri.parse().unwrap()), CustomError::Other(_) => Response::error(&error.to_string(), 500), } @@ -234,6 +235,22 @@ pub async fn main(req: Request, env: Env) -> Result { }) .post_async(oidc::USERINFO_PATH, userinfo) .get_async(oidc::USERINFO_PATH, userinfo) + .get_async( + &format!("{}/:id", oidc::CLIENTINFO_PATH), + |req, ctx| async move { + let client_id = if let Some(id) = ctx.param("id") { + id.clone() + } else { + return Response::error("Bad Request", 400); + }; + let url = req.url()?; + let db_client = CFClient { ctx, url }; + match oidc::clientinfo(client_id, &db_client).await { + Ok(r) => Ok(Response::from_json(&r)?), + Err(e) => e.into(), + } + }, + ) .get_async(oidc::SIGNIN_PATH, |req, ctx| async move { let url = req.url()?; let query = url.query().unwrap_or_default();