// reads the configuration file from the path specified by // the config command line flag. func readConfig(configFile string) error { b, err := ioutil.ReadFile(configFile) if err != nil { return err } err = json.Unmarshal(b, &config) if err != nil { return err } cookieAuthKey, err = hex.DecodeString(*config.CookieAuthKeyHexStr) if err != nil { return err } cookieEncrKey, err = hex.DecodeString(*config.CookieEncrKeyHexStr) if err != nil { return err } secureCookie = securecookie.New(cookieAuthKey, cookieEncrKey) // verify auth/encr keys are correct val := map[string]string{ "foo": "bar", } _, err = secureCookie.Encode(cookieName, val) if err != nil { // for convenience, if the auth/encr keys are not set, // generate valid, random value for them auth := securecookie.GenerateRandomKey(32) encr := securecookie.GenerateRandomKey(32) fmt.Printf("auth: %s\nencr: %s\n", hex.EncodeToString(auth), hex.EncodeToString(encr)) } // TODO: somehow verify twitter creds return err }
// Save adds a single session to the response. func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter, session *Session) error { if session.ID == "" { session.ID = string(securecookie.GenerateRandomKey(32)) } if err := s.save(session); err != nil { return err } encoded, err := securecookie.EncodeMulti(session.Name(), session.ID, s.Codecs...) if err != nil { return err } options := s.Options if session.Options != nil { options = session.Options } cookie := &http.Cookie{ Name: session.Name(), Value: encoded, Path: options.Path, Domain: options.Domain, MaxAge: options.MaxAge, Secure: options.Secure, HttpOnly: options.HttpOnly, } http.SetCookie(w, cookie) return nil }
func initSecureCookie(filename string) { key, err := ioutil.ReadFile(filename) if err != nil { key = securecookie.GenerateRandomKey(32) if key == nil { log.Fatal("Can't generate a secret!") } err = ioutil.WriteFile(filename, key, 0600) if err != nil { log.Fatal("Can't read or write .secret", err) } } scookie = securecookie.New(key, nil) }
// Save adds a single session to the response. func (s *DatastoreStore) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error { if session.ID == "" { session.ID = string(securecookie.GenerateRandomKey(32)) } if err := s.save(r, session); err != nil { return err } encoded, err := securecookie.EncodeMulti(session.Name(), session.ID, s.Codecs...) if err != nil { return err } http.SetCookie(w, sessions.NewCookie(session.Name(), encoded, session.Options)) return nil }
// Save adds a single session to the response. func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter, session *Session) error { if session.ID == "" { // Because the ID is used in the filename, encode it to // use alphanumeric characters only. session.ID = strings.TrimRight( base32.StdEncoding.EncodeToString( securecookie.GenerateRandomKey(32)), "=") } if err := s.save(session); err != nil { return err } encoded, err := securecookie.EncodeMulti(session.Name(), session.ID, s.Codecs...) if err != nil { return err } http.SetCookie(w, NewCookie(session.Name(), encoded, session.Options)) return nil }
package main import ( "code.google.com/p/gorilla/securecookie" mvc "github.com/cihub/trinity" names "github.com/cihub/trinity-examples/8-authentication-authorization/mvcnames" "net/http" ) var ( hashKey = securecookie.GenerateRandomKey(32) blockKey = securecookie.GenerateRandomKey(32) authCookieName = "auth" authCookieValue = "valid" ) type AuthProvider struct { } func (provider *AuthProvider) IsAccessAllowed( c mvc.Controller, a mvc.Action, response http.ResponseWriter, request *http.Request) mvc.ActionResultInterface { if (c == names.C.Home && a == names.A.Home.Index) || (c == names.C.Account && a == names.A.Account.Login) { return nil }
func runHttpServer(cfg *musebot.JsonCfg) { if len(cfg.SessionStoreAuthKey) != 32 && len(cfg.SessionStoreAuthKey) != 64 { b64 := base64.StdEncoding log.Fatalln("SessionStoreAuthKey must be 32 or 64 bytes long, not", len(cfg.SessionStoreAuthKey), "bytes! Here's a suggested value:", b64.EncodeToString(securecookie.GenerateRandomKey(64))) } sessionStore = sessions.NewCookieStore(cfg.SessionStoreAuthKey) // let's try to get the default provider defaultProvider, wasFound := musebot.CurrentProviders[config.DefaultProvider] if !wasFound { for _, p := range musebot.CurrentProviders { defaultProvider = p break } } // job ID generator go func(generatorPipe chan int) { i := 0 for { generatorPipe <- i i = i + 1 } }(jobIdGenerator) var eProviderNotFound = errors.New("Provider not found") // GO GO WEB HANDLER http.HandleFunc("/api/current_song/", func(w http.ResponseWriter, r *http.Request) { if !enforceLoggedIn(getSession(r), w) { return } currentSong, isPlaying, err := musebot.CurrentBackend.CurrentSong() if err != nil { writeApiResponse(w, wrapApiError(err)) } else { if isPlaying { writeApiResponse(w, musebot.CurrentSongApiResponse{Playing: isPlaying, CurrentSong: ¤tSong}) } else { writeApiResponse(w, musebot.CurrentSongApiResponse{Playing: isPlaying, CurrentSong: nil}) } } }) http.HandleFunc("/api/playback_queue/", func(w http.ResponseWriter, r *http.Request) { if !enforceLoggedIn(getSession(r), w) { return } playbackQueue, err := musebot.CurrentBackend.PlaybackQueue() if err != nil { writeApiResponse(w, wrapApiError(err)) } else { writeApiResponse(w, musebot.PlaybackQueueApiResponse{playbackQueue}) } }) http.HandleFunc("/api/search_and_queue_first/", func(w http.ResponseWriter, r *http.Request) { if !enforceLoggedIn(getSession(r), w) { return } // get the query! queryStrMap := r.URL.Query() queryArray, ok := queryStrMap["q"] if !ok || len(queryArray) < 1 || len(queryArray[0]) == 0 { writeApiResponse(w, wrapApiError(errors.New("You must pass a 'q' argument specifying the query!"))) return } query := queryArray[0] // cool searchRes, err := musebot.CurrentProviders["provider.GroovesharkProvider"].Search(query) if err != nil { writeApiResponse(w, wrapApiError(err)) return } if len(searchRes) == 0 { writeApiResponse(w, wrapApiError(errors.New("There were no results for that query."))) return } fetchChan := make(chan musebot.ProviderMessage, 1000) log.Println(searchRes[0].Title) go searchRes[0].Provider.FetchSong(&searchRes[0], fetchChan) waitToEnd := make(chan bool) go (func(fetchChan chan musebot.ProviderMessage, song *musebot.SongInfo, done chan bool) { for { msg := <-fetchChan log.Println(msg) if msg.Type == "done" { musebot.CurrentBackend.Add(*song) writeApiResponse(w, musebot.QueuedApiResponse{*song}) done <- true return } else if msg.Type == "error" { writeApiResponse(w, wrapApiError(msg.Content.(error))) done <- true return } } })(fetchChan, &searchRes[0], waitToEnd) <-waitToEnd }) http.HandleFunc("/api/available_providers/", func(w http.ResponseWriter, r *http.Request) { if !enforceLoggedIn(getSession(r), w) { return } outputBlah := make(map[string]string) for k, v := range musebot.CurrentProviders { outputBlah[k] = v.Name() } writeApiResponse(w, musebot.AvailableProvidersApiResponse{outputBlah}) }) http.HandleFunc("/api/search/", func(w http.ResponseWriter, r *http.Request) { if !enforceLoggedIn(getSession(r), w) { return } // get the query! queryStrMap := r.URL.Query() qArray, ok := queryStrMap["q"] if !ok || len(qArray) < 1 || len(qArray[0]) == 0 { writeApiResponse(w, wrapApiError(errors.New("You must pass a 'q' argument specifying the query!"))) return } q := qArray[0] // now the provider providerArray, ok := queryStrMap["provider"] var provider provider.Provider if !ok || len(providerArray) < 1 || len(providerArray[0]) == 0 { provider = defaultProvider } else { providerName := providerArray[0] provider, ok = musebot.CurrentProviders[providerName] if !ok { writeApiResponse(w, wrapApiError(eProviderNotFound)) return } } // now we have a provider, we can search! searchResults, err := provider.Search(q) if err != nil { writeApiResponse(w, wrapApiError(err)) return } writeApiResponse(w, musebot.SearchResultsApiResponse{searchResults}) }) http.HandleFunc("/api/logout/", func(w http.ResponseWriter, r *http.Request) { sess := getSession(r) result := true if !isLoggedIn(sess) { result = false } // cool sess.Values = map[interface{}]interface{}{} sess.Save(r, w) writeApiResponse(w, musebot.LoggedOutApiResponse{result}) return }) http.HandleFunc("/api/quit/", func(w http.ResponseWriter, r *http.Request) { if !enforceLoggedIn(getSession(r), w) { return } log.Println() log.Println("Exiting on request!") os.Exit(0) }) http.HandleFunc("/api/add_to_queue/", func(w http.ResponseWriter, r *http.Request) { sess := getSession(r) if !enforceLoggedIn(sess, w) { return } providerName := r.FormValue("provider") providerId := r.FormValue("provider_id") si := musebot.SongInfo{} si.ProviderName = providerName si.ProviderId = providerId provider, exists := musebot.CurrentProviders[providerName] if !exists { writeApiResponse(w, wrapApiError(errors.New("That provider doesn't exist."))) } si.Provider = provider log.Println("UPDATING SONG INFO") si.Provider.UpdateSongInfo(&si) log.Println(si) provMessage := make(chan musebot.ProviderMessage) quit := make(chan bool) go si.Provider.FetchSong(&si, provMessage) log.Println(si, provMessage) log.Println(sess.Values["username"]) go func(quit chan bool, provMessage chan musebot.ProviderMessage, w http.ResponseWriter, s *musebot.SongInfo, user string) { hasQuit := false jobId := <-jobIdGenerator var m musebot.ProviderMessage for { m = <-provMessage if m.Type == "error" { if !hasQuit { writeApiResponse(w, wrapApiError(m.Content.(error))) quit <- true return // done } } else if m.Type == "stages" { if !hasQuit { // tell them that we're AWESOME if m.Content == 0 { log.Println("ORDERING BACKEND TO ADD", s) musebot.CurrentBackend.Add(*s) writeApiResponse(w, musebot.QueuedApiResponse{*s}) quit <- true return // done } else { writeApiResponse(w, musebot.JobQueuedApiResponse{strconv.Itoa(jobId)}) quit <- true hasQuit = true } } } else if m.Type == "done" && hasQuit { musebot.CurrentBackend.Add(*s) } if hasQuit { outputData := musebot.JobWebSocketApiResponse{JobId: strconv.Itoa(jobId), Data: m} jsonData, _ := json.Marshal(outputData) userOutputData := UserMessage{user: user, message: "JOB_DATA " + string(jsonData)} h.broadcastUser <- userOutputData } } }(quit, provMessage, w, &si, sess.Values["username"].(string)) <-quit }) http.HandleFunc("/api/login/", func(w http.ResponseWriter, r *http.Request) { if r.TLS == nil { writeApiResponse(w, wrapApiError(errors.New("This method requires TLS! :<"))) return } sess := getSession(r) username := r.FormValue("username") password := r.FormValue("password") a := musebot.CurrentAuthenticator result, user, err := a.CheckLogin(username, password) if err != nil { writeApiResponse(w, wrapApiError(err)) return } if result { sess.Values["logged-in"] = true sess.Values["username"] = user.Username sess.Values["administrator"] = user.Administrator sess.Save(r, w) writeApiResponse(w, musebot.LoggedInApiResponse{username}) } else { writeApiResponse(w, wrapApiError(errors.New("The username or password was incorrect."))) } }) http.HandleFunc("/api/masquerade/", func(w http.ResponseWriter, r *http.Request) { if r.TLS == nil { writeApiResponse(w, wrapApiError(errors.New("This method requires TLS! :<"))) return } sess := getSession(r) if !enforceLoggedIn(sess, w) { return } if !isSessionBool(sess, "administrator") { writeApiResponse(w, wrapApiError(errors.New("You're not an administrator!"))) return } queryStrMap := r.URL.Query() qArray, ok := queryStrMap["username"] if !ok || len(qArray) < 1 || len(qArray[0]) == 0 { writeApiResponse(w, wrapApiError(errors.New("You must pass a 'username' argument specifying the user to masquerade as!"))) return } q := qArray[0] sess.Values["logged-in"] = true sess.Values["username"] = q sess.Values["administrator"] = true sess.Save(r, w) w.Write([]byte("YOU ARE NOW LOGGED IN AS ")) w.Write([]byte(q)) }) registerWsHandler() if len(cfg.ListenAddr) != 0 { httpServer := &http.Server{Addr: cfg.ListenAddr} go func() { log.Fatalln(httpServer.ListenAndServe()) }() log.Println(" - HTTP Server is listening on", cfg.ListenAddr) } if len(cfg.SslListenAddr) == 0 { log.Fatalln(" x The HTTPS server *must* run. Login will only take place over HTTPS.") } httpsServer := &http.Server{Addr: cfg.SslListenAddr} go func() { log.Fatalln(httpsServer.ListenAndServeTLS("ssl.pub.pem", "ssl.priv.pem")) }() log.Println(" - HTTPS Server is listening on", cfg.SslListenAddr) }
func init() { hashKey = securecookie.GenerateRandomKey(64) blockKey = securecookie.GenerateRandomKey(64) secureCookie = securecookie.New(hashKey, blockKey) }
func GenerateRandomBase64String(byteCount int) string { return base64.StdEncoding.EncodeToString(securecookie.GenerateRandomKey(byteCount)) }
func GenerateRandomBytes(byteCount int) []byte { return securecookie.GenerateRandomKey(byteCount) }