Standardization or JWT, JWT as URL param

This commit is contained in:
Ara Sadoyan
2025-05-02 16:36:56 +02:00
parent 026ef22c4d
commit 9eca87718b
5 changed files with 62 additions and 12 deletions

7
Cargo.lock generated
View File

@@ -180,6 +180,7 @@ dependencies = [
"sha2",
"tokio",
"tonic",
"urlencoding",
]
[[package]]
@@ -3001,6 +3002,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "utf16_iter"
version = "1.0.5"

View File

@@ -29,4 +29,5 @@ tonic = "0.13.0"
#uuid = { version = "1.16.0", features = ["v4"] }
sha2 = { version = "0.10.8", default-features = false }
base16ct = { version = "0.2.0", features = ["alloc"] }
urlencoding = "2.1.3"

View File

@@ -161,7 +161,8 @@ curl -XPOST --data-binary @./etc/upstreams.txt 127.0.0.1:3000/conf
- Only one method can be active at a time.
- `basic` : Standard HTTP Basic Authentication requests.
- `apikey` : Authentication via `x-api-key` header, which should match the value in config.
- `jwt`: JWT authentication implemented vi `x-jwt-token` header.
- `jwt`: JWT authentication implemented via `gazantoken=` url parameter. `/some/url?gazantoken=TOKEN`
- `jwt`: JWT authentication implemented via `Authorization: Bearer <token>` header.
- To obtain JWT token, you should send **generate** request to built in api server's `/jwt` endpoint.
- `masterkey`: should match configured `masterkey` in `main.yaml` and `upstreams.yaml`.
- `owner` : Just a placeholder, can be anything.
@@ -173,7 +174,7 @@ curl -XPOST --data-binary @./etc/upstreams.txt 127.0.0.1:3000/conf
PAYLOAD='{
"masterkey": "910517d9-f9a1-48de-8826-dbadacbd84af-cb6f830e-ab16-47ec-9d8f-0090de732774",
"owner": "valod",
"valid": 1
"valid": 10
}'
TOK=`curl -s -XPOST -H "Content-Type: application/json" -d "$PAYLOAD" http://127.0.0.1:3000/jwt | cut -d '"' -f4`

View File

@@ -6,13 +6,13 @@ globals:
- "Access-Control-Allow-Methods:POST, GET, OPTIONS"
- "Access-Control-Max-Age:86400"
- "X-Custom-Header:Something Special"
# authorization: # Optional, only one of auth methods below can be active at a time
# - "basic"
# - "zangag:Anhnazand1234"
# - "apikey"
# - "5a28cc4c-ce10-4ff1-824e-743c38835f5c"
# - "jwt"
# - "910517d9-f9a1-48de-8826-dbadacbd84af-cb6f830e-ab16-47ec-9d8f-0090de732774"
authorization: # Optional, only one of auth methods below can be active at a time
# - "basic"
# - "zangag:Anhnazand1234"
# - "apikey"
# - "5a28cc4c-ce10-4ff1-824e-743c38835f5c"
- "jwt"
- "910517d9-f9a1-48de-8826-dbadacbd84af-cb6f830e-ab16-47ec-9d8f-0090de732774"
consul: # If the provider is consul. Otherwise ignored
servers:
- "http://master1:8500"
@@ -57,7 +57,12 @@ upstreams: # If provider is files. Otherwise ignored
headers:
- "X-Some-Thing:Yaaaaaaaaaaaaaaa"
servers:
- "192.168.1.1:8000"
- "192.168.1.10:8000"
- "127.0.0.1:8000"
- "127.0.0.2:8000"
- "127.0.0.3:8000"
- "127.0.0.4:8000"
glop.netangels.net:
paths:
"/":

View File

@@ -2,6 +2,8 @@ use crate::utils::jwt::check_jwt;
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use pingora_proxy::Session;
use std::collections::HashMap;
use urlencoding::decode;
trait AuthValidator {
fn validate(&self, session: &Session) -> bool;
@@ -35,9 +37,27 @@ impl AuthValidator for ApiKeyAuth<'_> {
impl AuthValidator for JwtAuth<'_> {
fn validate(&self, session: &Session) -> bool {
let jwtsecret = self.0;
if let Some(header) = session.get_header("x-jwt-token") {
let tok = header.to_str().ok().unwrap();
return check_jwt(tok, jwtsecret);
if let Some(tok) = get_query_param(session, "gazantoken") {
return check_jwt(tok.as_str(), jwtsecret);
}
// if let Some(header) = session.get_header("authorization") {
// let h = header.to_str().ok().unwrap().split(" ").collect::<Vec<_>>();
// match h.len() {
// n => {
// return check_jwt(h[n - 1], jwtsecret);
// }
// }
// }
if let Some(auth_header) = session.get_header("authorization") {
if let Ok(header_str) = auth_header.to_str() {
if let Some((scheme, token)) = header_str.split_once(' ') {
if scheme.eq_ignore_ascii_case("bearer") {
return check_jwt(token, jwtsecret);
}
}
}
}
false
}
@@ -66,3 +86,19 @@ pub fn authenticate(c: &[String], session: &Session) -> bool {
}
}
}
pub fn get_query_param(session: &Session, key: &str) -> Option<String> {
let query = session.req_header().uri.query()?;
let params: HashMap<_, _> = query
.split('&')
.filter_map(|pair| {
let mut parts = pair.splitn(2, '=');
let k = parts.next()?;
let v = parts.next().unwrap_or(""); // Some params might have no value
Some((k, v))
})
.collect();
params.get(key).map(|v| decode(v).ok()).flatten().map(|s| s.to_string())
}