Skip to content

Commit

Permalink
Merge pull request #79 from go-bazzinga/login-system-workflow-change
Browse files Browse the repository at this point in the history
update_session after login
  • Loading branch information
rosarp-gobazzinga authored Mar 21, 2024
2 parents 617bc24 + fb15ab3 commit 378c6e8
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 23 deletions.
1 change: 1 addition & 0 deletions AppConfig.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ cloudflare_namespace_identifier = ""
google_auth_landing_url = "https://auth.yral.com/google_oauth2_response"
google_client_id = ""
google_client_secret = ""
google_user_info_url = "https://www.googleapis.com/oauth2/v3/userinfo"
3 changes: 2 additions & 1 deletion src/auth/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ pub async fn get_user_key_pair(
let metadata: Option<HashMap<String, String>> =
read_metadata(&public_key, cloudflare_config).await;
if private_key.is_none() || metadata.is_none() {
info!("private_key or metadata is empty");
None
} else {
let metadata = metadata.unwrap();
Expand All @@ -185,7 +186,7 @@ pub async fn get_user_key_pair(
let user_key_pair = match user_key_pair {
Some(kp) => kp,
None => {
// generate new user identity
info!("generate new user identity");
let new_key_pair = generate::key_pair().unwrap();
{
let private_key =
Expand Down
80 changes: 75 additions & 5 deletions src/page/auth_init.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use crate::constants;
use leptos::logging::log;
use leptos::{
logging::{error, warn},
logging::{error, log, warn},
*,
};
use leptos_use::{use_event_listener, use_window};
use reqwest::Url;
use wasm_bindgen::JsValue;

/// When user wants to login this opens in iframe
#[component]
pub fn staging() -> impl IntoView {
use reqwest::Url;
use wasm_bindgen::JsValue;

let url = create_local_resource(move || (), |_| get_redirect_url());
create_effect(move |_| match url.get() {
Some(Ok(u)) => {
Expand All @@ -32,9 +32,22 @@ pub fn staging() -> impl IntoView {
}
Some(session) => {
log!("session received: {}", session.len());
let message = session.to_owned();
let session = session.to_owned();

let resource = create_local_resource(
move || session.clone(),
|session| update_session(session),
);
create_effect(move |_| match resource.get() {
Some(Ok(())) => {}
Some(Err(_)) => {}
None => {}
});

let parent = use_window().as_ref().unwrap().parent().unwrap().unwrap();
match parent.post_message(
&JsValue::from_str(&session),
&JsValue::from_str(&message),
constants::APP_DOMAIN.as_str(),
) {
Err(error) => error!(
Expand Down Expand Up @@ -90,3 +103,60 @@ pub async fn get_redirect_url() -> Result<String, ServerFnError> {

Ok(url.as_str().to_owned())
}

#[server]
pub async fn update_session(session: String) -> Result<(), ServerFnError> {
use crate::auth::{agent_js, cookie, identity::AppState};
use axum::{http::header, response::IntoResponse};
use axum_extra::extract::{
cookie::{Key, SameSite},
SignedCookieJar,
};
use chrono::{Duration, Utc};
use leptos_axum::ResponseOptions;

let session = serde_json::from_str::<agent_js::SessionResponse>(&session)
.map_err(|e| ServerFnError::new(format!("{:?}", e)))?;
let app_state =
use_context::<AppState>().ok_or_else(|| ServerFnError::new("Context not found!"))?;
let mut signed_jar: SignedCookieJar =
leptos_axum::extract_with_state::<SignedCookieJar<Key>, AppState>(&app_state).await?;

let cookie_domain = app_state.cookie_domain.host_str().unwrap().to_owned();

let user_cookie = cookie::create_cookie(
"user_identity",
session.user_identity.to_owned(),
cookie_domain.to_owned(),
SameSite::None,
)
.await;
signed_jar = signed_jar.add(user_cookie);

let expiration = match session.delegation_identity._delegation.delegations.get(0) {
Some(signed_delegation) => signed_delegation.delegation.expiration.to_owned(),
None => {
let expiration = Utc::now() + Duration::days(30);
expiration
.timestamp_nanos_opt()
.unwrap()
.unsigned_abs()
.to_string()
}
};

let exp_cookie =
cookie::create_cookie("expiration", expiration, cookie_domain, SameSite::None).await;
signed_jar = signed_jar.add(exp_cookie);

let signed_jar_into_response = signed_jar.into_response();
let response_options = expect_context::<ResponseOptions>();
for header_value in signed_jar_into_response
.headers()
.get_all(header::SET_COOKIE)
{
response_options.append_header(header::SET_COOKIE, header_value.clone());
}

Ok(())
}
31 changes: 17 additions & 14 deletions src/providers/google.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::auth::agent_js::SessionResponse;
use cfg_if::cfg_if;
use leptos::*;
use leptos_router::{use_query, Params};
use wasm_bindgen::JsCast;

cfg_if! {
if #[cfg(feature="ssr")] {
Expand Down Expand Up @@ -126,7 +125,7 @@ async fn google_verify_response(
) -> Result<SessionResponse, ServerFnError> {
let app_state =
use_context::<AppState>().ok_or_else(|| ServerFnError::new("Context not found!"))?;
let mut jar: PrivateCookieJar =
let mut private_jar: PrivateCookieJar =
leptos_axum::extract_with_state::<PrivateCookieJar<Key>, AppState>(&app_state).await?;
let mut signed_jar: SignedCookieJar =
leptos_axum::extract_with_state::<SignedCookieJar<Key>, AppState>(&app_state).await?;
Expand All @@ -137,40 +136,38 @@ async fn google_verify_response(
}
.ok_or_else(|| ServerFnError::new("User Session not found."))?;

let client = app_state.oauth2_client;
let csrf_token = jar
let csrf_token = private_jar
.get("csrf_token")
.map(|cookie| cookie.value().to_owned())
.ok_or_else(|| ServerFnError::new("No CSRF token found!"))?;
if !csrf_token.eq(&provided_csrf) {
return Err(ServerFnError::new("Invalid CSRF token!"));
}
jar = jar.remove(Cookie::from("csrf_token"));
private_jar = private_jar.remove(Cookie::from("csrf_token"));
info!("aftr csrf: {}", csrf_token.len());
let pkce_verifier = jar
let pkce_verifier = private_jar
.get("pkce_verifier")
.map(|cookie| cookie.value().to_owned())
.ok_or_else(|| ServerFnError::new("No Verifier found!"))?;
jar = jar.remove(Cookie::from("pkce_verifier"));
let jar_into_response = jar.into_response();
private_jar = private_jar.remove(Cookie::from("pkce_verifier"));

// TODO: remove cookies
let jar_into_response = private_jar.into_response();
let response_options = expect_context::<ResponseOptions>();
for header_value in jar_into_response.headers().get_all(header::SET_COOKIE) {
response_options.append_header(header::SET_COOKIE, header_value.clone());
response_options.insert_header(header::SET_COOKIE, header_value.clone());
}
info!("aftr pkce: {}", pkce_verifier.len());

let pkce_verifier = PkceCodeVerifier::new(pkce_verifier);
let client = app_state.oauth2_client;
let token_result = client
.exchange_code(AuthorizationCode::new(code.clone()))
.set_pkce_verifier(pkce_verifier)
.request_async(async_http_client)
.await?;

info!(
"token_result: f you need any inputs from my side.{:?}",
&token_result
);
info!("token_result: {:?}", &token_result);
let access_token = token_result.access_token().secret();
// TODO: check against delegate session. set whichever is lower
let expires_in = token_result.expires_in().unwrap().as_secs();
Expand Down Expand Up @@ -209,6 +206,8 @@ async fn google_verify_response(
if !user_identity.eq(&user_public_key) {
// returning user with different temporary session
// delete current temp session
// TODO: check if pubkey with google exists if not use this
info!("Deleting: {}", user_identity);
let _ignore = delete_kv(&user_identity, &app_state.cloudflare_config).await;
Some(user_public_key)
} else {
Expand All @@ -229,6 +228,10 @@ async fn google_verify_response(
let session_response = get_session_response(user_identity, &app_state.cloudflare_config).await;
let cookie_domain = app_state.cookie_domain.host_str().unwrap().to_owned();

info!(
"user_identity in session: {}",
session_response.user_identity
);
let user_cookie = cookie::create_cookie(
"user_identity",
session_response.user_identity.to_owned(),
Expand All @@ -253,7 +256,7 @@ async fn google_verify_response(
.headers()
.get_all(header::SET_COOKIE)
{
response_options.append_header(header::SET_COOKIE, header_value.clone());
response_options.insert_header(header::SET_COOKIE, header_value.clone());
}

Ok(session_response)
Expand Down
9 changes: 6 additions & 3 deletions src/store/cloudflare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub async fn read_kv(key_name: &str, cloudflare_config: &ApiClientConfig) -> Opt
match cloudflare_config.cloudflare_client.send(end_point).await {
Ok(response) => Some(response),
Err(error) => {
warn!("Error read_kv: {}", error);
warn!("key: {}, Error read_kv: {}", key_name, error);
None
}
}
Expand All @@ -35,13 +35,16 @@ pub async fn read_metadata(
false => {
warn!("Error read_metadata: ");
for error in response.errors {
warn!("code: {}, message: {}", error.code, error.message);
warn!(
"key: {}, code: {}, message: {}",
key_name, error.code, error.message
);
}
None
}
},
Err(error) => {
warn!("Error read_metadata: {}", error);
warn!("key: {}, Error read_metadata: {}", key_name, error);
None
}
}
Expand Down

0 comments on commit 378c6e8

Please sign in to comment.