forked from tangled.org/core
this repo has no description
at master 1.6 kB view raw
1package serviceauth 2 3import ( 4 "context" 5 "encoding/json" 6 "log/slog" 7 "net/http" 8 "strings" 9 10 "github.com/bluesky-social/indigo/atproto/auth" 11 "tangled.org/core/idresolver" 12 xrpcerr "tangled.org/core/xrpc/errors" 13) 14 15const ActorDid string = "ActorDid" 16 17type ServiceAuth struct { 18 logger *slog.Logger 19 resolver *idresolver.Resolver 20 audienceDid string 21} 22 23func NewServiceAuth(logger *slog.Logger, resolver *idresolver.Resolver, audienceDid string) *ServiceAuth { 24 return &ServiceAuth{ 25 logger: logger, 26 resolver: resolver, 27 audienceDid: audienceDid, 28 } 29} 30 31func (sa *ServiceAuth) VerifyServiceAuth(next http.Handler) http.Handler { 32 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 33 l := sa.logger.With("url", r.URL) 34 35 token := r.Header.Get("Authorization") 36 token = strings.TrimPrefix(token, "Bearer ") 37 38 s := auth.ServiceAuthValidator{ 39 Audience: sa.audienceDid, 40 Dir: sa.resolver.Directory(), 41 } 42 43 did, err := s.Validate(r.Context(), token, nil) 44 if err != nil { 45 l.Error("signature verification failed", "err", err) 46 writeError(w, xrpcerr.AuthError(err), http.StatusForbidden) 47 return 48 } 49 50 r = r.WithContext( 51 context.WithValue(r.Context(), ActorDid, did), 52 ) 53 54 next.ServeHTTP(w, r) 55 }) 56} 57 58// this is slightly different from http_util::write_error to follow the spec: 59// 60// the json object returned must include an "error" and a "message" 61func writeError(w http.ResponseWriter, e xrpcerr.XrpcError, status int) { 62 w.Header().Set("Content-Type", "application/json") 63 w.WriteHeader(status) 64 json.NewEncoder(w).Encode(e) 65}