Compare commits
36 Commits
renovate/l
...
master
Author | SHA1 | Date | |
---|---|---|---|
c9d41f2517 | |||
1a1a41d5dc | |||
d01311abf1 | |||
a73ad4bf41 | |||
4a248e84ac | |||
e650fe0c29 | |||
473abb2d38 | |||
1b743c86bf | |||
8c25e2aa4c | |||
f7e4eb955c | |||
7d521ef040 | |||
c59e7b96db | |||
a0d204ad09 | |||
a06be2e889 | |||
42862aea7f | |||
8173ac5bc1 | |||
79a00ff7ad | |||
f2e4d82f87 | |||
022073f26a | |||
c22fcdab74 | |||
672267d521 | |||
c26a3af253 | |||
84d69de09b | |||
76faa33c4e | |||
fb0ebde748 | |||
e0f33c133b | |||
8a0ef75295 | |||
a4f73db82e | |||
31ad52607f | |||
a201f175a2 | |||
f5eaecc189 | |||
6c18a58c43 | |||
677b4221eb | |||
ae92f8f405 | |||
16083a7624 | |||
09da003f35 |
784
Cargo.lock
generated
784
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -18,13 +18,13 @@ serde_json = "1.0.128"
|
||||
serde_yaml = "0.9.34"
|
||||
env_logger = "0.11.3"
|
||||
serde = { version = "1.0.210", features = ["derive"] }
|
||||
bcrypt = "0.16.0"
|
||||
bcrypt = "0.17.0"
|
||||
uuid = { version = "1.8.0", features = ["v4"] }
|
||||
mime_guess = "2.0.4"
|
||||
askama = "0.12.1"
|
||||
futures-util = "0.3.30"
|
||||
urlencoding = "2.1.3"
|
||||
rand = "0.8.5"
|
||||
rand = "0.9.0"
|
||||
base64 = "0.22.1"
|
||||
jwt-simple = { version = "0.12.10", default-features = false, features = ["pure-rust"] }
|
||||
digest = "0.10.7"
|
||||
|
@ -16,7 +16,7 @@ use crate::constants::*;
|
||||
use crate::controllers::base_controller::{build_fatal_error_page, redirect_user};
|
||||
use crate::data::action_logger::{Action, ActionLogger};
|
||||
use crate::data::app_config::AppConfig;
|
||||
use crate::data::client::{AdditionalClaims, AuthenticationFlow, ClientID, ClientManager};
|
||||
use crate::data::client::{AdditionalClaims, ClientID, ClientManager};
|
||||
use crate::data::code_challenge::CodeChallenge;
|
||||
use crate::data::current_user::CurrentUser;
|
||||
use crate::data::id_token::IdToken;
|
||||
@ -50,7 +50,9 @@ pub async fn get_configuration(req: HttpRequest) -> impl Responder {
|
||||
host
|
||||
);
|
||||
|
||||
HttpResponse::Ok().json(OpenIDConfig {
|
||||
HttpResponse::Ok()
|
||||
.insert_header(("access-control-allow-origin", "*"))
|
||||
.json(OpenIDConfig {
|
||||
issuer: AppConfig::get().website_origin.clone(),
|
||||
authorization_endpoint: AppConfig::get().full_url(AUTHORIZE_URI),
|
||||
token_endpoint: curr_origin.clone() + TOKEN_URI,
|
||||
@ -218,8 +220,8 @@ pub async fn authorize(
|
||||
));
|
||||
}
|
||||
|
||||
match (client.auth_flow(), query.response_type.as_str()) {
|
||||
(AuthenticationFlow::AuthorizationCode, "code") => {
|
||||
match (client.has_secret(), query.response_type.as_str()) {
|
||||
(_, "code") => {
|
||||
// Save all authentication information in memory
|
||||
let session = Session {
|
||||
session_id: SessionID(rand_str(OPEN_ID_SESSION_LEN)),
|
||||
@ -261,7 +263,8 @@ pub async fn authorize(
|
||||
.finish())
|
||||
}
|
||||
|
||||
(AuthenticationFlow::Implicit, "id_token") => {
|
||||
// id_token is available only if user has no secret configured
|
||||
(false, "id_token") => {
|
||||
let id_token = IdToken {
|
||||
issuer: AppConfig::get().website_origin.to_string(),
|
||||
subject_identifier: user.uid.0.clone(),
|
||||
@ -293,11 +296,11 @@ pub async fn authorize(
|
||||
.finish())
|
||||
}
|
||||
|
||||
(flow, code) => {
|
||||
(secret, code) => {
|
||||
log::warn!(
|
||||
"For client {:?}, configured with flow {:?}, made request with code {}",
|
||||
"For client {:?}, configured with secret {:?}, made request with code {}",
|
||||
client.id,
|
||||
flow,
|
||||
secret,
|
||||
code
|
||||
);
|
||||
Ok(error_redirect(
|
||||
@ -366,9 +369,7 @@ pub async fn token(
|
||||
let (client_id, client_secret) =
|
||||
match (&query.client_id, &query.client_secret, authorization_header) {
|
||||
// post authentication
|
||||
(Some(client_id), Some(client_secret), None) => {
|
||||
(client_id.clone(), client_secret.to_string())
|
||||
}
|
||||
(Some(client_id), client_secret, None) => (client_id.clone(), client_secret.clone()),
|
||||
|
||||
// Basic authentication
|
||||
(_, None, Some(v)) => {
|
||||
@ -399,8 +400,8 @@ pub async fn token(
|
||||
.to_string();
|
||||
|
||||
match decode.split_once(':') {
|
||||
None => (ClientID(decode), "".to_string()),
|
||||
Some((id, secret)) => (ClientID(id.to_string()), secret.to_string()),
|
||||
None => (ClientID(decode), None),
|
||||
Some((id, secret)) => (ClientID(id.to_string()), Some(secret.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,7 +419,7 @@ pub async fn token(
|
||||
.ok_or_else(|| ErrorUnauthorized("Client not found"))?;
|
||||
|
||||
// Retrieving token requires the client to have a defined secret
|
||||
if client.secret != Some(client_secret) {
|
||||
if client.secret != client_secret {
|
||||
return Ok(error_response(
|
||||
&query,
|
||||
"invalid_request",
|
||||
@ -608,8 +609,9 @@ pub async fn token(
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.append_header(("Cache-Control", "no-store"))
|
||||
.append_header(("Pragam", "no-cache"))
|
||||
.insert_header(("Cache-Control", "no-store"))
|
||||
.insert_header(("Pragma", "no-cache"))
|
||||
.insert_header(("access-control-allow-origin", "*"))
|
||||
.json(token_response))
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,6 @@ use std::collections::HashMap;
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
|
||||
pub struct ClientID(pub String);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum AuthenticationFlow {
|
||||
AuthorizationCode,
|
||||
Implicit,
|
||||
}
|
||||
|
||||
pub type AdditionalClaims = HashMap<String, Value>;
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
@ -61,12 +55,9 @@ impl PartialEq for Client {
|
||||
impl Eq for Client {}
|
||||
|
||||
impl Client {
|
||||
/// Get the client authentication flow
|
||||
pub fn auth_flow(&self) -> AuthenticationFlow {
|
||||
match self.secret {
|
||||
None => AuthenticationFlow::Implicit,
|
||||
Some(_) => AuthenticationFlow::AuthorizationCode,
|
||||
}
|
||||
/// Check if the client has a secret defined
|
||||
pub fn has_secret(&self) -> bool {
|
||||
self.secret.is_some()
|
||||
}
|
||||
|
||||
/// Process a single claim value
|
||||
|
@ -21,7 +21,7 @@ pub struct TotpKey {
|
||||
impl TotpKey {
|
||||
/// Generate a new TOTP key
|
||||
pub fn new_random() -> Self {
|
||||
let random_bytes = rand::thread_rng().gen::<[u8; 20]>();
|
||||
let random_bytes = rand::rng().random::<[u8; 20]>();
|
||||
Self {
|
||||
encoded: base32::encode(BASE32_ALPHABET, &random_bytes),
|
||||
}
|
||||
|
@ -1,14 +1,9 @@
|
||||
use lazy_regex::regex_find;
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
use rand::distr::{Alphanumeric, SampleString};
|
||||
|
||||
/// Generate a random string of a given size
|
||||
pub fn rand_str(len: usize) -> String {
|
||||
rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.map(char::from)
|
||||
.take(len)
|
||||
.collect()
|
||||
Alphanumeric.sample_string(&mut rand::rng(), len)
|
||||
}
|
||||
|
||||
/// Parse environment variables
|
||||
|
Loading…
x
Reference in New Issue
Block a user