add http method validation on each route + add pubkey tests

This commit is contained in:
landrigun 2022-11-19 15:53:31 +00:00
parent 1d2924b7ef
commit 8d3651d6fc
5 changed files with 63 additions and 8 deletions

View File

@ -45,13 +45,19 @@ expiration_time = 2 # in hours
```bash
./simple-auth <ini_path>
# get a JWT
curl http://<ip>:<port>/get/ -d '{"username":"<user>", "password":"<password>"}'
# should returned
{"token":"<header>.<payload>.<signature>"}
# validate a JWT
curl http://<ip>:<port>/validate/ -d '{"token":"<header>.<payload>.<signature>"}'
# should returned (if valid)
{"valid":"true"}
# get the public key for local validation
curl http://<ip>:<port>/pubkey/
{"pubkey":"<b64_encoded_public_key>"}
```
## Test

View File

@ -217,6 +217,10 @@ impl HTTPRequest {
}
}
pub fn get_method(&self) -> String {
self.start_line.method.clone()
}
#[allow(dead_code)]
pub fn is_valid(&self) -> bool {
return self.start_line.is_valid();

View File

@ -14,7 +14,11 @@ const GET_ROUTE: &'static str = "/get/";
const VALIDATE_ROUTE: &'static str = "/validate/";
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());
match &request.body {
Some(ref b) => {
@ -48,7 +52,11 @@ async fn handle_get(request: HTTPRequest, config: Config) -> HTTPResponse {
/// validates the token by checking:
/// * expiration time
/// * 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 = {
match request.get_body_value("token") {
Some(t) => t,
@ -90,7 +98,11 @@ async fn handle_validate(request: HTTPRequest, config: Config) -> HTTPResponse {
}
/// 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 = {
match JWTSigner::new(config).await {
Ok(s) => s,
@ -114,6 +126,7 @@ async fn handle_public_key(_request: HTTPRequest, config: Config) -> HTTPRespons
pub struct Router;
impl Router {
/// routes the request to the corresponding handling method
pub async fn route(&self, request_str: &str, addr: String, config: Config) -> HTTPResponse {
let mut request = HTTPRequest::from(request_str);
request.set_addr(addr);
@ -121,9 +134,9 @@ impl Router {
let target = request.start_line.get_target();
match target.as_str() {
GET_ROUTE => handle_get(request, config).await,
VALIDATE_ROUTE => handle_validate(request, config).await,
PUBKEY_ROUTE => handle_public_key(request, config).await,
GET_ROUTE => handle_get(request, config, "post").await,
VALIDATE_ROUTE => handle_validate(request, config, "post").await,
PUBKEY_ROUTE => handle_public_key(request, config, "get").await,
_ => HTTPResponse::as_404(),
}
}

View File

@ -9,8 +9,8 @@
URL=${SIMPLE_AUTH_URL}
if [ -z ${URL} ]
then
echo "[WARN]: SIMPLE_AUTH_URL is empty, set to http://localhost:9001"
URL="http://localhost:9001"
echo "[WARN]: SIMPLE_AUTH_URL is empty, set to http://localhost:5555"
URL="http://localhost:5555"
fi
for i in {0..10}
@ -39,3 +39,14 @@ do
exit 1
fi
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

View File

@ -1,3 +1,4 @@
import base64
import jwt
import os
import requests
@ -113,3 +114,23 @@ class TestResponse(TestCase):
"the url requested does not exist",
"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",
)