// 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) }
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 }
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)) }
// 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, }) }
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}) }