summaryrefslogtreecommitdiff
path: root/src/api/oauth.rs
diff options
context:
space:
mode:
authormrw1593 <botahamec@outlook.com>2023-06-18 18:24:58 -0400
committermrw1593 <botahamec@outlook.com>2023-06-18 18:24:58 -0400
commitcfc6b9f35f49636a50ef9d170d01740439dfdbe4 (patch)
tree87dc94124d84ae26296891153b5a219a5df6cf83 /src/api/oauth.rs
parentec1a9e27fbd118c8cf3e129801f638fcad698387 (diff)
Implement refresh token grant
Diffstat (limited to 'src/api/oauth.rs')
-rw-r--r--src/api/oauth.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/api/oauth.rs b/src/api/oauth.rs
index bc9f5a2..de98e80 100644
--- a/src/api/oauth.rs
+++ b/src/api/oauth.rs
@@ -12,6 +12,7 @@ use tera::Tera;
use thiserror::Error;
use unic_langid::subtags::Language;
use url::Url;
+use uuid::Uuid;
use crate::models::client::ClientType;
use crate::resources::{languages, templates};
@@ -312,6 +313,10 @@ enum GrantType {
ClientCredentials {
scope: Option<Box<str>>,
},
+ RefreshToken {
+ refresh_token: Box<str>,
+ scope: Option<Box<str>>,
+ },
#[serde(other)]
Unsupported,
}
@@ -434,6 +439,14 @@ impl TokenError {
),
}
}
+
+ fn bad_refresh_token(err: VerifyJwtError) -> Self {
+ Self {
+ status_code: StatusCode::BAD_REQUEST,
+ error: TokenErrorType::InvalidGrant,
+ error_description: err.to_string().into_boxed_str(),
+ }
+ }
}
impl ResponseError for TokenError {
@@ -604,6 +617,62 @@ async fn token(
.insert_header((header::PRAGMA, "no-cache"))
.json(response)
}
+ GrantType::RefreshToken {
+ refresh_token,
+ scope,
+ } => {
+ let client_id: Option<Uuid>;
+ if let Some(authorization) = authorization {
+ let client_alias = authorization.username();
+ let Some(id) = db::get_client_id_by_alias(db, client_alias).await.unwrap() else {
+ return TokenError::client_not_found(client_alias).error_response();
+ };
+ client_id = Some(id);
+ } else {
+ client_id = None;
+ }
+
+ let claims =
+ match jwt::verify_refresh_token(db, &refresh_token, self_id, client_id).await {
+ Ok(claims) => claims,
+ Err(e) => {
+ let e = e.unwrap();
+ return TokenError::bad_refresh_token(e).error_response();
+ }
+ };
+
+ let scope = if let Some(scope) = scope {
+ if !scopes::is_subset_of(&scope, claims.scopes()) {
+ return TokenError::excessive_scope().error_response();
+ }
+
+ scope
+ } else {
+ claims.scopes().into()
+ };
+
+ let exp_time = Duration::hours(1);
+ let access_token = jwt::Claims::refreshed_access_token(db, &claims, exp_time)
+ .await
+ .unwrap();
+ let refresh_token = jwt::Claims::refresh_token(db, &claims).await.unwrap();
+
+ let access_token = access_token.to_jwt().unwrap();
+ let refresh_token = Some(refresh_token.to_jwt().unwrap());
+ let expires_in = exp_time.num_seconds();
+
+ let response = TokenResponse {
+ access_token,
+ token_type,
+ expires_in,
+ refresh_token,
+ scope,
+ };
+ HttpResponse::Ok()
+ .insert_header(cache_control)
+ .insert_header((header::PRAGMA, "no-cache"))
+ .json(response)
+ }
_ => TokenError::unsupported_grant_type().error_response(),
}
}