//ValidateUsername checks if a username is already taken or not func (service *Service) ValidateUsername(w http.ResponseWriter, request *http.Request) { username := request.URL.Query().Get("username") response := struct { Valid bool `json:"valid"` Error string `json:"error"` }{ Valid: true, Error: "", } valid := user.ValidateUsername(username) if !valid { log.Debug("Invalid username format:", username) response.Error = "invalid_username_format" response.Valid = false json.NewEncoder(w).Encode(&response) return } userMgr := user.NewManager(request) userExists, err := userMgr.Exists(username) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if userExists { log.Debug("username ", username, " already taken") response.Error = "duplicate_username" response.Valid = false } json.NewEncoder(w).Encode(&response) return }
// DeleteDigitalAssetAddress is the handler for DELETE /users/{username}/digitalwallet/{label} func (api UsersAPI) DeleteDigitalAssetAddress(w http.ResponseWriter, r *http.Request) { username := mux.Vars(r)["username"] label := mux.Vars(r)["label"] userMgr := user.NewManager(r) u, err := userMgr.GetByName(username) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } _, err = u.GetDigitalAssetAddressByLabel(label) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } if err = userMgr.RemoveVirtualCurrency(username, label); err != nil { log.Error("ERROR while saving address:\n", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.WriteHeader(http.StatusNoContent) }
//LoginResendPhonenumberConfirmation resend the phone number confirmation after logging in to a possibly new phone number func (service *Service) LoginResendPhonenumberConfirmation(w http.ResponseWriter, request *http.Request) { values := struct { PhoneNumber string `json:"phonenumber"` }{} response := struct { Error string `json:"error"` }{} if err := json.NewDecoder(request.Body).Decode(&values); err != nil { log.Debug("Error decoding the ResendPhonenumberConfirmation request: ", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } loginSession, err := service.GetSession(request, SessionLogin, "loginsession") if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if loginSession.IsNew { sessions.Save(request, w) log.Debug("Login session expired") http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } username, _ := loginSession.Values["username"].(string) //Invalidate the previous validation request, ignore a possible error validationkey, _ := loginSession.Values["phonenumbervalidationkey"].(string) _ = service.phonenumberValidationService.ExpireValidation(request, validationkey) phonenumber := user.Phonenumber{Label: "main", Phonenumber: values.PhoneNumber} if !phonenumber.IsValid() { log.Debug("Invalid phone number") w.WriteHeader(422) response.Error = "invalid_phonenumber" json.NewEncoder(w).Encode(&response) return } uMgr := user.NewManager(request) err = uMgr.SavePhone(username, phonenumber) if err != nil { log.Error("ResendPhonenumberConfirmation: Could not save phonenumber: ", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } validationkey, err = service.phonenumberValidationService.RequestValidation(request, username, phonenumber, fmt.Sprintf("https://%s/phonevalidation", request.Host)) if err != nil { log.Error("ResendPhonenumberConfirmation: Could not get validationkey: ", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } loginSession.Values["phonenumbervalidationkey"] = validationkey sessions.Save(request, w) w.WriteHeader(http.StatusNoContent) }
//FilterAuthorizedScopes filters the requested scopes to the ones that are authorizated, if no authorization exists, authorizedScops is nil func (service *Service) FilterAuthorizedScopes(r *http.Request, username string, grantedTo string, requestedscopes []string) (authorizedScopes []string, err error) { authorization, err := userdb.NewManager(r).GetAuthorization(username, grantedTo) if authorization == nil || err != nil { return } authorizedScopes = authorization.FilterAuthorizedScopes(requestedscopes) return }
// UpdateDigitalAssetAddress is the handler for PUT /users/{username}/digitalwallet/{label} // Update the label and/or value of an existing address. func (api UsersAPI) UpdateDigitalAssetAddress(w http.ResponseWriter, r *http.Request) { username := mux.Vars(r)["username"] oldlabel := mux.Vars(r)["label"] newcurrency := user.DigitalAssetAddress{} if err := json.NewDecoder(r.Body).Decode(&newcurrency); err != nil { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } if !isValidLabel(newcurrency.Label) { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } userMgr := user.NewManager(r) u, err := userMgr.GetByName(username) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } _, err = u.GetDigitalAssetAddressByLabel(oldlabel) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } if oldlabel != newcurrency.Label { _, err = u.GetAddressByLabel(newcurrency.Label) if err == nil { http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict) return } } if err = userMgr.SaveVirtualCurrency(username, newcurrency); err != nil { log.Error("ERROR while saving address - ", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if oldlabel != newcurrency.Label { if err := userMgr.RemoveVirtualCurrency(username, oldlabel); err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(newcurrency) }
//ForgotPassword handler for POST /login/forgotpassword func (service *Service) ForgotPassword(w http.ResponseWriter, request *http.Request) { // login can be username or email values := struct { Login string `json:"login"` }{} if err := json.NewDecoder(request.Body).Decode(&values); err != nil { log.Debug("Error decoding the ForgotPassword request:", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } userMgr := user.NewManager(request) valMgr := validationdb.NewManager(request) validatedemail, err := valMgr.GetByEmailAddressValidatedEmailAddress(values.Login) if err != nil && err != mgo.ErrNotFound { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } var username string var emails []string if err != mgo.ErrNotFound { username = validatedemail.Username emails = []string{validatedemail.EmailAddress} } else { user, err := userMgr.GetByName(values.Login) if err != nil && err != mgo.ErrNotFound { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } username = user.Username validatedemails, err := valMgr.GetByUsernameValidatedEmailAddress(username) if validatedemails == nil || len(validatedemails) == 0 { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } if err != nil { log.Error("Failed to get validated emails address - ", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } emails = make([]string, len(validatedemails)) for idx, validatedemail := range validatedemails { emails[idx] = validatedemail.EmailAddress } } _, err = service.emailaddressValidationService.RequestPasswordReset(request, username, emails) if err != nil { log.Error("Failed to request password reset - ", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } w.WriteHeader(http.StatusNoContent) return }
//GetSmsCode returns an sms code for a specified phone label func (service *Service) GetSmsCode(w http.ResponseWriter, request *http.Request) { phoneLabel := mux.Vars(request)["phoneLabel"] loginSession, err := service.GetSession(request, SessionLogin, "loginsession") if err != nil { log.Error("Error getting login session", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } sessionInfo, err := newLoginSessionInformation() if err != nil { log.Error("Error creating login session information", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } username, ok := loginSession.Values["username"].(string) if username == "" || !ok { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } userMgr := user.NewManager(request) userFromDB, err := userMgr.GetByName(username) if err != nil { log.Error("Error getting user", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } phoneNumber, err := userFromDB.GetPhonenumberByLabel(phoneLabel) if err != nil { log.Debug(userFromDB.Phonenumbers) http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } loginSession.Values["sessionkey"] = sessionInfo.SessionKey authClientId := loginSession.Values["auth_client_id"] authenticatingOrganization := "" if authClientId != nil { authenticatingOrganization = authClientId.(string) } mgoCollection := db.GetCollection(db.GetDBSession(request), mongoLoginCollectionName) mgoCollection.Insert(sessionInfo) organizationText := "" if authenticatingOrganization != "" { split := strings.Split(authenticatingOrganization, ".") organizationText = fmt.Sprintf("to authorize the organization %s, ", split[len(split)-1]) } smsmessage := fmt.Sprintf("To continue signing in at itsyou.online %senter the code %s in the form or use this link: https://%s/sc?c=%s&k=%s", organizationText, sessionInfo.SMSCode, request.Host, sessionInfo.SMSCode, url.QueryEscape(sessionInfo.SessionKey)) sessions.Save(request, w) go service.smsService.Send(phoneNumber.Phonenumber, smsmessage) w.WriteHeader(http.StatusNoContent) }
// RegisterNewDigitalAssetAddress is the handler for POST /users/{username}/digitalwallet // Register a new address func (api UsersAPI) RegisterNewDigitalAssetAddress(w http.ResponseWriter, r *http.Request) { username := mux.Vars(r)["username"] userMgr := user.NewManager(r) currency := user.DigitalAssetAddress{} if err := json.NewDecoder(r.Body).Decode(¤cy); err != nil { log.Debug("Error while decoding the body: ", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } if !isValidLabel(currency.Label) { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } u, err := userMgr.GetByName(username) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } //Check if this label is already used _, err = u.GetDigitalAssetAddressByLabel(currency.Label) if err == nil { http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict) return } if err := userMgr.SaveVirtualCurrency(username, currency); err != nil { log.Error("ERROR while saving virtual currency:\n", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } u, err = userMgr.GetByName(username) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } newWallet := u.DigitalWallet // respond with created phone number. w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(newWallet) }
// GetTwoFactorAuthenticationMethods returns the possible two factor authentication methods the user can use to login with. func (service *Service) GetTwoFactorAuthenticationMethods(w http.ResponseWriter, request *http.Request) { loginSession, err := service.GetSession(request, SessionLogin, "loginsession") if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } username, ok := loginSession.Values["username"].(string) if username == "" || !ok { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } userMgr := user.NewManager(request) userFromDB, err := userMgr.GetByName(username) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } response := struct { Totp bool `json:"totp"` Sms map[string]string `json:"sms"` }{Sms: make(map[string]string)} totpMgr := totp.NewManager(request) response.Totp, err = totpMgr.HasTOTP(username) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } valMgr := validationdb.NewManager(request) verifiedPhones, err := valMgr.GetByUsernameValidatedPhonenumbers(username) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } for _, validatedPhoneNumber := range verifiedPhones { for _, number := range userFromDB.Phonenumbers { if number.Phonenumber == string(validatedPhoneNumber.Phonenumber) { response.Sms[number.Label] = string(validatedPhoneNumber.Phonenumber) } } } json.NewEncoder(w).Encode(response) return }
// GetDigitalWallet is handler for GET /users/{username}/digitalwallet func (api UsersAPI) GetDigitalWallet(w http.ResponseWriter, r *http.Request) { username := mux.Vars(r)["username"] userMgr := user.NewManager(r) useobj, err := userMgr.GetByName(username) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } if len(useobj.DigitalWallet) == 0 { useobj.DigitalWallet = make([]user.DigitalAssetAddress, 0) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(useobj.DigitalWallet) }
// GetDigitalAssetAddress It is handler for GET /users/{username}/digitalwallet/{label} func (api UsersAPI) GetDigitalAssetAddress(w http.ResponseWriter, r *http.Request) { username := mux.Vars(r)["username"] label := mux.Vars(r)["label"] userMgr := user.NewManager(r) userobj, err := userMgr.GetByName(username) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } currency, err := userobj.GetDigitalAssetAddressByLabel(label) if err != nil { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(currency) }
func SearchUser(r *http.Request, searchString string) (usr *user.User, err1 error) { userMgr := user.NewManager(r) usr, err1 = userMgr.GetByName(searchString) if err1 == mgo.ErrNotFound { valMgr := validationdb.NewManager(r) validatedPhonenumber, err2 := valMgr.GetByPhoneNumber(searchString) if err2 == mgo.ErrNotFound { validatedEmailAddress, err3 := valMgr.GetByEmailAddress(searchString) if err3 != nil { return nil, err3 } else { return userMgr.GetByName(validatedEmailAddress.Username) } } else { return userMgr.GetByName(validatedPhonenumber.Username) } } else { return usr, err1 } }
func (service *Service) GithubCallback(w http.ResponseWriter, request *http.Request) { var code = request.URL.Query().Get("code") // Get GitHub access token clientId, err := identityservice.GetOauthClientID("github") log.Info("clientId") log.Info(clientId) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } clientSecret, err := identityservice.GetOauthSecret("github") if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } redirect_uri := "https://" + request.Host + "/github_callback" var oauthUrl = fmt.Sprintf("https://github.com/login/oauth/access_token?&client_id=%s&client_secret=%s&code=%s&redirect_uri=%s", clientId, clientSecret, code, redirect_uri) var githubUserInfo user.GithubAccount httpClient := &http.Client{} req, _ := http.NewRequest("POST", oauthUrl, nil) req.Header.Add("Accept", "application/json") // Get access token from Github response, err := httpClient.Do(req) if err != nil || response.StatusCode != 200 { log.Error(response.Status) log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } githubResponse := struct { Access_token string Scope string Token_type string Error string Error_description string Error_uri string }{} if err := json.NewDecoder(response.Body).Decode(&githubResponse); err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if githubResponse.Error != "" { log.Error(githubResponse) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } // Get user info from github var apiUrl = fmt.Sprintf("https://api.github.com/user?access_token=%s", githubResponse.Access_token) req, _ = http.NewRequest("GET", apiUrl, nil) // Get GitHub profile info from this user response, err = httpClient.Do(req) if err != nil || response.StatusCode != 200 { log.Error(response.Status) log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if err := json.NewDecoder(response.Body).Decode(&githubUserInfo); err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } userMgr := user.NewManager(request) // Save Github user info in db var loggedInUser, e = service.GetLoggedInUser(request, w) if e != nil { log.Error(e) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if err := userMgr.UpdateGithubAccount(loggedInUser, githubUserInfo); err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } http.Redirect(w, request, "/", http.StatusTemporaryRedirect) }
func (service *Service) FacebookCallback(w http.ResponseWriter, request *http.Request) { var code = request.URL.Query().Get("code") var redirectUri = "https://" + request.Host + "/facebook_callback" clientId, err := identityservice.GetOauthClientID("facebook") if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } clientSecret, err := identityservice.GetOauthSecret("facebook") if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } var oauthUrl = fmt.Sprintf("https://graph.facebook.com/v2.6/oauth/access_token?client_id=%s&client_secret=%s&code=%s&redirect_uri=%s", clientId, clientSecret, code, redirectUri) var fbInfo user.FBInfo httpClient := &http.Client{} req, _ := http.NewRequest("POST", oauthUrl, nil) // Get access token from Github response, _ := httpClient.Do(req) facebookResponse := struct { Access_token string Token_type string Expires_in int Error user.FacebookError }{} if err := json.NewDecoder(response.Body).Decode(&facebookResponse); err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if facebookResponse.Error.Message != "" { log.Error(facebookResponse.Error) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } // Get Facebook user info using the Graph API. var fields = "id,picture,link,name" var apiUrl = fmt.Sprintf("https://graph.facebook.com/v2.6/me/?access_token=%s&fields=%s", facebookResponse.Access_token, fields) req, _ = http.NewRequest("GET", apiUrl, nil) response, _ = httpClient.Do(req) if err := json.NewDecoder(response.Body).Decode(&fbInfo); err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } // Save facebook info in database. userMgr := user.NewManager(request) var loggedInUser, e = service.GetLoggedInUser(request, w) if e != nil { log.Error(e) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } var fbAccount user.FacebookAccount fbAccount.Id = fbInfo.Id fbAccount.Name = fbInfo.Name fbAccount.Picture = fbInfo.Picture.Data.Url fbAccount.Link = fbInfo.Link if err := userMgr.UpdateFacebookAccount(loggedInUser, fbAccount); err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } http.Redirect(w, request, "/", http.StatusTemporaryRedirect) }
//ProcessRegistrationForm processes the user registration form func (service *Service) ProcessRegistrationForm(w http.ResponseWriter, request *http.Request) { response := struct { Redirecturl string `json:"redirecturl"` Error string `json:"error"` }{} values := struct { TwoFAMethod string `json:"twofamethod"` Login string `json:"login"` Email string `json:"email"` Phonenumber string `json:"phonenumber"` TotpCode string `json:"totpcode"` Password string `json:"password"` RedirectParams string `json:"redirectparams"` }{} if err := json.NewDecoder(request.Body).Decode(&values); err != nil { log.Debug("Error decoding the registration request:", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } twoFAMethod := values.TwoFAMethod if twoFAMethod != "sms" && twoFAMethod != "totp" { log.Info("Invalid 2fa method during registration: ", twoFAMethod) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } totpsession, err := service.GetSession(request, SessionForRegistration, "totp") if err != nil { log.Error("ERROR while getting the totp registration session", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if totpsession.IsNew { log.Debug("New registration session while processing the registration form") http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } totpsecret, ok := totpsession.Values["secret"].(string) if !ok { log.Error("Unable to convert the stored session totp secret to a string") http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } valid := user.ValidateUsername(values.Login) var phonenumber user.Phonenumber if !valid { response.Error = "invalid_username_format" w.WriteHeader(422) json.NewEncoder(w).Encode(response) return } newuser := &user.User{ Username: values.Login, EmailAddresses: []user.EmailAddress{user.EmailAddress{Label: "main", EmailAddress: values.Email}}, } //validate the username is not taken yet userMgr := user.NewManager(request) count, err := userMgr.GetPendingRegistrationsCount() if err != nil { log.Error("Failed to get pending registerations count: ", err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } log.Debug("count", count) if count >= MAX_PENDING_REGISTRATION_COUNT { log.Warn("Maximum amount of pending registrations reached") http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } //we now just depend on mongo unique index to avoid duplicates when concurrent requests are made userExists, err := userMgr.Exists(newuser.Username) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if userExists { log.Debug("USER ", newuser.Username, " already registered") http.Error(w, http.StatusText(http.StatusConflict), http.StatusConflict) return } if twoFAMethod == "sms" { phonenumber = user.Phonenumber{Label: "main", Phonenumber: values.Phonenumber} if !phonenumber.IsValid() { log.Debug("Invalid phone number") w.WriteHeader(422) response.Error = "invalid_phonenumber" json.NewEncoder(w).Encode(&response) return } newuser.Phonenumbers = []user.Phonenumber{phonenumber} // Remove account after 3 days if it still doesn't have a verified phone by then duration := time.Duration(time.Hour * 24 * 3) expiresAt := time.Now() expiresAt = expiresAt.Add(duration) newuser.Expire = db.DateTime(expiresAt) } else { token := totp.TokenFromSecret(totpsecret) if !token.Validate(values.TotpCode) { log.Debug("Invalid totp code") w.WriteHeader(422) response.Error = "invalid_totpcode" json.NewEncoder(w).Encode(&response) return } } userMgr.Save(newuser) passwdMgr := password.NewManager(request) err = passwdMgr.Save(newuser.Username, values.Password) if err != nil { log.Error(err) if err.Error() != "internal_error" { w.WriteHeader(422) response.Error = "invalid_password" json.NewEncoder(w).Encode(&response) } else { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } return } if twoFAMethod == "sms" { validationkey, err := service.phonenumberValidationService.RequestValidation(request, newuser.Username, phonenumber, fmt.Sprintf("https://%s/phonevalidation", request.Host)) if err != nil { log.Error(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } registrationSession, err := service.GetSession(request, SessionForRegistration, "registrationdetails") registrationSession.Values["username"] = newuser.Username registrationSession.Values["phonenumbervalidationkey"] = validationkey registrationSession.Values["redirectparams"] = values.RedirectParams sessions.Save(request, w) response.Redirecturl = fmt.Sprintf("https://%s/register#/smsconfirmation", request.Host) json.NewEncoder(w).Encode(&response) return } totpMgr := totp.NewManager(request) totpMgr.Save(newuser.Username, totpsecret) log.Debugf("Registered %s", newuser.Username) service.loginUser(w, request, newuser.Username) }
//ProcessPhonenumberConfirmationForm processes the Phone number confirmation form func (service *Service) ProcessPhonenumberConfirmationForm(w http.ResponseWriter, request *http.Request) { values := struct { Smscode string `json:"smscode"` }{} response := struct { RedirectUrL string `json:"redirecturl"` Error string `json:"error"` }{} if err := json.NewDecoder(request.Body).Decode(&values); err != nil { log.Debug("Error decoding the ProcessPhonenumberConfirmation request:", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } registrationSession, err := service.GetSession(request, SessionForRegistration, "registrationdetails") if err != nil { log.Debug(err) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if registrationSession.IsNew { sessions.Save(request, w) response.RedirectUrL = fmt.Sprintf("https://%s/register/#/smsconfirmation", request.Host) json.NewEncoder(w).Encode(&response) return } username, _ := registrationSession.Values["username"].(string) validationkey, _ := registrationSession.Values["phonenumbervalidationkey"].(string) if isConfirmed, _ := service.phonenumberValidationService.IsConfirmed(request, validationkey); isConfirmed { userMgr := user.NewManager(request) userMgr.RemoveExpireDate(username) service.loginUser(w, request, username) return } smscode := values.Smscode if err != nil || smscode == "" { log.Debug(err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } err = service.phonenumberValidationService.ConfirmValidation(request, validationkey, smscode) if err == validation.ErrInvalidCode { w.WriteHeader(422) response.Error = "invalid_sms_code" json.NewEncoder(w).Encode(&response) return } if err == validation.ErrInvalidOrExpiredKey { sessions.Save(request, w) http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) json.NewEncoder(w).Encode(&response) return } else if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } userMgr := user.NewManager(request) userMgr.RemoveExpireDate(username) service.loginUser(w, request, username) }
//Process2FASMSConfirmation checks the totp 2 factor authentication code func (service *Service) Process2FASMSConfirmation(w http.ResponseWriter, request *http.Request) { username, err := service.getUserLoggingIn(request) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if username == "" { sessions.Save(request, w) http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } values := struct { Smscode string `json:"smscode"` }{} if err := json.NewDecoder(request.Body).Decode(&values); err != nil { log.Debug("Error decoding the totp confirmation request:", err) http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) return } sessionInfo, err := service.getLoginSessionInformation(request, "") if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } if sessionInfo == nil { loginSession, err := service.GetSession(request, SessionLogin, "loginsession") if err != nil { if err == mgo.ErrNotFound { http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } validationkey, _ := loginSession.Values["phonenumbervalidationkey"].(string) err = service.phonenumberValidationService.ConfirmValidation(request, validationkey, values.Smscode) if err == validation.ErrInvalidCode { // TODO: limit to 3 failed attempts w.WriteHeader(422) log.Debug("invalid code") return } } else if !sessionInfo.Confirmed { //Already confirmed on the phone validsmscode := (values.Smscode == sessionInfo.SMSCode) if !validsmscode { // TODO: limit to 3 failed attempts w.WriteHeader(422) log.Debugf("Expected code %s, got %s", sessionInfo.SMSCode, values.Smscode) return } } userMgr := user.NewManager(request) userMgr.RemoveExpireDate(username) //add last 2fa date if logging in with oauth2 service.storeLast2FALogin(request, username) service.loginUser(w, request, username) }
// DeleteOrganization is the handler for DELETE /organizations/{globalid} // Deletes an organization and all data linked to it (join-organization-invitations, oauth_access_tokens, oauth_clients, authorizations) func (api OrganizationsAPI) DeleteOrganization(w http.ResponseWriter, r *http.Request) { globalid := mux.Vars(r)["globalid"] orgMgr := organization.NewManager(r) logoMgr := organization.NewLogoManager(r) if !orgMgr.Exists(globalid) { writeErrorResponse(w, http.StatusNotFound, "organization_not_found") return } suborganizations, err := orgMgr.GetSubOrganizations(globalid) if handleServerError(w, "fetching suborganizations", err) { return } if len(suborganizations) != 0 { writeErrorResponse(w, 422, "organization_has_children") return } err = orgMgr.Remove(globalid) if handleServerError(w, "removing organization", err) { return } // Remove the organizations as a member/ an owner of other organizations organizations, err := orgMgr.AllByOrg(globalid) if handleServerError(w, "fetching organizations where this org is an owner/a member", err) { return } for _, org := range organizations { err = orgMgr.RemoveOrganization(org.Globalid, globalid) if handleServerError(w, "removing organizations as a member / an owner of another organization", err) { return } } if logoMgr.Exists(globalid) { err = logoMgr.Remove(globalid) if handleServerError(w, "removing organization logo", err) { return } } orgReqMgr := invitations.NewInvitationManager(r) err = orgReqMgr.RemoveAll(globalid) if handleServerError(w, "removing organization invitations", err) { return } oauthMgr := oauthservice.NewManager(r) err = oauthMgr.RemoveTokensByGlobalId(globalid) if handleServerError(w, "removing organization oauth accesstokens", err) { return } err = oauthMgr.DeleteAllForOrganization(globalid) if handleServerError(w, "removing client secrets", err) { return } err = oauthMgr.RemoveClientsById(globalid) if handleServerError(w, "removing organization oauth clients", err) { return } userMgr := user.NewManager(r) err = userMgr.DeleteAllAuthorizations(globalid) if handleServerError(w, "removing all authorizations", err) { return } err = oauthMgr.RemoveClientsById(globalid) if handleServerError(w, "removing organization oauth clients", err) { return } l2faMgr := organization.NewLast2FAManager(r) err = l2faMgr.RemoveByOrganization(globalid) if handleServerError(w, "removing organization 2FA history", err) { return } w.WriteHeader(http.StatusNoContent) }