Example #1
0
func (s *ErrorSuite) TestNewInteractionRequiredError(c *gc.C) {
	// With a request with no version header, the response
	// should be 407.
	req, err := http.NewRequest("GET", "/", nil)
	c.Assert(err, gc.IsNil)

	err = httpbakery.NewInteractionRequiredError("/visit", "/wait", nil, req)
	code, resp := httpbakery.ErrorToResponse(err)
	c.Assert(code, gc.Equals, http.StatusProxyAuthRequired)

	data, err := json.Marshal(resp)
	c.Assert(err, gc.IsNil)

	c.Assert(string(data), jc.JSONEquals, &httpbakery.Error{
		Code:    httpbakery.ErrInteractionRequired,
		Message: httpbakery.ErrInteractionRequired.Error(),
		Info: &httpbakery.ErrorInfo{
			VisitURL: "/visit",
			WaitURL:  "/wait",
		},
	})

	// With a request with a version 1 header, the response
	// should be 401.
	req.Header.Set("Bakery-Protocol-Version", "1")

	err = httpbakery.NewInteractionRequiredError("/visit", "/wait", nil, req)
	code, resp = httpbakery.ErrorToResponse(err)
	c.Assert(code, gc.Equals, http.StatusUnauthorized)

	h := make(http.Header)
	resp.(httprequest.HeaderSetter).SetHeader(h)
	c.Assert(h.Get("WWW-Authenticate"), gc.Equals, "Macaroon")

	data, err = json.Marshal(resp)
	c.Assert(err, gc.IsNil)

	c.Assert(string(data), jc.JSONEquals, &httpbakery.Error{
		Code:    httpbakery.ErrInteractionRequired,
		Message: httpbakery.ErrInteractionRequired.Error(),
		Info: &httpbakery.ErrorInfo{
			VisitURL: "/visit",
			WaitURL:  "/wait",
		},
	})

}
Example #2
0
func (d *InteractiveDischarger) checker(req *http.Request, cavId, cav string) ([]checkers.Caveat, error) {
	d.mu.Lock()
	id := fmt.Sprintf("%d", d.id)
	d.id++
	d.waiting[id] = discharge{cavId, make(chan dischargeResult, 1)}
	d.mu.Unlock()
	visitURL := "/visit?waitid=" + id
	waitURL := "/wait?waitid=" + id
	return nil, httpbakery.NewInteractionRequiredError(visitURL, waitURL, nil, req)
}
Example #3
0
func (d *InteractiveDischarger) checker(req *http.Request, cavId, cav string) ([]checkers.Caveat, error) {
	d.mu.Lock()
	id := fmt.Sprintf("%d", d.id)
	d.id++
	d.waiting[id] = discharge{cavId, make(chan dischargeResult, 1)}
	d.mu.Unlock()
	prefix := strings.TrimSuffix(req.URL.String(), "/discharge")
	visitURL := fmt.Sprintf("%s/visit?waitid=%s", prefix, id)
	waitURL := fmt.Sprintf("%s/wait?waitid=%s", prefix, id)
	return nil, httpbakery.NewInteractionRequiredError(visitURL, waitURL, nil, req)
}
Example #4
0
func (s *Service) checker(req *http.Request, cavID, cav string) ([]checkers.Caveat, error) {
	election, err := s.newElection(cavID, cav)
	if err != nil {
		return nil, errgo.Mask(err, errgo.Any)
	}
	var waitURL string
	if s.root != "" {
		waitURL = s.root + s.prefix + "/wait/" + election
	} else {
		waitURL = s.prefix + "/wait/" + election
	}
	return nil, httpbakery.NewInteractionRequiredError(waitURL, waitURL, nil, req)
}
Example #5
0
// needLogin returns an error suitable for returning
// from a discharge request that can only be satisfied
// if the user logs in.
func (h *handler) needLogin(cavId string, caveat string, why error, req *http.Request) error {
	// TODO(rog) If the user is already logged in (username != ""),
	// we should perhaps just return an error here.
	log.Printf("login required")
	waitId, err := h.place.NewRendezvous(&thirdPartyCaveatInfo{
		CaveatId: cavId,
		Caveat:   caveat,
	})
	if err != nil {
		return fmt.Errorf("cannot make rendezvous: %v", err)
	}
	log.Printf("returning redirect error")
	visitURL := "/login?waitid=" + waitId
	waitURL := "/wait?waitid=" + waitId
	return httpbakery.NewInteractionRequiredError(visitURL, waitURL, why, req)
}
Example #6
0
// CheckThirdPartyCaveat is part of the bakery.ThirdPartyChecker interface.
func (ctx *macaroonAuthContext) CheckThirdPartyCaveat(cavId, cav string) ([]checkers.Caveat, error) {
	tag, err := ctx.CheckLocalLoginCaveat(cav)
	if err != nil {
		return nil, errors.Trace(err)
	}
	firstPartyCaveats, err := ctx.CheckLocalLoginRequest(ctx.req, tag)
	if err != nil {
		if _, ok := errors.Cause(err).(*bakery.VerificationError); ok {
			waitId, err := ctx.localUserInteractions.Start(
				cavId,
				ctx.clock.Now().Add(authentication.LocalLoginInteractionTimeout),
			)
			if err != nil {
				return nil, errors.Trace(err)
			}
			visitURL := localUserIdentityLocationPath + "/login?waitid=" + waitId
			waitURL := localUserIdentityLocationPath + "/wait?waitid=" + waitId
			return nil, httpbakery.NewInteractionRequiredError(visitURL, waitURL, nil, ctx.req)
		}
		return nil, errors.Trace(err)
	}
	return firstPartyCaveats, nil
}