Skip to content

Commit

Permalink
Json webtoken
Browse files Browse the repository at this point in the history
  • Loading branch information
CharlesTaylor7 committed May 19, 2024
1 parent aa73f18 commit 1c92d76
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 9 deletions.
44 changes: 44 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ percent-encoding = "2.3.1"
pkce = { path = "./vendor/pkce" }
tower-service = "0.3.2"
async-trait = "0.1.80"
jsonwebtoken = { version = "9.3.0", default-features = false }
getrandom = { version = "0.2.11", default-features = false }

[features]
dev = []
Expand Down
38 changes: 38 additions & 0 deletions src/server/auth.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use jsonwebtoken::{Algorithm, DecodingKey};
use serde::Deserialize;
use std::borrow::Cow;
use std::env;
use time::Duration;
use tower_cookies::cookie::SameSite;
use tower_cookies::Cookie;
Expand All @@ -19,3 +22,38 @@ pub fn cookie<'a>(

cookie.into()
}

#[derive(Clone)]
pub struct JwtDecoder {
pub secret: jsonwebtoken::DecodingKey,
pub validation: jsonwebtoken::Validation,
}

impl Default for JwtDecoder {
fn default() -> Self {
let mut validation = jsonwebtoken::Validation::new(Algorithm::HS256);
validation.set_audience(&["authenticated"]);
Self {
validation,
secret: DecodingKey::from_secret(env::var("SUPABASE_JWT_SECRET").unwrap().as_ref()),
}
}
}

impl JwtDecoder {
pub fn decode(&self, jwt: &str) -> anyhow::Result<Claims> {
let token = jsonwebtoken::decode::<Claims>(&jwt, &self.secret, &self.validation)?;
Ok(token.claims)
}
}
type Claims = serde_json::Value;

#[derive(Deserialize)]
pub struct Claims_ {
aud: String, // Optional. Audience
exp: usize, // Required (validate_exp defaults to true in validation). Expiration time (as UTC timestamp)
//iat: usize, // Optional. Issued at (as UTC timestamp)
iss: String, // Optional. Issuer
//nbf: usize, // Optional. Not Before (as UTC timestamp)
sub: String,
}
22 changes: 13 additions & 9 deletions src/server/state.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use super::auth::JwtDecoder;
use super::ws::WebSockets;
use crate::server::supabase::SupabaseAnonClient;
use crate::strings::UserName;
use crate::strings::{AccessToken, RefreshToken, SessionId, UserId};
use crate::{game::Game, lobby::Lobby};
use anyhow::anyhow;
use serde::Deserialize;
use std::sync::{Arc, Mutex};
use tower_cookies::Cookies;
Expand All @@ -11,23 +13,25 @@ fn new_arc_mutex<T>(item: T) -> Arc<std::sync::Mutex<T>> {
Arc::new(std::sync::Mutex::new(item))
}

struct SessionInfo {
pub user_id: UserId,
pub access_token: AccessToken,
pub refresh_token: RefreshToken,
pub expires_in: u64,
}

#[derive(Default, Clone)]
pub struct AppState {
pub lobby: Arc<std::sync::Mutex<Lobby>>,
pub game: Arc<std::sync::Mutex<Option<Game>>>,
// TODO: remove these
pub lobby: Arc<Mutex<Lobby>>,
pub game: Arc<Mutex<Option<Game>>>,
// inherently stateless
pub jwt_decoder: JwtDecoder,
pub supabase: SupabaseAnonClient,
// stateful, but transient
pub ws_connections: Arc<Mutex<WebSockets>>,
}

impl AppState {
pub async fn user_id(&self, cookies: Cookies) -> anyhow::Result<UserId> {
let cookie = cookies
.get("access_token")
.ok_or(anyhow!("no jwt cookie"))?;
let decoded = self.jwt_decoder.decode(cookie.value());

anyhow::bail!("TODO: app.user_id()")
}
pub async fn logout(&self, cookies: Cookies) -> anyhow::Result<()> {
Expand Down

0 comments on commit 1c92d76

Please sign in to comment.