Merge pull request 'feat: Webhook use auth token' (#10) from feat/webhook-auth into main
Reviewed-on: #10
This commit is contained in:
commit
6d9626eaa2
@ -14,6 +14,12 @@ TODO
|
||||
- Create new user for database: `GRANT ALL PRIVILEGES ON dev_locationhub.* TO 'dbuser'@'localhost' IDENTIFIED BY '1234';`
|
||||
- Import tables: `/usr/bin/mariadb -u dbuser -p1234 dev_locationhub < server/sql/tables.sql`
|
||||
|
||||
### TTN Integration
|
||||
Create new Webhook for application. Set base url and enable "Uplink message" to api `/api/ttn/webhook`.
|
||||
Add a addidtional header:
|
||||
- Type: `authorization`
|
||||
- Value: `Bearer your-very-secure-token`
|
||||
|
||||
### Testing Webhook
|
||||
- To test the webhook use the python script `ttn-webhook-dummy.py` to send prerecorded TTN Uplinks.
|
||||
- To test the script you can use `while true; do echo -e "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nSuccess"; nc -l -p 8080 -q 1; done`
|
@ -4,6 +4,7 @@ DB_PASSWORD=""
|
||||
DB_HOST=""
|
||||
DB_DIALECT=""
|
||||
DB_PORT=""
|
||||
WEBHOOK_TOKEN="" #Token that is placed a the TTN Webhook auth
|
||||
WIGLE_TOKEN="" # Go to account and generate token "Encoded for use"
|
||||
WIGLE_BASE_URL="https://api.wigle.net"
|
||||
WIGLE_NETWORK_SEARCH="/api/v2/network/search"
|
||||
|
@ -9,11 +9,16 @@ import json
|
||||
import argparse
|
||||
import random
|
||||
|
||||
def send_post_request(uri, data):
|
||||
def send_post_request(uri, data, token):
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
try:
|
||||
requests.post(uri, json=data, timeout=1)
|
||||
response = requests.post(uri, json=data, timeout=1, headers=headers)
|
||||
print("Return code: " + str(response.status_code))
|
||||
except requests.exceptions.RequestException as e:
|
||||
pass
|
||||
print(e)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
@ -24,6 +29,11 @@ def main():
|
||||
type=str,
|
||||
help="The URI to send POST requests to (e.g., http://127.0.0.1:8080/api)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"token",
|
||||
type=str,
|
||||
help="Bearer authorization token)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"directory",
|
||||
type=str,
|
||||
@ -46,7 +56,7 @@ def main():
|
||||
try:
|
||||
data = json.load(file)
|
||||
print(f"Sending {args.directory} to {args.uri}")
|
||||
send_post_request(args.uri, data)
|
||||
send_post_request(args.uri, data, args.token)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error reading {args.directory}: {e}")
|
||||
return
|
||||
@ -67,7 +77,7 @@ def main():
|
||||
try:
|
||||
data = json.load(file)
|
||||
print(f"Sending {filename} to {args.uri}")
|
||||
send_post_request(args.uri, data)
|
||||
send_post_request(args.uri, data, args.token)
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error reading {filename}: {e}")
|
||||
|
||||
@ -78,7 +88,7 @@ def main():
|
||||
try:
|
||||
data = json.load(file)
|
||||
print(f"Sending {filename} to {args.uri}")
|
||||
send_post_request(args.uri, data)
|
||||
send_post_request(args.uri, data, args.token)
|
||||
input("Press Enter to send the next file...")
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error reading {filename}: {e}")
|
||||
@ -91,11 +101,10 @@ def main():
|
||||
try:
|
||||
data = json.load(file)
|
||||
print(f"Sending {filename} to {args.uri}")
|
||||
send_post_request(args.uri, data)
|
||||
send_post_request(args.uri, data, args.token)
|
||||
input("Press Enter to send another random file...")
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"Error reading {filename}: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -7,6 +7,8 @@ import { LpTtnEndDeviceUplinksService } from "../services/lpTtnEndDeviceUplinksS
|
||||
import { TtnGatewayReceptionService } from "../services/ttnGatewayReceptionService";
|
||||
import { WifiScanService } from "../services/wifiScanService";
|
||||
import { ttnMessageValidator } from "../validation/ttn/ttnMessageValidation";
|
||||
import { authenticateHeader } from "../middleware/authentificationMiddleware";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
|
||||
const lpTtnEndDeviceUplinksService = container.resolve(
|
||||
LpTtnEndDeviceUplinksService
|
||||
@ -22,7 +24,7 @@ const router = express.Router();
|
||||
|
||||
router.post(
|
||||
"/webhook",
|
||||
validateData(ttnMessageValidator),
|
||||
[authenticateHeader, validateData(ttnMessageValidator)],
|
||||
async (req: Request, res: Response) => {
|
||||
try {
|
||||
const message = req.body as TtnMessage;
|
||||
@ -96,17 +98,17 @@ router.post(
|
||||
gnss:
|
||||
gnnsLocation.latitude && gnnsLocation.longitude
|
||||
? {
|
||||
latitude: gnnsLocation.latitude,
|
||||
longitude: gnnsLocation.longitude,
|
||||
}
|
||||
latitude: gnnsLocation.latitude,
|
||||
longitude: gnnsLocation.longitude,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
};
|
||||
createDatabaseEntries().then();
|
||||
res.status(200);
|
||||
res.status(StatusCodes.OK).send();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
res.status(500).json({ error: "Error creating uplink" });
|
||||
res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({ error: "Error creating uplink" });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
42
server/src/middleware/authentificationMiddleware.ts
Normal file
42
server/src/middleware/authentificationMiddleware.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
|
||||
const validateBearerToken = (authorizationHeader: string | undefined): boolean => {
|
||||
if (!authorizationHeader) {
|
||||
console.log("Authorization header is missing!");
|
||||
return false;
|
||||
}
|
||||
|
||||
const token = authorizationHeader.split(' ')[1]; // Extract token after 'Bearer'
|
||||
if (!token) {
|
||||
console.log("Bearer token is missing!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token !== process.env.WEBHOOK_TOKEN) {
|
||||
console.log("Bearer token is incorrect!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
export function authenticateHeader(req: Request, res: Response, next: NextFunction) {
|
||||
try {
|
||||
const authorizationHeader = req.headers['authorization'];
|
||||
|
||||
if (!validateBearerToken(authorizationHeader as string)) {
|
||||
res.status(StatusCodes.UNAUTHORIZED).json({ error: "Authentication failed" });
|
||||
return;
|
||||
}
|
||||
console.log("Bearer token is correct!");
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
res.status(StatusCodes.INTERNAL_SERVER_ERROR)
|
||||
.json({ error: "Internal Server Error" });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -22,4 +22,4 @@ export function validateData(schema: z.ZodObject<any, any>) {
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user