Somewhat lightweight auth for simple usage counting. Could do with some locking really, but fit for this purpose.

This commit is contained in:
stevenhowes
2025-02-22 21:22:33 +00:00
parent 910ff909b1
commit 9397e13e5a
3 changed files with 71 additions and 13 deletions
+3
View File
@@ -0,0 +1,3 @@
osgrid-server
/keys
Executable
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
TOKEN=`uuidgen`
echo $TOKEN
MD5=`echo -n $TOKEN | md5sum | awk '{ print $1 }'`
echo $MD5
echo -n 0 > keys/$MD5
+62 -13
View File
@@ -1,20 +1,23 @@
package main package main
import ( import (
"crypto/md5"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"os"
"strconv"
"strings" "strings"
"time" "time"
"github.com/paulcager/go-http-middleware" middleware "github.com/paulcager/go-http-middleware"
"github.com/paulcager/osgridref" "github.com/paulcager/osgridref"
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
) )
const ( const (
apiVersion = "v4" apiVersion = "v5"
) )
var ( var (
@@ -32,11 +35,12 @@ func main() {
} }
type Reply struct { type Reply struct {
OSGridRef string `json:"osGridRef"` OSGridRef string `json:"osGridRef"`
Easting int `json:"easting"` Easting int `json:"easting"`
Northing int `json:"northing"` Northing int `json:"northing"`
Lat float64 `json:"lat"` Lat float64 `json:"lat"`
Lon float64 `json:"lon"` Lon float64 `json:"lon"`
UsageCount int `json:"usageCount"`
} }
func makeHTTPServer(listenPort string) *http.Server { func makeHTTPServer(listenPort string) *http.Server {
@@ -82,19 +86,64 @@ func makeHTTPServer(listenPort string) *http.Server {
return s return s
} }
func md5hash(text string) string {
hash := md5.New()
hash.Write([]byte(text))
return fmt.Sprintf("%x", hash.Sum(nil))
}
func handleError(w http.ResponseWriter, _ *http.Request, str string, _ error) { func handleError(w http.ResponseWriter, _ *http.Request, str string, _ error) {
w.Header().Add("Access-Control-Allow-Origin", "*") w.Header().Add("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Invalid request: %q\n", str) fmt.Fprintf(w, "Invalid request: %q\n", str)
} }
func handle(w http.ResponseWriter, _ *http.Request, ref osgridref.OsGridRef, lat float64, lon float64) { func handle(w http.ResponseWriter, r *http.Request, ref osgridref.OsGridRef, lat float64, lon float64) {
authorization := r.Header.Get("Authorization")
// extract bearer token from authorization header
if authorization != "" {
authorization = strings.TrimPrefix(strings.ToLower(authorization), "bearer ")
} else {
w.WriteHeader(http.StatusUnauthorized)
return
}
usageCount := 0
// if file exists, increment usage count
if authorization != "" {
authorization = md5hash(authorization)
filePath := "keys/" + authorization
if _, err := os.Stat(filePath); err == nil {
data, err := os.ReadFile(filePath)
if err == nil {
usageCount, err = strconv.Atoi(strings.TrimSpace(string(data)))
if err == nil {
usageCount++
err = os.WriteFile(filePath, []byte(strconv.Itoa(usageCount)), 0644)
if err != nil {
log.Printf("Failed to write usage count: %s", err)
}
} else {
log.Printf("Failed to parse usage count: %s", err)
}
} else {
log.Printf("Failed to read file: %s", err)
}
} else {
w.WriteHeader(http.StatusForbidden)
return
}
}
reply := Reply{ reply := Reply{
OSGridRef: ref.StringNCompact(8), OSGridRef: ref.StringNCompact(8),
Easting: ref.Easting, Easting: ref.Easting,
Northing: ref.Northing, Northing: ref.Northing,
Lat: lat, Lat: lat,
Lon: lon, Lon: lon,
UsageCount: usageCount,
} }
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")