Beispiel #1
0
// ServeHTTP implements the http.Handler interface.
func (h *registerUserHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if req.Method != "POST" {
		sendError(w, errors.MethodNotAllowedf("unsupported method: %q", req.Method))
		return
	}
	st, err := h.ctxt.stateForRequestUnauthenticated(req)
	if err != nil {
		sendError(w, err)
		return
	}
	userTag, response, err := h.processPost(req, st)
	if err != nil {
		sendError(w, err)
		return
	}

	// Set a short-lived macaroon as a cookie on the response,
	// which the client can use to obtain a discharge macaroon.
	m, err := h.ctxt.srv.authCtxt.CreateLocalLoginMacaroon(userTag)
	if err != nil {
		sendError(w, err)
		return
	}
	cookie, err := httpbakery.NewCookie(macaroon.Slice{m})
	if err != nil {
		sendError(w, err)
		return
	}
	http.SetCookie(w, cookie)

	sendStatusAndJSON(w, http.StatusOK, response)
}
Beispiel #2
0
func (h *localLoginHandlers) serveLoginPost(p httprequest.Params) (interface{}, error) {
	if err := p.Request.ParseForm(); err != nil {
		return nil, err
	}
	waitId := p.Request.Form.Get("waitid")
	if waitId == "" {
		return nil, errors.NotValidf("missing waitid")
	}
	username := p.Request.Form.Get("user")
	password := p.Request.Form.Get("password")
	if !names.IsValidUser(username) {
		return nil, errors.NotValidf("username %q", username)
	}
	userTag := names.NewUserTag(username)
	if !userTag.IsLocal() {
		return nil, errors.NotValidf("non-local username %q", username)
	}

	authenticator := h.authCtxt.authenticator(p.Request.Host)
	if _, err := authenticator.Authenticate(h.state, userTag, params.LoginRequest{
		Credentials: password,
	}); err != nil {
		// Mark the interaction as done (but failed),
		// unblocking a pending "/auth/wait" request.
		if err := h.authCtxt.localUserInteractions.Done(waitId, userTag, err); err != nil {
			if !errors.IsNotFound(err) {
				logger.Warningf(
					"failed to record completion of interaction %q for %q",
					waitId, userTag.Id(),
				)
			}
		}
		return nil, errors.Trace(err)
	}

	// Provide the client with a macaroon that they can use to
	// prove that they have logged in, and obtain a discharge
	// macaroon.
	m, err := h.authCtxt.CreateLocalLoginMacaroon(userTag)
	if err != nil {
		return nil, err
	}
	cookie, err := httpbakery.NewCookie(macaroon.Slice{m})
	if err != nil {
		return nil, err
	}
	http.SetCookie(p.Response, cookie)

	// Mark the interaction as done, unblocking a pending
	// "/auth/wait" request.
	if err := h.authCtxt.localUserInteractions.Done(
		waitId, userTag, nil,
	); err != nil {
		if errors.IsNotFound(err) {
			err = errors.New("login timed out")
		}
		return nil, err
	}
	return nil, nil
}
Beispiel #3
0
func (s *ClientSuite) TestNewCookieExpires(c *gc.C) {
	t := time.Now().Add(24 * time.Hour)
	svc := newService("loc", nil)
	m, err := svc.NewMacaroon("", nil, []checkers.Caveat{
		checkers.TimeBeforeCaveat(t),
	})
	c.Assert(err, gc.IsNil)
	cookie, err := httpbakery.NewCookie(macaroon.Slice{m})
	c.Assert(err, gc.IsNil)
	c.Assert(cookie.Expires.Equal(t), gc.Equals, true, gc.Commentf("obtained: %s, expected: %s", cookie.Expires, t))
}
Beispiel #4
0
// loginAttemptHandler is invoked when a user clicks on the "Log in"
// button on the login page. It checks the credentials and then
// completes the rendezvous, allowing the original wait
// request to complete.
func (h *handler) loginAttemptHandler(w http.ResponseWriter, req *http.Request) {
	log.Printf("login attempt %s", req.URL)
	req.ParseForm()
	waitId := req.Form.Get("waitid")
	if waitId == "" {
		http.Error(w, "wait id not found in form", http.StatusBadRequest)
		return
	}
	user := req.Form.Get("user")
	info, ok := h.users[user]
	if !ok {
		http.Error(w, fmt.Sprintf("user %q not found", user), http.StatusUnauthorized)
		return
	}
	if req.Form.Get("password") != info.Password {
		http.Error(w, "bad password", http.StatusUnauthorized)
		return
	}

	// User and password match; we can allow the user
	// to have a macaroon that they can use later to prove
	// to us that they have logged in. We also add a cookie
	// to hold the logged in user name.
	m, err := h.svc.NewMacaroon("", nil, []checkers.Caveat{{
		Condition: "user-is " + user,
	}})
	// TODO(rog) when this fails, we should complete the rendezvous
	// to cause the wait request to complete with an appropriate error.
	if err != nil {
		http.Error(w, "cannot mint macaroon: "+err.Error(), http.StatusInternalServerError)
		return
	}
	cookie, err := httpbakery.NewCookie(macaroon.Slice{m})
	if err != nil {
		http.Error(w, "cannot make cookie: "+err.Error(), http.StatusInternalServerError)
		return
	}
	http.SetCookie(w, cookie)
	http.SetCookie(w, &http.Cookie{
		Path:  "/",
		Name:  cookieUser,
		Value: user,
	})
	h.place.Done(waitId, &loginInfo{
		User: user,
	})
}
Beispiel #5
0
func addCookie(c *gc.C, jar *cookiejar.Jar, mac *macaroon.Macaroon, url *url.URL) {
	cookie, err := httpbakery.NewCookie(macaroon.Slice{mac})
	c.Assert(err, jc.ErrorIsNil)
	cookie.Expires = time.Now().Add(time.Hour) // only persistent cookies are stored
	jar.SetCookies(url, []*http.Cookie{cookie})
}