diff options
| author | mrw1593 <botahamec@outlook.com> | 2023-07-02 11:52:50 -0400 |
|---|---|---|
| committer | mrw1593 <botahamec@outlook.com> | 2023-07-02 11:52:50 -0400 |
| commit | 15a7387309fed7dcc589216aac748811e0321ab4 (patch) | |
| tree | 0541ba37a9b5e01e3c03dcf31b0b2df234d1bf49 /src | |
| parent | b909c8496a7e0f035623105f631809ef3016a810 (diff) | |
Changes to jwt claims
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/oauth.rs | 43 | ||||
| -rw-r--r-- | src/services/jwt.rs | 55 |
2 files changed, 57 insertions, 41 deletions
diff --git a/src/api/oauth.rs b/src/api/oauth.rs index fe1c361..aee0ed4 100644 --- a/src/api/oauth.rs +++ b/src/api/oauth.rs @@ -216,12 +216,16 @@ async fn authenticate_user( db: &MySqlPool, username: &str, password: &str, -) -> Result<bool, RawUnexpected> { +) -> Result<Option<Uuid>, RawUnexpected> { let Some(user) = db::get_user_by_username(db, username).await? else { - return Ok(false); + return Ok(None); }; - Ok(user.check_password(password)?) + if user.check_password(password)? { + Ok(Some(user.id)) + } else { + Ok(None) + } } #[post("/authorize")] @@ -248,7 +252,7 @@ async fn authorize( return HttpResponse::InternalServerError().content_type("text/html").body(page); }; - let self_id = config.id; + let self_id = config.url; let state = req.state.clone(); // get redirect uri @@ -267,9 +271,9 @@ async fn authorize( }; // authenticate user - if !authenticate_user(db, &credentials.username, &credentials.password) + let Some(user_id) = authenticate_user(db, &credentials.username, &credentials.password) .await - .unwrap() + .unwrap() else { let language = Language::from_str("en").unwrap(); let translations = translations.get_ref().clone(); @@ -289,9 +293,10 @@ async fn authorize( match req.response_type { ResponseType::Code => { // create auth code - let code = jwt::Claims::auth_code(db, &self_id, client_id, &scope, &redirect_uri) - .await - .unwrap(); + let code = + jwt::Claims::auth_code(db, self_id, client_id, user_id, &scope, &redirect_uri) + .await + .unwrap(); let code = code.to_jwt().unwrap(); let response = AuthCodeResponse { code, state }; @@ -307,7 +312,7 @@ async fn authorize( // create access token let duration = Duration::hours(1); let access_token = - jwt::Claims::access_token(db, None, &self_id, client_id, duration, &scope) + jwt::Claims::access_token(db, None, self_id, client_id, user_id, duration, &scope) .await .unwrap(); @@ -635,7 +640,7 @@ async fn token( }; let config = config::get_config().unwrap(); - let self_id = config.id; + let self_id = config.url; let duration = Duration::hours(1); let token_type = Box::from("bearer"); let cache_control = header::CacheControl(vec![header::CacheDirective::NoStore]); @@ -677,8 +682,9 @@ async fn token( let access_token = jwt::Claims::access_token( db, Some(claims.id()), - &self_id, + self_id, client_id, + claims.subject(), duration, claims.scopes(), ) @@ -729,7 +735,7 @@ async fn token( } // authenticate user - if !authenticate_user(db, &username, &password).await.unwrap() { + let Some(user_id) = authenticate_user(db, &username, &password).await.unwrap() else { return TokenError::incorrect_user_credentials().error_response(); }; @@ -755,7 +761,7 @@ async fn token( } let access_token = - jwt::Claims::access_token(db, None, &self_id, client_id, duration, &scope) + jwt::Claims::access_token(db, None, self_id, client_id, user_id, duration, &scope) .await .unwrap(); let refresh_token = jwt::Claims::refresh_token(db, &access_token).await.unwrap(); @@ -818,10 +824,11 @@ async fn token( return TokenError::excessive_scope().error_response(); } - let access_token = - jwt::Claims::access_token(db, None, &self_id, client_id, duration, &scope) - .await - .unwrap(); + let access_token = jwt::Claims::access_token( + db, None, self_id, client_id, client_id, duration, &scope, + ) + .await + .unwrap(); let expires_in = access_token.expires_in(); let scope = access_token.scopes().into(); diff --git a/src/services/jwt.rs b/src/services/jwt.rs index 489b32f..16f5fa6 100644 --- a/src/services/jwt.rs +++ b/src/services/jwt.rs @@ -19,14 +19,15 @@ pub enum TokenType { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Claims { - iss: Box<str>, + iss: Url, + sub: Uuid, aud: Box<[String]>, #[serde(with = "ts_milliseconds")] exp: DateTime<Utc>, #[serde(with = "ts_milliseconds_option")] nbf: Option<DateTime<Utc>>, - #[serde(with = "ts_milliseconds_option")] - iat: Option<DateTime<Utc>>, + #[serde(with = "ts_milliseconds")] + iat: DateTime<Utc>, jti: Uuid, scope: Box<str>, client_id: Uuid, @@ -45,27 +46,29 @@ pub enum RevokedRefreshTokenReason { impl Claims { pub async fn auth_code<'c>( db: &MySqlPool, - self_id: &str, + self_id: Url, client_id: Uuid, + sub: Uuid, scopes: &str, redirect_uri: &Url, ) -> Result<Self, RawUnexpected> { let five_minutes = Duration::minutes(5); let id = new_id(db, db::auth_code_exists).await?; - let time = Utc::now(); - let exp = time + five_minutes; + let iat = Utc::now(); + let exp = iat + five_minutes; db::create_auth_code(db, id, exp).await?; let aud = [self_id.to_string(), client_id.to_string()].into(); Ok(Self { - iss: Box::from(self_id), + iss: self_id, + sub, aud, exp, nbf: None, - iat: Some(time), + iat, jti: id, scope: scopes.into(), client_id, @@ -78,14 +81,15 @@ impl Claims { pub async fn access_token<'c>( db: &MySqlPool, auth_code_id: Option<Uuid>, - self_id: &str, + self_id: Url, client_id: Uuid, + sub: Uuid, duration: Duration, scopes: &str, ) -> Result<Self, RawUnexpected> { let id = new_id(db, db::access_token_exists).await?; - let time = Utc::now(); - let exp = time + duration; + let iat = Utc::now(); + let exp = iat + duration; db::create_access_token(db, id, auth_code_id, exp) .await @@ -94,11 +98,12 @@ impl Claims { let aud = [self_id.to_string(), client_id.to_string()].into(); Ok(Self { - iss: Box::from(self_id), + iss: self_id, + sub, aud, exp, nbf: None, - iat: Some(time), + iat, jti: id, scope: scopes.into(), client_id, @@ -115,14 +120,14 @@ impl Claims { let one_day = Duration::days(1); let id = new_id(db, db::refresh_token_exists).await?; - let time = Utc::now(); + let iat = Utc::now(); let exp = other_token.exp + one_day; db::create_refresh_token(db, id, other_token.auth_code_id, exp).await?; let mut claims = other_token.clone(); claims.exp = exp; - claims.iat = Some(time); + claims.iat = iat; claims.jti = id; claims.token_type = TokenType::Refresh; @@ -135,14 +140,14 @@ impl Claims { exp_time: Duration, ) -> Result<Self, RawUnexpected> { let id = new_id(db, db::access_token_exists).await?; - let time = Utc::now(); - let exp = time + exp_time; + let iat = Utc::now(); + let exp = iat + exp_time; db::create_access_token(db, id, refresh_token.auth_code_id, exp).await?; let mut claims = refresh_token.clone(); claims.exp = exp; - claims.iat = Some(time); + claims.iat = iat; claims.jti = id; claims.token_type = TokenType::Access; @@ -153,6 +158,10 @@ impl Claims { self.jti } + pub fn subject(&self) -> Uuid { + self.sub + } + pub fn expires_in(&self) -> i64 { (self.exp - Utc::now()).num_seconds() } @@ -190,7 +199,7 @@ pub enum VerifyJwtError { fn verify_jwt( token: &str, - self_id: &str, + self_id: &Url, client_id: Option<Uuid>, ) -> Result<Claims, Expect<VerifyJwtError>> { let key = secrets::signing_key()?; @@ -198,7 +207,7 @@ fn verify_jwt( .verify_with_key(&key) .map_err(|e| VerifyJwtError::from(e))?; - if claims.iss != self_id.into() { + if &claims.iss != self_id { yeet!(VerifyJwtError::IncorrectIssuer.into()) } @@ -230,7 +239,7 @@ fn verify_jwt( pub async fn verify_auth_code<'c>( db: &MySqlPool, token: &str, - self_id: &str, + self_id: &Url, client_id: Uuid, redirect_uri: Url, ) -> Result<Claims, Expect<VerifyJwtError>> { @@ -254,7 +263,7 @@ pub async fn verify_auth_code<'c>( pub async fn verify_access_token<'c>( db: impl Executor<'c, Database = MySql>, token: &str, - self_id: &str, + self_id: &Url, client_id: Uuid, ) -> Result<Claims, Expect<VerifyJwtError>> { let claims = verify_jwt(token, self_id, Some(client_id))?; @@ -269,7 +278,7 @@ pub async fn verify_access_token<'c>( pub async fn verify_refresh_token<'c>( db: impl Executor<'c, Database = MySql>, token: &str, - self_id: &str, + self_id: &Url, client_id: Option<Uuid>, ) -> Result<Claims, Expect<VerifyJwtError>> { let claims = verify_jwt(token, self_id, client_id)?; |
