Last active
April 23, 2024 10:26
-
-
Save Fyko/2c80a03b02219b082b68b337ed88503f to your computer and use it in GitHub Desktop.
a clerk webhook verifier for axum
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///! An [axum](https://docs.rs/axum) extractor for [Clerk webhooks](https://clerk.com/docs/integration/webhooks). | |
use axum::{ | |
body::Bytes, | |
extract::FromRequest, | |
http::{Request, StatusCode}, | |
response::{IntoResponse, Response}, | |
}; | |
// TODO: replace with your config | |
use happycamper_util::config::CONFIG; | |
use serde::{Deserialize, Serialize}; | |
use serde_json::Value; | |
use svix::webhooks::Webhook; | |
/// A structure and axum extractor representing a Clerk webhook. | |
/// ```rs | |
/// async fn clerk_webhook(webhook: ClerkWebhook) -> Result<Response<String>> { | |
/// /// your business logic | |
/// } | |
#[derive(Debug, Deserialize)] | |
pub struct ClerkWebhook { | |
pub object: String, | |
#[serde(rename = "type")] | |
pub kind: String, | |
pub data: Value, | |
} | |
#[async_trait::async_trait] | |
impl<S, B> FromRequest<S, B> for ClerkWebhook | |
where | |
S: Send + Sync, | |
B: Send + 'static, | |
Bytes: FromRequest<S, B>, | |
{ | |
type Rejection = Response; | |
async fn from_request(req: Request<B>, state: &S) -> Result<Self, Self::Rejection> { | |
let headers = req.headers().clone(); | |
let payload = Bytes::from_request(req, state) | |
.await | |
.map_err(IntoResponse::into_response)?; | |
// TODO: replace with your config | |
let webhook = Webhook::new(&CONFIG.clerk_webhook_key).expect("Invalid clerk webhook key"); | |
webhook.verify(&payload, &headers).map_err(|e| { | |
(StatusCode::BAD_REQUEST, format!("Failed to verify: {}", e)).into_response() | |
})?; | |
let data: ClerkWebhook = serde_json::from_slice(&payload) | |
.map_err(|_| (StatusCode::INTERNAL_SERVER_ERROR, "Failed to parse").into_response())?; | |
Ok(data) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment