76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
package httpauth
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"lol.mleku.dev/chk"
|
|
"next.orly.dev/pkg/encoders/event"
|
|
"next.orly.dev/pkg/encoders/kind"
|
|
"next.orly.dev/pkg/encoders/tag"
|
|
"next.orly.dev/pkg/encoders/timestamp"
|
|
"next.orly.dev/pkg/interfaces/signer"
|
|
)
|
|
|
|
const (
|
|
HeaderKey = "Authorization"
|
|
NIP98Prefix = "Nostr"
|
|
)
|
|
|
|
// MakeNIP98Event creates a new NIP-98 event. If expiry is given, method is
|
|
// ignored; otherwise either option is the same.
|
|
func MakeNIP98Event(u, method, hash string, expiry int64) (ev *event.E) {
|
|
var t []*tag.T
|
|
t = append(t, tag.NewFromAny("u", u))
|
|
if expiry > 0 {
|
|
t = append(
|
|
t,
|
|
tag.NewFromAny("expiration", timestamp.FromUnix(expiry).String()),
|
|
)
|
|
} else {
|
|
t = append(
|
|
t,
|
|
tag.NewFromAny("method", strings.ToUpper(method)),
|
|
)
|
|
}
|
|
if hash != "" {
|
|
t = append(t, tag.NewFromAny("payload", hash))
|
|
}
|
|
ev = &event.E{
|
|
CreatedAt: timestamp.Now().V,
|
|
Kind: kind.HTTPAuth.K,
|
|
Tags: tag.NewS(t...),
|
|
}
|
|
return
|
|
}
|
|
|
|
func CreateNIP98Blob(
|
|
ur, method, hash string, expiry int64, sign signer.I,
|
|
) (blob string, err error) {
|
|
ev := MakeNIP98Event(ur, method, hash, expiry)
|
|
if err = ev.Sign(sign); chk.E(err) {
|
|
return
|
|
}
|
|
// log.T.F("nip-98 http auth event:\n%s\n", ev.SerializeIndented())
|
|
blob = base64.URLEncoding.EncodeToString(ev.Serialize())
|
|
return
|
|
}
|
|
|
|
// AddNIP98Header creates a NIP-98 http auth event and adds the standard header to a provided
|
|
// http.Request.
|
|
func AddNIP98Header(
|
|
r *http.Request, ur *url.URL, method, hash string,
|
|
sign signer.I, expiry int64,
|
|
) (err error) {
|
|
var b64 string
|
|
if b64, err = CreateNIP98Blob(
|
|
ur.String(), method, hash, expiry, sign,
|
|
); chk.E(err) {
|
|
return
|
|
}
|
|
r.Header.Add(HeaderKey, "Nostr "+b64)
|
|
return
|
|
}
|