func (s *httpAuthChecker) ServeHTTP(w http.ResponseWriter, req *http.Request) { mss := httpbakery.RequestMacaroons(req) logger.Infof("%d macaroons in request", len(mss)) authorizer := s.service.NewAuthorizer(mss) // version := httpbakery.RequestVersion(req) if req.Method == "AUTH" { // Special HTTP method to ask for a capability. // TODO what's the best way of requesting this in in reality? req1 := *req req1.Method = req.Header.Get("AuthMethod") ops := s.h.EndpointAuth(&req1) logger.Infof("asking for capability for %#v", ops) conditions, err := authorizer.AllowCapability(context.TODO(), ops) if err != nil { s.writeError(w, err, req) return } m, err := s.store.NewMacaroon(withoutLoginOp(ops), nil) if err != nil { panic("cannot make new macaroon: " + err.Error()) } for _, cond := range conditions { if err := m.AddFirstPartyCaveat(cond); err != nil { panic("cannot add first party caveat: " + err.Error()) } } data, err := json.Marshal(capabilityResponse{m}) if err != nil { s.writeError(w, err, req) return } w.Header().Set("Content-Type", "application/json") w.Write(data) return } ops := s.h.EndpointAuth(req) logger.Infof("got ops %#v for path %v", ops, req.URL) authInfo, err := authorizer.Allow(req.Context(), ops) if err != nil { logger.Infof("Allow returned %#v", err) s.writeError(w, err, req) return } if authInfo.Identity != nil { logger.Infof("successful authorization as %q", authInfo.Identity.Id()) } else { logger.Infof("successful authorization as no-one") } // Authorized OK - execute the actual handler logic. s.h.ServeHTTP(w, req) return }
func authHandler(h http.Handler) http.Handler { key, _ := bakery.GenerateKey() // TODO check error! b := bakery.New(bakery.BakeryParams{ Key: key, }) return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { ops := opsForRequest(req) macaroons := httpbakery.RequestMacaroons(req) _, err := b.Checker.Auth(macaroons...).Allow(req.Context(), ops...) if err != nil { http.Error(w, err.Error(), http.StatusUnauthorized) return } h.ServeHTTP(w, req) }) }