Skip to content

Commit

Permalink
Shield OIDC: Add user info support
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielleHuisman committed Dec 26, 2024
1 parent 8a84be0 commit c5461e9
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 24 deletions.
15 changes: 7 additions & 8 deletions examples/leptos-actix/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use leptos::prelude::*;
use leptos_meta::{provide_meta_context, MetaTags, Title};
use leptos_router::{
components::{Route, Router, Routes},
components::{Route, Router, Routes, A},
path,
};
use shield_leptos::routes::SignIn;
Expand Down Expand Up @@ -29,11 +29,11 @@ pub fn App() -> impl IntoView {
provide_meta_context();

view! {
<Title text="Welcome to Leptos"/>
<Title text="Shield Leptos Actix Example"/>

<Router>
<main>
<Routes fallback=|| "Page not found.".into_view()>
<Routes fallback=|| "Not found.".into_view()>
<Route path=path!("") view=HomePage/>

<Route path=path!("/auth/sign-in") view=SignIn />
Expand All @@ -45,11 +45,10 @@ pub fn App() -> impl IntoView {

#[component]
fn HomePage() -> impl IntoView {
let count = RwSignal::new(0);
let on_click = move |_| *count.write() += 1;

view! {
<h1>"Welcome to Leptos!"</h1>
<button on:click=on_click>"Click Me: " {count}</button>
<h1>"Shield Leptos Actix Example"</h1>
<A href="/auth/sign-in">
<button>"Sign in"</button>
</A>
}
}
15 changes: 7 additions & 8 deletions examples/leptos-axum/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use leptos::prelude::*;
use leptos_meta::{provide_meta_context, MetaTags, Title};
use leptos_router::{
components::{Route, Router, Routes},
components::{Route, Router, Routes, A},
path,
};
use shield_leptos::routes::SignIn;
Expand Down Expand Up @@ -29,11 +29,11 @@ pub fn App() -> impl IntoView {
provide_meta_context();

view! {
<Title text="Welcome to Leptos"/>
<Title text="Shield Leptos Axum Example"/>

<Router>
<main>
<Routes fallback=|| "Page not found.".into_view()>
<Routes fallback=|| "Not found.".into_view()>
<Route path=path!("") view=HomePage/>

<Route path=path!("/auth/sign-in") view=SignIn />
Expand All @@ -45,11 +45,10 @@ pub fn App() -> impl IntoView {

#[component]
fn HomePage() -> impl IntoView {
let count = RwSignal::new(0);
let on_click = move |_| *count.write() += 1;

view! {
<h1>"Welcome to Leptos!"</h1>
<button on:click=on_click>"Click Me: " {count}</button>
<h1>"Shield Leptos Axum Example"</h1>
<A href="/auth/sign-in">
<button>"Sign in"</button>
</A>
}
}
2 changes: 1 addition & 1 deletion examples/leptos-axum/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async fn main() {
let session_store = MemoryStore::default();
let session_layer = SessionManagerLayer::new(session_store)
.with_secure(false)
.with_expiry(Expiry::OnInactivity(Duration::hours(1)));
.with_expiry(Expiry::OnInactivity(Duration::minutes(10)));

// Initialize Shield
let shield = Shield::new(
Expand Down
31 changes: 31 additions & 0 deletions packages/providers/shield-oidc/src/claims.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use openidconnect::{
core::CoreGenderClaim, EmptyAdditionalClaims, IdTokenClaims, SubjectIdentifier, UserInfoClaims,
};

/// Unified interface for [`IdTokenClaims`] and [`UserInfoClaims`].
#[derive(Clone, Debug)]
pub enum Claims {
IdToken(IdTokenClaims<EmptyAdditionalClaims, CoreGenderClaim>),
UserInfo(UserInfoClaims<EmptyAdditionalClaims, CoreGenderClaim>),
}

impl Claims {
pub fn subject(&self) -> &SubjectIdentifier {
match &self {
Claims::IdToken(id_token_claims) => id_token_claims.subject(),
Claims::UserInfo(user_info_claims) => user_info_claims.subject(),
}
}
}

impl From<IdTokenClaims<EmptyAdditionalClaims, CoreGenderClaim>> for Claims {
fn from(value: IdTokenClaims<EmptyAdditionalClaims, CoreGenderClaim>) -> Self {
Self::IdToken(value)
}
}

impl From<UserInfoClaims<EmptyAdditionalClaims, CoreGenderClaim>> for Claims {
fn from(value: UserInfoClaims<EmptyAdditionalClaims, CoreGenderClaim>) -> Self {
Self::UserInfo(value)
}
}
1 change: 1 addition & 0 deletions packages/providers/shield-oidc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod builders;
mod claims;
mod provider;
mod storage;
mod subprovider;
Expand Down
28 changes: 21 additions & 7 deletions packages/providers/shield-oidc/src/provider.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
use async_trait::async_trait;
use openidconnect::{
core::CoreAuthenticationFlow, reqwest::async_http_client, AccessToken, AuthorizationCode,
CsrfToken, Nonce, PkceCodeChallenge, PkceCodeVerifier, Scope, TokenResponse,
core::{CoreAuthenticationFlow, CoreGenderClaim},
reqwest::async_http_client,
AccessToken, AuthorizationCode, CsrfToken, EmptyAdditionalClaims, Nonce, OAuth2TokenResponse,
PkceCodeChallenge, PkceCodeVerifier, Scope, TokenResponse, UserInfoClaims,
};
use shield::{
ConfigurationError, Provider, ProviderError, Response, Session, SessionError, ShieldError,
SignInCallbackRequest, SignInRequest, SignOutRequest, Subprovider,
};

use crate::{storage::OidcStorage, subprovider::OidcSubprovider, OidcProviderPkceCodeChallenge};
use crate::{
claims::Claims, storage::OidcStorage, subprovider::OidcSubprovider,
OidcProviderPkceCodeChallenge,
};

pub const OIDC_PROVIDER_ID: &str = "oidc";

Expand Down Expand Up @@ -201,7 +206,7 @@ impl Provider for OidcProvider {
.await
.map_err(|err| ShieldError::Request(err.to_string()))?;

if let Some(id_token) = token_response.id_token() {
let claims = if let Some(id_token) = token_response.id_token() {
let claims =
id_token
.claims(
Expand All @@ -212,10 +217,19 @@ impl Provider for OidcProvider {
)
.map_err(|err| ShieldError::Verification(err.to_string()))?;

println!("{:?}", claims);
}
Claims::from(claims.clone())
} else {
let claims: UserInfoClaims<EmptyAdditionalClaims, CoreGenderClaim> = client
.user_info(token_response.access_token().to_owned(), None)
.map_err(|err| ConfigurationError::Missing(err.to_string()))?
.request_async(async_http_client)
.await
.map_err(|err| ShieldError::Request(err.to_string()))?;

Claims::from(claims)
};

// let user_info = client.user_info(token_response.access_token(), None)
println!("{:?}\n{:?}", claims.subject(), claims);

// TODO
Ok(Response::Redirect("/".to_owned()))
Expand Down

0 comments on commit c5461e9

Please sign in to comment.