Allow redirect url path when user signs in #316
@@ -1,7 +0,0 @@
|
|||||||
FLEET_AUTH_ISSUER_URL=
|
|
||||||
FLEET_AUTH_AUTHORIZE_URL=
|
|
||||||
FLEET_AUTH_TOKEN_URL=
|
|
||||||
FLEET_AUTH_CLIENT_ID=
|
|
||||||
FLEET_AUTH_REDIRECT_URI=
|
|
||||||
FLEET_AUTH_SCOPE=
|
|
||||||
FLEET_AUTH_TRUSTED_AUDIENCES=
|
|
||||||
@@ -759,7 +759,7 @@ pub async fn mint_access_token(
|
|||||||
access_token: String,
|
access_token: String,
|
||||||
}
|
}
|
||||||
let tr: TokenResponse = resp.json().await.context("parse token response")?;
|
let tr: TokenResponse = resp.json().await.context("parse token response")?;
|
||||||
if std::env::var("FLEET_AUTH_CALLOUT_DEBUG_TOKENS").is_ok()
|
if std::env::var("HARMONY_SSO_CALLOUT_DEBUG_TOKENS").is_ok()
|
||||||
&& let Some(payload_b64) = tr.access_token.split('.').nth(1)
|
&& let Some(payload_b64) = tr.access_token.split('.').nth(1)
|
||||||
{
|
{
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
export BASE_URL=http://localhost:18080
|
export BASE_URL=http://localhost:18080
|
||||||
export FLEET_AUTH_ZITADEL_BASE=https://sso-stg.cb1.nationtech.io
|
export HARMONY_SSO_ZITADEL_BASE=https://sso-stg.cb1.nationtech.io
|
||||||
export FLEET_AUTH_CLIENT_ID=372626218874372917
|
export HARMONY_SSO_CLIENT_ID=372626218874372917
|
||||||
export FLEET_AUTH_SCOPE="openid profile email"
|
export HARMONY_SSO_SCOPE="openid profile email"
|
||||||
export FLEET_AUTH_LOGOUT_REDIRECT_URI="http://localhost:18080/"
|
export HARMONY_SSO_LOGOUT_REDIRECT_URI="http://localhost:18080/"
|
||||||
export FLEET_OPERATOR_COOKIE_KEY_B64=6eKVpj88jwIcmaJajPfohdaIXhSPlfYCrHaOfymTcIWBAIadvhg7NHpMo5vPSMy90vac3cq2liWe1naSgkbaYg==
|
export HARMONY_COOKIE_KEY_B64=6eKVpj88jwIcmaJajPfohdaIXhSPlfYCrHaOfymTcIWBAIadvhg7NHpMo5vPSMy90vac3cq2liWe1naSgkbaYg==
|
||||||
export FLEET_AUTH_TRUSTED_AUDIENCES=371639797493596981,371683318111994677,372626218874372917,371639797157987125
|
export HARMONY_SSO_TRUSTED_AUDIENCES=371639797493596981,371683318111994677,372626218874372917,371639797157987125
|
||||||
export BASE_URL=http://localhost:18080
|
export BASE_URL=http://localhost:18080
|
||||||
export RUST_LOG=debug
|
export RUST_LOG=debug
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ use base64::engine::general_purpose::URL_SAFE_NO_PAD;
|
|||||||
use crate::config::ZitadelAuthConfig;
|
use crate::config::ZitadelAuthConfig;
|
||||||
use crate::jwks::JwksCache;
|
use crate::jwks::JwksCache;
|
||||||
use crate::login::{
|
use crate::login::{
|
||||||
AuthCallbackQuery, RawAuthCallbackQuery, TokenResponse, build_login_attempt, build_logout_url,
|
AuthCallbackQuery, LoginQuery, RawAuthCallbackQuery, TokenResponse, build_login_attempt,
|
||||||
exchange_code_for_token, jwt_exp, validate_callback_state,
|
build_logout_url, exchange_code_for_token, jwt_exp, valid_next, validate_callback_state,
|
||||||
};
|
};
|
||||||
use crate::session::LoginAttemptCookie;
|
use crate::session::LoginAttemptCookie;
|
||||||
|
|
||||||
@@ -23,8 +23,9 @@ pub const HARMONY_SESSION_COOKIE: &str = "harmony_fleet_session";
|
|||||||
pub async fn login_handler(
|
pub async fn login_handler(
|
||||||
jar: PrivateCookieJar,
|
jar: PrivateCookieJar,
|
||||||
State(config): State<ZitadelAuthConfig>,
|
State(config): State<ZitadelAuthConfig>,
|
||||||
|
Query(query): Query<LoginQuery>,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
match build_login_response(jar, &config) {
|
match build_login_response(jar, &config, query) {
|
||||||
Ok(r) => r.into_response(),
|
Ok(r) => r.into_response(),
|
||||||
Err(e) => auth_error_response(e),
|
Err(e) => auth_error_response(e),
|
||||||
}
|
}
|
||||||
@@ -33,9 +34,16 @@ pub async fn login_handler(
|
|||||||
fn build_login_response(
|
fn build_login_response(
|
||||||
jar: PrivateCookieJar,
|
jar: PrivateCookieJar,
|
||||||
config: &ZitadelAuthConfig,
|
config: &ZitadelAuthConfig,
|
||||||
|
query: LoginQuery,
|
||||||
) -> Result<impl IntoResponse> {
|
) -> Result<impl IntoResponse> {
|
||||||
let attempt = build_login_attempt(config)?;
|
let attempt = build_login_attempt(config)?;
|
||||||
let cookie_payload = LoginAttemptCookie::from(&attempt);
|
let mut cookie_payload = LoginAttemptCookie::from(&attempt);
|
||||||
|
cookie_payload.next = Some(
|
||||||
|
query
|
||||||
|
.next
|
||||||
|
.filter(|next| valid_next(next))
|
||||||
|
.unwrap_or_else(|| "/".to_string()),
|
||||||
|
);
|
||||||
let cookie_value = URL_SAFE_NO_PAD.encode(serde_json::to_vec(&cookie_payload)?);
|
let cookie_value = URL_SAFE_NO_PAD.encode(serde_json::to_vec(&cookie_payload)?);
|
||||||
|
|
||||||
let mut builder = Cookie::build((LOGIN_ATTEMPT_COOKIE, cookie_value))
|
let mut builder = Cookie::build((LOGIN_ATTEMPT_COOKIE, cookie_value))
|
||||||
@@ -113,7 +121,12 @@ async fn build_callback_response(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let session_jar = session_jar.add(session_cookie(&tokens, config));
|
let session_jar = session_jar.add(session_cookie(&tokens, config));
|
||||||
Ok((jar, session_jar, Redirect::to("/")).into_response())
|
let next = attempt
|
||||||
|
.next
|
||||||
|
.as_deref()
|
||||||
|
.filter(|next| valid_next(next))
|
||||||
|
.unwrap_or("/");
|
||||||
|
Ok((jar, session_jar, Redirect::to(next)).into_response())
|
||||||
}
|
}
|
||||||
AuthCallbackQuery::Failure {
|
AuthCallbackQuery::Failure {
|
||||||
error,
|
error,
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ impl ZitadelAuthConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ZITADEL_BASE_ENV: &str = "FLEET_AUTH_ZITADEL_BASE";
|
pub const ZITADEL_BASE_ENV: &str = "HARMONY_SSO_ZITADEL_BASE";
|
||||||
pub const BASE_URL_ENV: &str = "BASE_URL";
|
pub const BASE_URL_ENV: &str = "BASE_URL";
|
||||||
pub const CLIENT_ID_ENV: &str = "FLEET_AUTH_CLIENT_ID";
|
pub const CLIENT_ID_ENV: &str = "HARMONY_SSO_CLIENT_ID";
|
||||||
pub const SCOPE_ENV: &str = "FLEET_AUTH_SCOPE";
|
pub const SCOPE_ENV: &str = "HARMONY_SSO_SCOPE";
|
||||||
pub const TRUSTED_AUDIENCES_ENV: &str = "FLEET_AUTH_TRUSTED_AUDIENCES";
|
pub const TRUSTED_AUDIENCES_ENV: &str = "HARMONY_SSO_TRUSTED_AUDIENCES";
|
||||||
pub const LOGOUT_REDIRECT_URI_ENV: &str = "FLEET_AUTH_LOGOUT_REDIRECT_URI";
|
pub const LOGOUT_REDIRECT_URI_ENV: &str = "HARMONY_SSO_LOGOUT_REDIRECT_URI";
|
||||||
pub const COOKIE_KEY_ENV: &str = "FLEET_OPERATOR_COOKIE_KEY_B64";
|
pub const COOKIE_KEY_ENV: &str = "HARMONY_COOKIE_KEY_B64";
|
||||||
|
|
||||||
pub fn config_from_env() -> ZitadelAuthConfig {
|
pub fn config_from_env() -> ZitadelAuthConfig {
|
||||||
ZitadelAuthConfig {
|
ZitadelAuthConfig {
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ pub use config::{
|
|||||||
pub use jwks::JwksCache;
|
pub use jwks::JwksCache;
|
||||||
|
|
||||||
pub use login::{
|
pub use login::{
|
||||||
AuthCallbackQuery, LoginAttempt, RawAuthCallbackQuery, TokenResponse, ValidatedUser,
|
AuthCallbackQuery, LoginAttempt, LoginQuery, RawAuthCallbackQuery, TokenResponse, ValidatedUser,
|
||||||
build_login_attempt, build_logout_url, exchange_code_for_token, jwt_exp,
|
build_login_attempt, build_logout_url, exchange_code_for_token, jwt_exp,
|
||||||
validate_callback_state, validate_id_token,
|
valid_next, validate_callback_state, validate_id_token,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use session::{LoginAttemptCookie, VerifiedSession};
|
pub use session::{LoginAttemptCookie, VerifiedSession};
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ pub struct TokenResponse {
|
|||||||
pub expires_in: Option<u64>,
|
pub expires_in: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct LoginQuery {
|
||||||
|
pub next: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct RawAuthCallbackQuery {
|
pub struct RawAuthCallbackQuery {
|
||||||
pub code: Option<String>,
|
pub code: Option<String>,
|
||||||
@@ -63,10 +68,15 @@ impl From<&LoginAttempt> for LoginAttemptCookie {
|
|||||||
state: attempt.state.clone(),
|
state: attempt.state.clone(),
|
||||||
pkce_code_verifier: attempt.pkce_code_verifier.clone(),
|
pkce_code_verifier: attempt.pkce_code_verifier.clone(),
|
||||||
nonce: attempt.nonce.clone(),
|
nonce: attempt.nonce.clone(),
|
||||||
|
next: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn valid_next(next: &str) -> bool {
|
||||||
|
next.starts_with('/') && !next.starts_with("//") && !next.chars().any(char::is_control)
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<RawAuthCallbackQuery> for AuthCallbackQuery {
|
impl TryFrom<RawAuthCallbackQuery> for AuthCallbackQuery {
|
||||||
type Error = anyhow::Error;
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
|||||||
@@ -18,4 +18,5 @@ pub struct LoginAttemptCookie {
|
|||||||
pub state: String,
|
pub state: String,
|
||||||
pub pkce_code_verifier: String,
|
pub pkce_code_verifier: String,
|
||||||
pub nonce: String,
|
pub nonce: String,
|
||||||
|
pub next: Option<String>,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user