68 lines
1.7 KiB
Go
68 lines
1.7 KiB
Go
package api
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"browser.local/platform/domain"
|
|
"browser.local/platform/service"
|
|
)
|
|
|
|
const (
|
|
runEndpointHeader = "X-Run-Endpoint"
|
|
runTimestampHeader = "X-Run-Timestamp"
|
|
runNonceHeader = "X-Run-Nonce"
|
|
runSignatureHeader = "X-Run-Signature"
|
|
)
|
|
|
|
type runRequestEnvelope struct {
|
|
RunEndpointID string `json:"runEndpointId"`
|
|
SessionToken string `json:"sessionToken"`
|
|
}
|
|
|
|
func (h *coreHandlers) requireRunSignature(next http.HandlerFunc) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost || r.Body == nil {
|
|
next(w, r)
|
|
return
|
|
}
|
|
body, err := io.ReadAll(io.LimitReader(r.Body, 16<<20))
|
|
if err != nil {
|
|
writeDecodeError(w, err)
|
|
return
|
|
}
|
|
r.Body = io.NopCloser(bytes.NewReader(body))
|
|
var envelope runRequestEnvelope
|
|
if err := json.Unmarshal(body, &envelope); err != nil {
|
|
next(w, r)
|
|
return
|
|
}
|
|
headerEndpoint := strings.TrimSpace(r.Header.Get(runEndpointHeader))
|
|
if headerEndpoint != "" && headerEndpoint != envelope.RunEndpointID {
|
|
writeServiceError(w, service.ErrUnauthorized)
|
|
return
|
|
}
|
|
bodySum := sha256.Sum256(body)
|
|
err = h.core.AuthorizeRunRequestSignature(domain.RunRequestSignature{
|
|
RunEndpointID: envelope.RunEndpointID,
|
|
SessionToken: envelope.SessionToken,
|
|
Method: r.Method,
|
|
Path: r.URL.Path,
|
|
Timestamp: strings.TrimSpace(r.Header.Get(runTimestampHeader)),
|
|
Nonce: strings.TrimSpace(r.Header.Get(runNonceHeader)),
|
|
BodyHash: hex.EncodeToString(bodySum[:]),
|
|
Signature: strings.TrimSpace(r.Header.Get(runSignatureHeader)),
|
|
})
|
|
if err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
next(w, r)
|
|
}
|
|
}
|