package pin import ( "errors" "fmt" "net/http" "github.com/gin-gonic/gin" "github.com/google/uuid" "edge-infra.dev/pkg/edge/iam/apperror" iamErrors "edge-infra.dev/pkg/edge/iam/errors" "edge-infra.dev/pkg/edge/iam/log" "edge-infra.dev/pkg/edge/iam/util" ) type saveRequest struct { //Username string `json:"username"` Pin string `json:"pin" binding:"required,len=6"` ConfirmPIN string `json:"pin_confirm" binding:"required,len=6"` Action string `json:"action"` } func (pin *PIN) savePIN(c *gin.Context) error { logger := log.Get(c.Request.Context()).WithName("save-pin") req := c.Request var reqBody saveRequest if err := c.BindJSON(&reqBody); err != nil { pin.metrics.IncSignUpRequestsTotal(signUpPin, util.Failed) return apperror.NewAbortError( fmt.Errorf("invalid save pin request body: %w", err), http.StatusBadRequest) } err := req.ParseForm() if err != nil { return apperror.NewAbortError( fmt.Errorf("failed to parse save pin request: %w", err), http.StatusBadRequest) } session, _ := pin.sessionStore.Get(c.Request, "oauth2") if session.Values["method"] != "federated" { err := errors.New("no cloud login found in session. need strong auth to set PIN") return apperror.NewAbortError(err, http.StatusForbidden) } sub, ok := session.Values["sub"] if !ok { err := errors.New("invalid session. could not find subject in the cookie session") return apperror.NewAbortError(err, http.StatusUnauthorized) } subject := sub.(string) switch reqBody.Action { case "save": // client already made sure that pin and confirmPin are the same... err = pin.storage.SavePIN(c.Request.Context(), subject, reqBody.Pin) if err != nil { if err == iamErrors.ErrPINPreviouslyUsed { return apperror.NewStatusError(err, http.StatusUnprocessableEntity) } return apperror.NewAbortError( fmt.Errorf("failed to save pin: %w", err), http.StatusInternalServerError) } case "cancel": logger.Info(fmt.Sprintf("[%v] - 'cancel' action received, pin not set.", util.ShortOperationID(c.Request.Context()))) } // save new continuation to the session continuation := uuid.New().String() session.Values["continuation"] = continuation //remove reason from session delete(session.Values, "reason") err = session.Save(c.Request, c.Writer) if err != nil { return apperror.NewAbortError( fmt.Errorf("failed to save cookie session: %w", err), http.StatusInternalServerError) } pin.metrics.IncSignUpRequestsTotal(signUpPin, util.Succeeded) return util.WriteJSON(c.Writer, http.StatusOK, gin.H{ "challenge": continuation, }) }