auth + creating identities
This commit is contained in:
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"libshared"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
@@ -17,16 +17,12 @@ type AuthenticateRequest struct {
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type AuthenticateResponse struct {
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func authenticateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
/*
|
||||
var hashText string
|
||||
var salt []byte
|
||||
var err error
|
||||
var checkExisting pgx.Row
|
||||
var req CreateIdentityRequest
|
||||
var accountid string
|
||||
*/
|
||||
var authenticaterequest AuthenticateRequest
|
||||
var err error
|
||||
var checkExisting pgx.Row
|
||||
@@ -35,24 +31,28 @@ func authenticateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var token string
|
||||
secret := []byte("super-secret-key")
|
||||
|
||||
response := map[string]interface{}{}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// Only allow POST method
|
||||
if r.Method != http.MethodPost {
|
||||
//http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
response["status"] = "error"
|
||||
response["message"] = "HTTP POST Method not allowed"
|
||||
goto ExitAPICall
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
apiresponse := libshared.NewAPIResponse("fail", "POST method required", AuthenticateResponse{})
|
||||
json.NewEncoder(w).Encode(apiresponse)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Optional: enforce content type
|
||||
if r.Header.Get("Content-Type") != "application/json" {
|
||||
apiresponse := libshared.NewAPIResponse("fail", "Content-Type must be application/json", AuthenticateResponse{})
|
||||
w.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
response["status"] = "error"
|
||||
response["message"] = "Content-Type must be application/json"
|
||||
goto ExitAPICall
|
||||
//response["status"] = "error"
|
||||
//response["message"] = "Content-Type must be application/json"
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(apiresponse)
|
||||
return
|
||||
}
|
||||
|
||||
// Read body with size limit (protect against huge requests)
|
||||
@@ -63,15 +63,18 @@ func authenticateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println(r.Body)
|
||||
err = json.NewDecoder(r.Body).Decode(&authenticaterequest)
|
||||
if err != nil {
|
||||
apiresponse := libshared.NewAPIResponse("fail", "Invalid JSON: "+err.Error(), AuthenticateResponse{})
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
response["status"] = "error"
|
||||
response["message"] = "Invalid JSON: " + err.Error()
|
||||
goto ExitAPICall
|
||||
//response["status"] = "error"
|
||||
//response["message"] = "Invalid JSON: " + err.Error()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(apiresponse)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println(authenticaterequest)
|
||||
|
||||
checkExisting = pool.QueryRow(context.Background(),
|
||||
checkExisting = libshared.Pool.QueryRow(context.Background(),
|
||||
"SELECT password_hash FROM identities WHERE accountid = $1 AND provider = $2 AND provider_user_id = $3",
|
||||
authenticaterequest.Accountid, "local", authenticaterequest.Username)
|
||||
|
||||
@@ -79,37 +82,39 @@ func authenticateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = checkExisting.Scan(&hashText)
|
||||
if err != nil {
|
||||
response["status"] = "fail"
|
||||
response["message"] = "User account does not exist"
|
||||
apiresponse := libshared.NewAPIResponse("fail", "User account does not exist", AuthenticateResponse{})
|
||||
log.Println(err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
goto ExitAPICall
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(apiresponse)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println(hashText)
|
||||
|
||||
ok = verifyPassword(authenticaterequest.Password, hashText)
|
||||
if ok == false {
|
||||
response["status"] = "fail"
|
||||
response["message"] = "Bad password"
|
||||
apiresponse := libshared.NewAPIResponse("fail", "Incorrect username or password", AuthenticateResponse{})
|
||||
//response["message"] = "Bad password"
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
goto ExitAPICall
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(apiresponse)
|
||||
return
|
||||
}
|
||||
|
||||
token, err = createJWT(secret, fmt.Sprintf("%d", authenticaterequest.Accountid), authenticaterequest.Username, "user")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
response["status"] = "error"
|
||||
response["message"] = "Failed to create JWT"
|
||||
goto ExitAPICall
|
||||
apiresponse := libshared.NewAPIResponse("fail", "Failed to create JWT", AuthenticateResponse{})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(apiresponse)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
apiresponse := libshared.NewAPIResponse("success", "Authentication successful", AuthenticateResponse{Token: token})
|
||||
w.WriteHeader(http.StatusOK)
|
||||
response["status"] = "success"
|
||||
response["token"] = token
|
||||
ExitAPICall:
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
response["timestamp"] = fmt.Sprintf("%d", time.Now().Unix())
|
||||
json.NewEncoder(w).Encode(response)
|
||||
json.NewEncoder(w).Encode(apiresponse)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user