Skip to content

fix(auth): Parse URL from request parts to enable wasmtime serve #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ fn handle_http_handler(_req: Request) -> anyhow::Result<impl IntoResponse> {
Ok(http::Response::builder()
.status(200)
.header("content-type", "text/plain")
.body("Hello, Fermyon!")?)
.body("Business logic executed!")?)
}
4 changes: 2 additions & 2 deletions github-oauth/src/api/authorize.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::OAuth2;
use oauth2::{CsrfToken, RedirectUrl, Scope};
use spin_sdk::http::{Headers, IncomingRequest, OutgoingResponse, ResponseOutparam};
use spin_sdk::http::{Headers, OutgoingResponse, ResponseOutparam};

/// `authorize` kicks off the oauth flow constructing the authorization url and redirecting the client to github
/// to authorize the application to the user's profile.
pub async fn authorize(_request: IncomingRequest, output: ResponseOutparam) {
pub async fn authorize(output: ResponseOutparam) {
let client = match OAuth2::try_init() {
Ok(config) => {
let redirect_url = RedirectUrl::new("http://127.0.0.1:3000/login/callback".to_string())
Expand Down
10 changes: 4 additions & 6 deletions github-oauth/src/api/callback.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use super::OAuth2;
use cookie::{Cookie, SameSite};
use oauth2::{AuthorizationCode, CsrfToken, RedirectUrl, TokenResponse};
use spin_sdk::http::{
send, Headers, IncomingRequest, OutgoingResponse, ResponseOutparam, SendError,
};
use spin_sdk::http::{send, Headers, OutgoingResponse, ResponseOutparam, SendError};
use url::Url;

pub async fn callback(url: Url, _request: IncomingRequest, output: ResponseOutparam) {
pub async fn callback(url: Url, output: ResponseOutparam) {
let client = match OAuth2::try_init() {
Ok(config) => {
let redirect_url = RedirectUrl::new("http://127.0.0.1:3000/login/callback".to_string())
Expand Down Expand Up @@ -85,13 +83,13 @@ fn get_code_and_state_param(url: &Url) -> anyhow::Result<(AuthorizationCode, Csr
const STATE_QUERY_PARAM_NAME: &str = "state";
const CODE_QUERY_PARAM_NAME: &str = "code";

let Some(param) = get_query_param(&url, STATE_QUERY_PARAM_NAME) else {
let Some(param) = get_query_param(url, STATE_QUERY_PARAM_NAME) else {
anyhow::bail!("missing '{STATE_QUERY_PARAM_NAME}' query parameter");
};

let state = CsrfToken::new(param);

let Some(param) = get_query_param(&url, CODE_QUERY_PARAM_NAME) else {
let Some(param) = get_query_param(url, CODE_QUERY_PARAM_NAME) else {
anyhow::bail!("missing '{CODE_QUERY_PARAM_NAME}' query parameter");
};

Expand Down
4 changes: 2 additions & 2 deletions github-oauth/src/api/login.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use spin_sdk::http::{Headers, IncomingRequest, OutgoingResponse, ResponseOutparam};
use spin_sdk::http::{Headers, OutgoingResponse, ResponseOutparam};

/// `login` returns the login page.
pub async fn login(_request: IncomingRequest, output: ResponseOutparam) {
pub async fn login(output: ResponseOutparam) {
const LOGIN_HTML: &[u8] = include_bytes!("../../login.html"); // TODO: this shouldn't be included statically.

let headers = Headers::new(&[("content-type".to_string(), b"text/html".to_vec())]);
Expand Down
27 changes: 20 additions & 7 deletions github-oauth/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,40 @@ use url::Url;
mod api;

// TODO: Allow configurable redirect URL

#[http_component]
async fn middleware(request: IncomingRequest, output: ResponseOutparam) {
let url = match Url::parse(&request.uri()) {
let url = match get_url(&request) {
Ok(url) => url,
Err(error) => {
eprintln!("error parsing URL: {error}");
Err(e) => {
eprintln!("error parsing URL: {e}");
let response = OutgoingResponse::new(500, &Headers::new(&[]));
output.set(response);
return;
}
};

match url.path() {
"/login/authorize" => api::authorize(request, output).await,
"/login/callback" => api::callback(url, request, output).await,
"/login" => api::login(request, output).await,
"/login/authorize" => api::authorize(output).await,
"/login/callback" => api::callback(url, output).await,
"/login" => api::login(output).await,
_ => api::authenticate(request, output).await,
}
}

fn get_url(request: &IncomingRequest) -> anyhow::Result<Url> {
let mut host_header = request
.headers()
.get(http::header::HOST.as_str())
.into_iter();
let header = &host_header
.next()
.ok_or(anyhow::anyhow!("missing host header"))?;
let host = String::from_utf8_lossy(header);
let path = request.path_with_query().unwrap_or_default();
let full = format!("http://{}{}", host, path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to consider not hardcoding scheme in the future.

Ok(Url::parse(&full)?)
}

wit_bindgen::generate!({
runtime_path: "::spin_sdk::wit_bindgen::rt",
world: "wasi-http-import",
Expand Down