Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
2.1 kB · 81 lines
Go
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182package serviceauth
import ( "context" "encoding/json" "log/slog" "net/http" "path" "strings"
"github.com/bluesky-social/indigo/atproto/auth" "github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/atproto/syntax" "tangled.org/core/log" xrpcerr "tangled.org/core/xrpc/errors")
type contextKey string
const ActorDid contextKey = "ActorDid"
func DidWeb(hostname string) syntax.DID { return syntax.DID("did:web:" + strings.ReplaceAll(hostname, ":", "%3A"))}
type ServiceAuth struct { logger *slog.Logger dir identity.Directory audienceDid string}
func NewServiceAuth(logger *slog.Logger, dir identity.Directory, audienceDid string) *ServiceAuth { return &ServiceAuth{ logger: log.SubLogger(logger, "serviceauth"), dir: dir, audienceDid: audienceDid, }}
func (sa *ServiceAuth) VerifyServiceAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") token = strings.TrimPrefix(token, "Bearer ")
lxm, err := syntax.ParseNSID(path.Base(r.URL.Path)) if err != nil { sa.logger.Error("could not derive lexicon method from request path", "path", r.URL.Path, "err", err) writeError(w, xrpcerr.AuthError(err), http.StatusForbidden) return }
s := auth.ServiceAuthValidator{ Audience: sa.audienceDid, Dir: sa.dir, }
did, err := s.Validate(r.Context(), token, &lxm) if err != nil { sa.logger.Error("signature verification failed", "err", err) writeError(w, xrpcerr.AuthError(err), http.StatusForbidden) return }
sa.logger.Debug("valid signature", "did", did)
r = r.WithContext( context.WithValue(r.Context(), ActorDid, did), )
next.ServeHTTP(w, r) })}
// this is slightly different from http_util::write_error to follow the spec://// the json object returned must include an "error" and a "message"func writeError(w http.ResponseWriter, e xrpcerr.XrpcError, status int) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(status) json.NewEncoder(w).Encode(e)}