diff --git a/visions/server/Cargo.toml b/visions/server/Cargo.toml
index b1a3edc..031dace 100644
--- a/visions/server/Cargo.toml
+++ b/visions/server/Cargo.toml
@@ -4,6 +4,9 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-axum = "0.8.1"
+axum = { version = "0.8.1", features = ["macros"] }
+serde = { version = "1.0.217", features = ["derive", "serde_derive"] }
 tokio = { version = "1.43.0", features = ["full", "rt"] }
 tower-http = { version = "0.6.2", features = ["cors"] }
+typeshare = "1.0.4"
+uuid = { version = "1.13.1", features = ["v4"] }
diff --git a/visions/server/src/main.rs b/visions/server/src/main.rs
index 54d9196..bed0623 100644
--- a/visions/server/src/main.rs
+++ b/visions/server/src/main.rs
@@ -1,5 +1,60 @@
-use axum::{http::{Method, StatusCode}, routing::get, Json, Router};
+use axum::{http::{Method, StatusCode}, routing::{get, post}, Json, Router};
+use serde::{Deserialize, Serialize};
 use tower_http::cors::{Any, CorsLayer};
+use typeshare::typeshare;
+use uuid::Uuid;
+
+#[derive(Deserialize, Serialize)]
+#[typeshare]
+struct AuthRequest {
+    username: String,
+    password: String
+}
+
+#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
+#[typeshare]
+pub struct SessionId(String);
+
+impl SessionId {
+    pub fn new() -> Self {
+        Self(format!("{}", Uuid::new_v4().hyphenated()))
+    }
+
+    pub fn as_str(&self) -> &str {
+        &self.0
+    }
+}
+
+impl From<&str> for SessionId {
+    fn from(s: &str) -> Self {
+        Self(s.to_owned())
+    }
+}
+
+impl From<String> for SessionId {
+    fn from(s: String) -> Self {
+        Self(s)
+    }
+}
+
+#[derive(Deserialize, Serialize)]
+#[typeshare]
+enum AuthResponse {
+    Success(SessionId),
+    PasswordReset(SessionId),
+}
+
+#[axum::debug_handler]
+async fn check_password(request: Json<AuthRequest>) -> (StatusCode, Json<Option<AuthResponse>>) {
+    let Json(request) = request;
+    if request.username == "vakarian" && request.password == "aoeu" {
+        (StatusCode::OK, Json(Some(AuthResponse::Success("vakarian-session-id".into()))))
+    } else if request.username == "shephard" && request.password == "aoeu" {
+        (StatusCode::OK, Json(Some(AuthResponse::PasswordReset("shephard-session-id".into()))))
+    } else {
+        (StatusCode::UNAUTHORIZED, Json(None))
+    }
+}
 
 #[tokio::main]
 async fn main() {
@@ -12,11 +67,11 @@ async fn main() {
                 .allow_methods([Method::GET]).allow_origin(Any),
         )
         .route(
-            "/api/v1/denied",
-            get(|| async { (StatusCode::UNAUTHORIZED, Json(None::<String>)) }),
+            "/api/v1/auth",
+            post(|req: Json<AuthRequest>| check_password(req)),
         ).layer(
             CorsLayer::new()
-            .allow_methods([Method::GET]).allow_origin(Any),
+            .allow_methods([Method::POST]).allow_origin(Any),
         );
     let listener = tokio::net::TcpListener::bind("127.0.0.1:8001")
         .await