mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-14 13:52:11 +00:00
upgrade / refresh tokens
This commit is contained in:
1 parent
76a639a045
commit
f2a2aa6e28
10 files changed
+92
-8
No files matched your search
@@ -1,3 +1,4 @@
|
||||
pub mod sora_jwt_bearer_token;
|
||||
pub mod sora_cookies;
|
||||
pub mod sora_credential_set;
|
||||
pub mod sora_jwt_bearer_token;
|
||||
pub mod sora_sentinel;
|
||||
@@ -1,5 +1,7 @@
|
||||
/// Cookies are the credential that are always required.
|
||||
/// You can mint a JWT bearer token with just the cookies.
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SoraCookies {
|
||||
cookies: String,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
use crate::creds::sora_cookies::SoraCookies;
|
||||
use crate::creds::sora_jwt_bearer_token::SoraJwtBearerToken;
|
||||
use crate::creds::sora_sentinel::SoraSentinel;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SoraCredentialSet {
|
||||
pub (crate) cookies: SoraCookies,
|
||||
pub (crate) jwt_bearer_token: Option<SoraJwtBearerToken>,
|
||||
pub (crate) sora_sentinel: Option<SoraSentinel>,
|
||||
}
|
||||
|
||||
impl SoraCredentialSet {
|
||||
pub fn initialize_with_just_cookies(cookies: SoraCookies) -> Self {
|
||||
SoraCredentialSet {
|
||||
cookies,
|
||||
jwt_bearer_token: None,
|
||||
sora_sentinel: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_with_just_cookies_str(cookies: &str) -> Self {
|
||||
Self::initialize_with_just_cookies(
|
||||
SoraCookies::new(cookies.to_string()),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::utils::lightweight_jwt_parse::{lightweight_jwt_parse, SoraJwtClaims};
|
||||
use crate::utils::lightweight_sora_jwt_parse::{lightweight_sora_jwt_parse, SoraJwtClaims};
|
||||
use errors::AnyhowResult;
|
||||
|
||||
/// Sora bearer tokens are JWT tokens that can be minted with a valid cookie/session.
|
||||
#[derive(Clone)]
|
||||
pub struct SoraJwtBearerToken {
|
||||
token: String,
|
||||
jwt_claims: SoraJwtClaims,
|
||||
@@ -9,7 +10,7 @@ pub struct SoraJwtBearerToken {
|
||||
|
||||
impl SoraJwtBearerToken {
|
||||
pub fn new(token: String) -> AnyhowResult<Self> {
|
||||
let jwt_claims = lightweight_jwt_parse(&token)?;
|
||||
let jwt_claims = lightweight_sora_jwt_parse(&token)?;
|
||||
Ok(SoraJwtBearerToken {
|
||||
token,
|
||||
jwt_claims,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
/// Sora Sentinel tokens can be generated without cookies or JWTs, and are needed for some API calls.
|
||||
#[derive(Clone)]
|
||||
pub struct SoraSentinel {
|
||||
sentinel: String,
|
||||
}
|
||||
|
||||
@@ -2,4 +2,5 @@ pub mod credentials;
|
||||
pub mod creds;
|
||||
pub mod requests;
|
||||
pub mod sora_error;
|
||||
pub mod utils;
|
||||
pub mod utils;
|
||||
mod recipes;
|
||||
@@ -0,0 +1 @@
|
||||
mod upgrade_or_renew_session;
|
||||
@@ -0,0 +1,51 @@
|
||||
use crate::creds::sora_credential_set::SoraCredentialSet;
|
||||
use crate::creds::sora_jwt_bearer_token::SoraJwtBearerToken;
|
||||
use crate::creds::sora_sentinel::SoraSentinel;
|
||||
use crate::requests::bearer::generate::generate_bearer_with_cookie;
|
||||
use crate::requests::sentinel_refresh::generate::token::generate_token;
|
||||
use chrono::{DateTime, TimeDelta, Utc};
|
||||
use errors::AnyhowResult;
|
||||
use log::info;
|
||||
use std::ops::Sub;
|
||||
|
||||
const EXPIRATION_DEADLINE : TimeDelta = TimeDelta::hours(12);
|
||||
|
||||
/// Call this at session startup to generate the tokens for the first time.
|
||||
/// Call this periodically to refresh the JWT as it nears its expiration date.
|
||||
/// This will not refresh the sentinel token once it's been generated - we can use other flows to accomplish that.
|
||||
pub async fn upgrade_or_renew_session(sora_credentials: &mut SoraCredentialSet) -> AnyhowResult<()> {
|
||||
let mut refresh_jwt = !sora_credentials.jwt_bearer_token.is_some();
|
||||
let refresh_sentinel = !sora_credentials.sora_sentinel.is_some();
|
||||
|
||||
if let Some(jwt) = &sora_credentials.jwt_bearer_token {
|
||||
let now = Utc::now();
|
||||
let refresh_deadline = now.sub(EXPIRATION_DEADLINE);
|
||||
if jwt.jwt_claims().expiration.lt(&now) {
|
||||
info!("JWT expiration time has elapsed.");
|
||||
refresh_jwt = true;
|
||||
} else if jwt.jwt_claims().expiration.lt(&refresh_deadline) {
|
||||
info!("JWT expiration time is under the expiration deadline.");
|
||||
refresh_jwt = true;
|
||||
}
|
||||
}
|
||||
|
||||
if refresh_jwt {
|
||||
let cookies = sora_credentials.cookies.get_cookies();
|
||||
|
||||
info!("Generating new JWT bearer token...");
|
||||
let token = generate_bearer_with_cookie(cookies).await?;
|
||||
|
||||
info!("Parsing JWT bearer token.");
|
||||
let token = SoraJwtBearerToken::new(token)?;
|
||||
sora_credentials.jwt_bearer_token = Some(token);
|
||||
}
|
||||
|
||||
if refresh_sentinel {
|
||||
info!("Generating new sentinel...");
|
||||
let token = generate_token().await?;
|
||||
let token = SoraSentinel::new(token);
|
||||
sora_credentials.sora_sentinel = Some(token);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
+3
-3
@@ -19,7 +19,7 @@ pub struct SoraJwtClaims {
|
||||
pub email_verified: bool,
|
||||
}
|
||||
|
||||
pub fn lightweight_jwt_parse(token: &str) -> AnyhowResult<SoraJwtClaims> {
|
||||
pub fn lightweight_sora_jwt_parse(token: &str) -> AnyhowResult<SoraJwtClaims> {
|
||||
let [_header_str, claims_str, _signature_str] = split_components(token)?;
|
||||
|
||||
let claims = decode_base64(claims_str)?;
|
||||
@@ -100,7 +100,7 @@ fn decode_base64(raw: &str) -> AnyhowResult<String> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::utils::lightweight_jwt_parse::lightweight_jwt_parse;
|
||||
use crate::utils::lightweight_sora_jwt_parse::lightweight_sora_jwt_parse;
|
||||
|
||||
#[test]
|
||||
fn test_sora_jwt_bearer_token() {
|
||||
@@ -131,7 +131,7 @@ mod tests {
|
||||
// - "nbf": 1744936471, - not before, don't use before date
|
||||
// - "exp": 1745800472, - in 5 days, expiry
|
||||
|
||||
let result = lightweight_jwt_parse(token).expect("claim should parse");
|
||||
let result = lightweight_sora_jwt_parse(token).expect("claim should parse");
|
||||
|
||||
assert_eq!(result.email, "vocodes2020@gmail.com");
|
||||
assert_eq!(result.email_verified, true);
|
||||
@@ -1 +1 @@
|
||||
pub mod lightweight_jwt_parse;
|
||||
pub mod lightweight_sora_jwt_parse;
|
||||
Reference in new issue
Block a user