// NewAuthMiddleware new Auth Middleware func NewAuthMiddleware(headerKeyLabel string, headerSecretLabel string, config AuthConfig) *RESTGate { t := &RESTGate{headerKeyLabel: headerKeyLabel, headerSecretLabel: headerSecretLabel, config: config} if headerKeyLabel == "" { //headerKeyLabel must be defined if t.config.Debug == true { log.Printf("RestGate: headerKeyLabel is not defined.") } return nil } //Default Error Messages if t.config.ErrorMessages == nil { t.config.ErrorMessages = map[int]map[string]string{ 1: e.New(1, "No Key Or Secret", "").Render(), 2: e.New(2, "Unauthorized Access", "").Render(), } } else { if _, ok := t.config.ErrorMessages[1]; !ok { t.config.ErrorMessages[1] = e.New(1, "No Key Or Secret", "").Render() } if _, ok := t.config.ErrorMessages[2]; !ok { t.config.ErrorMessages[2] = e.New(2, "Unauthorized Access", "").Render() } } return t }
func NewRoute() *mux.Router { routes := mux.NewRouter().StrictSlash(false) r := render.New(render.Options{ Directory: "templates", IndentJSON: true, IsDevelopment: true, Layout: "layout", }) routes.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { r.Text(w, http.StatusOK, "Index page") }) routes.HandleFunc("/template", func(w http.ResponseWriter, req *http.Request) { r.HTML(w, http.StatusOK, "index", nil) }) routes.HandleFunc("/error", func(w http.ResponseWriter, req *http.Request) { err := e.New(12, "Unauthorized Access", "Please log in first to access this site") r.JSON(w, http.StatusUnauthorized, err.Render()) }) routes.HandleFunc("/data", func(w http.ResponseWriter, req *http.Request) { r.Data(w, http.StatusOK, []byte("Some binary data here.")) }) routes.Handle("/metrics", prometheus.Handler()) addStaticRoutes(routes) return routes }
// Returns an Optimus struct which can be used to encode and decode // integers. Usually used for obfuscating internal ids such as database // table rows. This method calculates the modInverse computationally. // Panics if prime is not valid. func NewCalculated(prime uint64, random uint64) Optimus { p := big.NewInt(int64(prime)) if p.ProbablyPrime(MILLER_RABIN) { return Optimus{prime, ModInverse(prime), random} } else { accuracy := 1.0 - 1.0/math.Pow(float64(4), float64(MILLER_RABIN)) panic(jsonerror.New(2, "Number is not prime", fmt.Sprintf("%d Miller-Rabin tests done. Accuracy: %f", MILLER_RABIN, accuracy))) } }
// Calculates the Modular Inverse of a given Prime number such that // (PRIME * MODULAR_INVERSE) & (MAX_INT_VALUE) = 1 // Panics if n is not a valid prime number. // See: http://en.wikipedia.org/wiki/Modular_multiplicative_inverse func ModInverse(n uint64) uint64 { p := big.NewInt(int64(n)) if !p.ProbablyPrime(MILLER_RABIN) { accuracy := 1.0 - 1.0/math.Pow(float64(4), float64(MILLER_RABIN)) panic(jsonerror.New(2, "Number is not prime", fmt.Sprintf("n=%d. %d Miller-Rabin tests done. Accuracy: %f", n, MILLER_RABIN, accuracy))) } var i big.Int prime := big.NewInt(int64(n)) max := big.NewInt(int64(MAX_INT + 1)) return i.ModInverse(prime, max).Uint64() }
func New(headerKeyLabel string, headerSecretLabel string, store KeyStore, config Config) *RESTGate { t := &RESTGate{headerKeyLabel: headerKeyLabel, headerSecretLabel: headerSecretLabel, config: config, store: store} log.Printf("RestGate initializing") if headerKeyLabel == "" { //headerKeyLabel must be defined if t.config.Debug == true { log.Printf("RestGate: headerKeyLabel is not defined.") } return nil } //Default Error Messages if t.config.ErrorMessages == nil { t.config.ErrorMessages = map[int]map[string]string{ 1: e.New(1, "No Key Or Secret", "", "com.github.pjebs.restgate").Render(), 2: e.New(2, "Unauthorized Access", "", "com.github.pjebs.restgate").Render(), 3: e.New(3, "Please use HTTPS connection", "", "com.github.pjebs.restgate").Render(), 99: e.New(99, "Software Developers have not setup authentication correctly", "", "com.github.pjebs.restgate").Render(), } } else { if _, ok := t.config.ErrorMessages[1]; !ok { t.config.ErrorMessages[1] = e.New(1, "No Key Or Secret", "", "com.github.pjebs.restgate").Render() } if _, ok := t.config.ErrorMessages[2]; !ok { t.config.ErrorMessages[2] = e.New(2, "Unauthorized Access", "", "com.github.pjebs.restgate").Render() } if _, ok := t.config.ErrorMessages[3]; !ok { t.config.ErrorMessages[3] = e.New(3, "Please use HTTPS connection", "", "com.github.pjebs.restgate").Render() } if _, ok := t.config.ErrorMessages[99]; !ok { t.config.ErrorMessages[99] = e.New(99, "Software Developers have not setup authentication correctly", "", "com.github.pjebs.restgate").Render() } } //Check if HTTPS Protection has been turned off if t.config.HTTPSProtectionOff { //HTTPS Protection is off log.Printf("\x1b[31mWARNING: HTTPS Protection is off. This is potentially insecure!\x1b[39;49m") } return t }
func (self *RESTGate) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) { //Check if HTTPS Protection has been turned off if !self.config.HTTPSProtectionOff { //HTTPS Protection is on so we must check it if !(strings.EqualFold(req.URL.Scheme, "https") || req.TLS != nil) { r := render.New(render.Options{}) r.JSON(w, http.StatusUnauthorized, self.config.ErrorMessages[3]) //"Please use HTTPS connection" return } } //Check key in Header key := req.Header.Get(self.headerKeyLabel) secret := req.Header.Get(self.headerSecretLabel) if key == "" { //Authentication Information not included in request r := render.New(render.Options{}) r.JSON(w, http.StatusUnauthorized, self.config.ErrorMessages[1]) //"No Key Or Secret" return } authenticationPassed, err := self.store.MatchKey(key, secret) if err != nil { if self.config.Debug == true { log.Printf("RestGate: Run time error: %+v", err) } r := render.New(render.Options{}) jerr := e.New(2, err.Error(), "", "com.github.pjebs.restgate").Render() r.JSON(w, http.StatusUnauthorized, jerr) //"Unauthorized Access" } if !authenticationPassed { r := render.New(render.Options{}) r.JSON(w, http.StatusUnauthorized, self.config.ErrorMessages[2]) //"Unauthorized Access" } else { if self.config.Context != nil { self.config.Context(req, key) } next(w, req) } }
"strconv" "strings" "text/template" "time" ) var minPort int var holeHost string var host string var configPath string var tplFile = "config.tpl" var port int var sg *sendgrid.SGClient var ErrorMessages = map[int]map[string]string{ 0: e.New(0, "", "Success").Render(), 1: e.New(1, "User is already exists.", "Please try a new one.").Render(), 2: e.New(2, "Email is already exists.", "Please try a new one or reset the password.").Render(), 3: e.New(3, "Email format error", "Please type a valid email.").Render(), 4: e.New(4, "User name or password invalid.", "").Render(), 5: e.New(5, "User is confimd or ConfirmationCode is expired.", "Resend a new confirmation code?").Render(), 6: e.New(6, "User is confimd.", "No need resend twice.").Render(), 7: e.New(7, "User NotFound.", "").Render(), 8: e.New(8, "Old password is not correct.", "").Render(), 9: e.New(9, "PasswordToken is expired.", "").Render(), 10: e.New(10, "HoleApp is not exists.", "").Render(), } var reEmail, _ = regexp.Compile("(\\w[-._\\w]*\\w@\\w[-._\\w]*\\w\\.\\w{2,3})") type NewUserForm struct {
// Generates a valid Optimus struct using a randomly selected prime // number from this site: http://primes.utm.edu/lists/small/millions/ // The first 50 million prime numbers are distributed evenly in 50 files. // Parameter req should be nil if not using Google App Engine. // This Function is Time, Memory and CPU intensive. Run it once to generate the // required seeds. // WARNING: Potentially Insecure. Double check that the prime number returned // is actually prime number using an independent source. // The largest Prime has 9 digits. The smallest has 1 digit. // The final return value is the website zip file identifier that was used to obtain the prime number func GenerateSeed(req *http.Request) (*Optimus, error, uint8) { log.Printf("\x1b[31mWARNING: Optimus generates a random number via this site: http://primes.utm.edu/lists/small/millions/. This is potentially insecure!\x1b[39;49m") baseURL := "http://primes.utm.edu/lists/small/millions/primes%d.zip" //Generate Random number between 1-50 b_49 := *big.NewInt(49) n, _ := rand.Int(rand.Reader, &b_49) i_n := n.Uint64() + 1 //Download zip file finalUrl := fmt.Sprintf(baseURL, i_n) log.Printf("Using file: %s", finalUrl) resp, err := client(req).Get(finalUrl) if err != nil { return nil, jsonerror.New(1, "Could not generate seed", err.Error()), uint8(i_n) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, jsonerror.New(1, "Could not generate seed", err.Error()), uint8(i_n) } r, err := zip.NewReader(bytes.NewReader(body), resp.ContentLength) if err != nil { return nil, jsonerror.New(1, "Could not generate seed", err.Error()), uint8(i_n) } zippedFile := r.File[0] src, err := zippedFile.Open() //src contains ReaderCloser if err != nil { return nil, jsonerror.New(1, "Could not generate seed", err.Error()), uint8(i_n) } defer src.Close() //Create a Byte Slice buf := new(bytes.Buffer) noOfBytes, _ := buf.ReadFrom(src) b := buf.Bytes() //Byte Slice //Randomly pick a character position start := 67 // Each zip file has an introductory header which is not relevant until the 67th character end := noOfBytes b_end := *big.NewInt(int64(end) - int64(start)) n, _ = rand.Int(rand.Reader, &b_end) randomPosition := n.Uint64() + uint64(start) min := randomPosition - 9 max := randomPosition + 9 if min < uint64(start) { min = uint64(start) } if max > uint64(end) { max = uint64(end) } scanner := bufio.NewScanner(strings.NewReader(string(b[min:max]))) //Input scanner.Split(bufio.ScanWords) var selectedNumbers []uint64 for scanner.Scan() { p, _ := strconv.ParseUint(scanner.Text(), 10, 64) selectedNumbers = append(selectedNumbers, p) } //Not perfect but good enough var selectedPrime uint64 length := len(selectedNumbers) if length > 2 { //Pick middle number //Check if length is even number //Check if round is odd or even var odd bool if length&1 != 0 { odd = true //odd } else { odd = false //even } if odd { selectedPrime = selectedNumbers[length/2] } else { r := *big.NewInt(1) rn, _ := rand.Int(rand.Reader, &r) if rn.Uint64() == 0 { selectedPrime = selectedNumbers[length/2] } else { selectedPrime = selectedNumbers[length/2-1] } } } else { //Pick largest number largest := selectedNumbers[0] for _, value := range selectedNumbers { if value > largest { largest = value } } selectedPrime = largest } //Calculate Mod Inverse for selectedPrime modInverse := ModInverse(selectedPrime) //Generate Random Integer less than MAX_INT upper := *big.NewInt(MAX_INT - 2) rand, _ := rand.Int(rand.Reader, &upper) randomNumber := rand.Uint64() + 1 return &Optimus{selectedPrime, modInverse, randomNumber}, nil, uint8(i_n) }
func New(headerKeyLabel string, headerSecretLabel string, as AuthenticationSource, config Config) *RESTGate { t := &RESTGate{headerKeyLabel: headerKeyLabel, headerSecretLabel: headerSecretLabel, source: as, config: config} log.Printf("RestGate initializing") numberKeys := len(t.config.Key) numberSecrets := len(t.config.Secret) if numberKeys == 0 { //Key is not set if t.config.Debug == true { log.Printf("RestGate: Key is not set") } return nil } if numberSecrets > numberKeys { //Too many Secret's defined if t.config.Debug == true { log.Printf("RestGate: Too many Secrets defined. At most there should be 1 secret per key") } return nil } if headerKeyLabel == "" { //headerKeyLabel must be defined if t.config.Debug == true { log.Printf("RestGate: headerKeyLabel is not defined.") } return nil } //Default Error Messages if t.config.ErrorMessages == nil { t.config.ErrorMessages = map[int]map[string]string{ 1: e.New(1, "No Key Or Secret", "", "com.github.pjebs.restgate").Render(), 2: e.New(2, "Unauthorized Access", "", "com.github.pjebs.restgate").Render(), 99: e.New(99, "Software Developers have not setup authentication correctly", "", "com.github.pjebs.restgate").Render(), } } if as == Database { if numberKeys != 1 { //We need exactly 1 Key (it represents field name in database) if t.config.Debug == true { log.Printf("RestGate: For Database mode, we need exactly 1 Key which represents the field name in the database table") } return nil } //Check if database is set. //The developer should ensure a database has been selected (i.e. to prevent "No Database selected" error) if t.config.DB == nil { //DB is not set if t.config.Debug == true { log.Printf("RestGate: Database is not set. Be sure that a database name is selected") } return nil } //Check if table is set if t.config.TableName == "" { //Table name is not set if t.config.Debug == true { log.Printf("RestGate: For Database mode, a table name is required") } return nil } } return t }