add http method validation on each route + add pubkey tests
This commit is contained in:
parent
1d2924b7ef
commit
8d3651d6fc
@ -45,13 +45,19 @@ expiration_time = 2 # in hours
|
|||||||
```bash
|
```bash
|
||||||
./simple-auth <ini_path>
|
./simple-auth <ini_path>
|
||||||
|
|
||||||
|
# get a JWT
|
||||||
curl http://<ip>:<port>/get/ -d '{"username":"<user>", "password":"<password>"}'
|
curl http://<ip>:<port>/get/ -d '{"username":"<user>", "password":"<password>"}'
|
||||||
# should returned
|
# should returned
|
||||||
{"token":"<header>.<payload>.<signature>"}
|
{"token":"<header>.<payload>.<signature>"}
|
||||||
|
|
||||||
|
# validate a JWT
|
||||||
curl http://<ip>:<port>/validate/ -d '{"token":"<header>.<payload>.<signature>"}'
|
curl http://<ip>:<port>/validate/ -d '{"token":"<header>.<payload>.<signature>"}'
|
||||||
# should returned (if valid)
|
# should returned (if valid)
|
||||||
{"valid":"true"}
|
{"valid":"true"}
|
||||||
|
|
||||||
|
# get the public key for local validation
|
||||||
|
curl http://<ip>:<port>/pubkey/
|
||||||
|
{"pubkey":"<b64_encoded_public_key>"}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Test
|
## Test
|
||||||
|
|||||||
@ -217,6 +217,10 @@ impl HTTPRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_method(&self) -> String {
|
||||||
|
self.start_line.method.clone()
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn is_valid(&self) -> bool {
|
pub fn is_valid(&self) -> bool {
|
||||||
return self.start_line.is_valid();
|
return self.start_line.is_valid();
|
||||||
|
|||||||
@ -14,7 +14,11 @@ const GET_ROUTE: &'static str = "/get/";
|
|||||||
const VALIDATE_ROUTE: &'static str = "/validate/";
|
const VALIDATE_ROUTE: &'static str = "/validate/";
|
||||||
const PUBKEY_ROUTE: &'static str = "/pubkey/";
|
const PUBKEY_ROUTE: &'static str = "/pubkey/";
|
||||||
|
|
||||||
async fn handle_get(request: HTTPRequest, config: Config) -> HTTPResponse {
|
async fn handle_get(request: HTTPRequest, config: Config, method: &str) -> HTTPResponse {
|
||||||
|
if method.trim().to_lowercase() != "post" {
|
||||||
|
return HTTPResponse::as_400();
|
||||||
|
}
|
||||||
|
|
||||||
let mut store = FileStore::new(config.filestore_path.clone());
|
let mut store = FileStore::new(config.filestore_path.clone());
|
||||||
match &request.body {
|
match &request.body {
|
||||||
Some(ref b) => {
|
Some(ref b) => {
|
||||||
@ -48,7 +52,11 @@ async fn handle_get(request: HTTPRequest, config: Config) -> HTTPResponse {
|
|||||||
/// validates the token by checking:
|
/// validates the token by checking:
|
||||||
/// * expiration time
|
/// * expiration time
|
||||||
/// * signature
|
/// * signature
|
||||||
async fn handle_validate(request: HTTPRequest, config: Config) -> HTTPResponse {
|
async fn handle_validate(request: HTTPRequest, config: Config, method: &str) -> HTTPResponse {
|
||||||
|
if request.get_method().trim().to_lowercase() != method {
|
||||||
|
return HTTPResponse::as_400();
|
||||||
|
}
|
||||||
|
|
||||||
let token = {
|
let token = {
|
||||||
match request.get_body_value("token") {
|
match request.get_body_value("token") {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
@ -90,7 +98,11 @@ async fn handle_validate(request: HTTPRequest, config: Config) -> HTTPResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// returns the JWT public key in base64 encoded
|
/// returns the JWT public key in base64 encoded
|
||||||
async fn handle_public_key(_request: HTTPRequest, config: Config) -> HTTPResponse {
|
async fn handle_public_key(request: HTTPRequest, config: Config, method: &str) -> HTTPResponse {
|
||||||
|
if request.get_method().trim().to_lowercase() != method {
|
||||||
|
return HTTPResponse::as_400();
|
||||||
|
}
|
||||||
|
|
||||||
let jwt_signer = {
|
let jwt_signer = {
|
||||||
match JWTSigner::new(config).await {
|
match JWTSigner::new(config).await {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
@ -114,6 +126,7 @@ async fn handle_public_key(_request: HTTPRequest, config: Config) -> HTTPRespons
|
|||||||
pub struct Router;
|
pub struct Router;
|
||||||
|
|
||||||
impl Router {
|
impl Router {
|
||||||
|
/// routes the request to the corresponding handling method
|
||||||
pub async fn route(&self, request_str: &str, addr: String, config: Config) -> HTTPResponse {
|
pub async fn route(&self, request_str: &str, addr: String, config: Config) -> HTTPResponse {
|
||||||
let mut request = HTTPRequest::from(request_str);
|
let mut request = HTTPRequest::from(request_str);
|
||||||
request.set_addr(addr);
|
request.set_addr(addr);
|
||||||
@ -121,9 +134,9 @@ impl Router {
|
|||||||
let target = request.start_line.get_target();
|
let target = request.start_line.get_target();
|
||||||
|
|
||||||
match target.as_str() {
|
match target.as_str() {
|
||||||
GET_ROUTE => handle_get(request, config).await,
|
GET_ROUTE => handle_get(request, config, "post").await,
|
||||||
VALIDATE_ROUTE => handle_validate(request, config).await,
|
VALIDATE_ROUTE => handle_validate(request, config, "post").await,
|
||||||
PUBKEY_ROUTE => handle_public_key(request, config).await,
|
PUBKEY_ROUTE => handle_public_key(request, config, "get").await,
|
||||||
_ => HTTPResponse::as_404(),
|
_ => HTTPResponse::as_404(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@
|
|||||||
URL=${SIMPLE_AUTH_URL}
|
URL=${SIMPLE_AUTH_URL}
|
||||||
if [ -z ${URL} ]
|
if [ -z ${URL} ]
|
||||||
then
|
then
|
||||||
echo "[WARN]: SIMPLE_AUTH_URL is empty, set to http://localhost:9001"
|
echo "[WARN]: SIMPLE_AUTH_URL is empty, set to http://localhost:5555"
|
||||||
URL="http://localhost:9001"
|
URL="http://localhost:5555"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for i in {0..10}
|
for i in {0..10}
|
||||||
@ -39,3 +39,14 @@ do
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
for i in {0..10}
|
||||||
|
do
|
||||||
|
http_response=$(curl -s -o response.txt -w "%{http_code}" ${URL}/pubkey/)
|
||||||
|
if [ $http_response != "200" ]
|
||||||
|
then
|
||||||
|
echo "bad http status code : ${http_response}, expect 400"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import base64
|
||||||
import jwt
|
import jwt
|
||||||
import os
|
import os
|
||||||
import requests
|
import requests
|
||||||
@ -113,3 +114,23 @@ class TestResponse(TestCase):
|
|||||||
"the url requested does not exist",
|
"the url requested does not exist",
|
||||||
"invalid error message returned",
|
"invalid error message returned",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_get_pubkey(self):
|
||||||
|
resp = requests.get(URL + "/pubkey/")
|
||||||
|
self.assertEqual(resp.status_code, 200, "bad status code returned")
|
||||||
|
self.assertIsNotNone(resp.json(), "response data must not be empty")
|
||||||
|
self.assertIsNotNone(resp.json()["pubkey"], "invalid error message returned")
|
||||||
|
|
||||||
|
b64_pubkey = base64.b64decode(resp.json()["pubkey"])
|
||||||
|
self.assertIsNotNone(b64_pubkey, "public key b64 decoded can't be empty")
|
||||||
|
self.assertIn("-BEGIN PUBLIC KEY-", b64_pubkey.decode())
|
||||||
|
|
||||||
|
def test_get_pubkey_bad_method(self):
|
||||||
|
resp = requests.post(URL + "/pubkey/", json={"tutu": "toto"})
|
||||||
|
self.assertEqual(resp.status_code, 400, "bad status code returned")
|
||||||
|
self.assertIsNotNone(resp.json(), "response data must not be empty")
|
||||||
|
self.assertEqual(
|
||||||
|
resp.json()["error"],
|
||||||
|
"the incoming request is not valid",
|
||||||
|
"invalid error message returned",
|
||||||
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user