Add openidconnect authentication demo (#1500)
* Add openidconnect authentication demo * use_atom_ref usage to have a read/write handle on the atom * Use default * Code rewrite to better reflect the authentication flow * Use the env macro instead of the build.rs to load env variables * Add env variables * Remove unnecessary dependency * Add env variables to the root workspace * Update readme * Bump openidconnect version * Use props to pass the client to the child components * Code clean up --------- Co-authored-by: Truong Tan Dat <truongt@igbmc.fr>
This commit is contained in:
1 parent
1cf8f71368
commit
b836851d02
21 files changed
+736
No files matched your search
@@ -0,0 +1,86 @@
|
||||
use crate::{
|
||||
oidc::{token_response, AuthRequestState, AuthTokenState},
|
||||
router::Route,
|
||||
storage::PersistentWrite,
|
||||
DIOXUS_FRONT_URL, FERMI_AUTH_REQUEST, FERMI_AUTH_TOKEN, FERMI_CLIENT,
|
||||
};
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_router::prelude::{Link, NavigationTarget};
|
||||
use fermi::*;
|
||||
use openidconnect::{OAuth2TokenResponse, TokenResponse};
|
||||
|
||||
#[component]
|
||||
pub fn Login(cx: Scope, query_string: String) -> Element {
|
||||
let fermi_client = use_atom_ref(cx, &FERMI_CLIENT);
|
||||
let fermi_auth_token = use_atom_ref(cx, &FERMI_AUTH_TOKEN);
|
||||
let home_url: NavigationTarget<Route> = DIOXUS_FRONT_URL.parse().unwrap();
|
||||
let fermi_auth_request = use_atom_ref(cx, &FERMI_AUTH_REQUEST);
|
||||
let client = fermi_client.read().oidc_client.clone();
|
||||
let auth_token_read = fermi_auth_token.read().clone();
|
||||
cx.render(match (client, auth_token_read) {
|
||||
(Some(client_props), Some(auth_token_read)) => {
|
||||
match (auth_token_read.id_token, auth_token_read.refresh_token) {
|
||||
(Some(_id_token), Some(_refresh_token)) => {
|
||||
rsx! {
|
||||
div { "Sign in successful" }
|
||||
Link { to: home_url, "Go back home" }
|
||||
}
|
||||
}
|
||||
// If the refresh token is set but not the id_token, there was an error, we just go back home and reset their value
|
||||
(None, Some(_)) | (Some(_), None) => {
|
||||
rsx! {
|
||||
div { "Error while attempting to log in" }
|
||||
Link {
|
||||
to: home_url,
|
||||
onclick: move |_| {
|
||||
AuthTokenState::persistent_set(fermi_auth_token, Some(AuthTokenState::default()));
|
||||
AuthRequestState::persistent_set(
|
||||
fermi_auth_request,
|
||||
Some(AuthRequestState::default()),
|
||||
);
|
||||
},
|
||||
"Go back home"
|
||||
}
|
||||
}
|
||||
}
|
||||
(None, None) => {
|
||||
let mut query_pairs = form_urlencoded::parse(query_string.as_bytes());
|
||||
let code_pair = query_pairs.find(|(key, _value)| key == "code");
|
||||
match code_pair {
|
||||
Some((_key, code)) => {
|
||||
let auth_code = code.to_string();
|
||||
let token_response_spawn = move ||{
|
||||
cx.spawn({
|
||||
let fermi_auth_token = fermi_auth_token.to_owned();
|
||||
async move {
|
||||
let token_response_result = token_response(client_props.client, auth_code).await;
|
||||
match token_response_result{
|
||||
Ok(token_response) => {
|
||||
let id_token = token_response.id_token().unwrap();
|
||||
AuthTokenState::persistent_set(&fermi_auth_token, Some(AuthTokenState {
|
||||
id_token: Some(id_token.clone()),
|
||||
refresh_token: token_response.refresh_token().cloned()
|
||||
}));
|
||||
}
|
||||
Err(error) => {
|
||||
log::warn!{"{error}"};
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
token_response_spawn();
|
||||
rsx!{ div {} }
|
||||
}
|
||||
None => {
|
||||
rsx! { div { "No code provided" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(_, _) => {
|
||||
rsx! {{}}
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user