func (s *httpAuthChecker) writeError(w http.ResponseWriter, err error, req *http.Request) { err1, ok := errgo.Cause(err).(*auth.DischargeRequiredError) if !ok { logger.Infof("error when authorizing: %#v", err) // TODO permission denied error. http.Error(w, err.Error(), http.StatusInternalServerError) return } logger.Infof("got discharge-required error: %#v", err) if len(err1.Caveats) == 0 { panic("no caveats on discharge-required error!") } cookieName := "authz" expiry := 5 * time.Second if len(err1.Ops) == 1 && err1.Ops[0] == auth.LoginOp { cookieName = "authn" expiry = 24 * time.Hour } caveats := append(err1.Caveats, checkers.TimeBeforeCaveat(time.Now().Add(expiry))) m, err := s.store.NewMacaroon(err1.Ops, caveats) if err != nil { panic("cannot make new macaroon: " + err.Error()) } // It's a discharge-required error. Write the expected httpbakery response. berr := httpbakery.NewDischargeRequiredErrorForRequest(m, "/", err, req) berr.(*httpbakery.Error).Info.CookieNameSuffix = cookieName // TODO we need some way of telling the client that the response shouldn't // be persisted. httprequest.ErrorMapper(httpbakery.ErrorToResponse).WriteError(w, berr) }
func (c *caveatSquasher) final() []string { if !c.expiry.IsZero() { c.conds = append(c.conds, checkers.TimeBeforeCaveat(c.expiry).Condition) } if len(c.conds) == 0 { return nil } // Make deterministic and eliminate duplicates. sort.Strings(c.conds) prev := c.conds[0] j := 1 for _, cond := range c.conds[1:] { if cond != prev { c.conds[j] = cond prev = cond j++ } } return c.conds }