package http import ( "encoding/json" "io/ioutil" "log" "net/http" "net/url" "os" "strings" "git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP.git/xmpp" "gopkg.in/oauth2.v3/errors" "gopkg.in/oauth2.v3/manage" "gopkg.in/oauth2.v3/models" "gopkg.in/oauth2.v3/server" "gopkg.in/oauth2.v3/store" "gopkg.in/session.v1" ) const ( ROUTE_LOGIN = "/login" ROUTE_AUTHORIZE = "/authorize" ROUTE_TOKEN = "/token" ) var ( globalSessions *session.Manager manager *manage.Manager clientList []models.Client ) func init() { globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid","gclifetime":3600}`) go globalSessions.GC() } func LoadConfigClient(configFile string) error { file, err := ioutil.ReadFile(configFile) if err != nil { return err } return json.Unmarshal(file, &clientList) } func LoadOAuth() { manager = manage.NewDefaultManager() // token store manager.MustTokenStorage(store.NewMemoryTokenStore()) clientStore := store.NewClientStore() for _, c := range clientList { clientStore.Set(c.ID, &c) } manager.MapClientStorage(clientStore) } func LoadServer() { srv := server.NewServer(server.NewConfig(), manager) srv.SetUserAuthorizationHandler(userAuthorizeHandler) srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { log.Println("Internal Error:", err.Error()) return }) srv.SetResponseErrorHandler(func(re *errors.Response) { log.Println("Response Error:", re.Error.Error()) }) http.HandleFunc(ROUTE_LOGIN, loginHandler) http.HandleFunc(ROUTE_AUTHORIZE, func(w http.ResponseWriter, r *http.Request) { err := srv.HandleAuthorizeRequest(w, r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) } }) http.HandleFunc(ROUTE_TOKEN, func(w http.ResponseWriter, r *http.Request) { err := srv.HandleTokenRequest(w, r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } }) } func userAuthorizeHandler(w http.ResponseWriter, r *http.Request) (userID string, err error) { us, err := globalSessions.SessionStart(w, r) uid := us.Get("UserID") if uid == nil { if r.Form == nil { r.ParseForm() } us.Set("Form", r.Form) w.Header().Set("Location", ROUTE_LOGIN) w.WriteHeader(http.StatusFound) return } userID = uid.(string) us.Delete("UserID") return } func loginHandler(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { us, err := globalSessions.SessionStart(w, r) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } r.ParseForm() jid := strings.Join(r.Form["jid"], "") // TODO answer := xmpp.Confirm(jid, "GET", "toto.fr", "oauth2", -1) switch answer { case xmpp.REPLY_OK: us.Set("LoggedInUserID", jid) form := us.Get("Form").(url.Values) u := new(url.URL) u.Path = ROUTE_AUTHORIZE u.RawQuery = form.Encode() w.Header().Set("Location", u.String()) w.WriteHeader(http.StatusFound) us.Delete("Form") us.Set("UserID", us.Get("LoggedInUserID")) case xmpp.REPLY_DENY: w.WriteHeader(http.StatusUnauthorized) case xmpp.REPLY_UNREACHABLE: w.WriteHeader(StatusUnreachable) default: w.WriteHeader(StatusUnknownError) } return } outputHTML(w, r, "static/login.html") } func outputHTML(w http.ResponseWriter, req *http.Request, filename string) { file, err := os.Open(filename) if err != nil { http.Error(w, err.Error(), 500) return } defer file.Close() fi, _ := file.Stat() http.ServeContent(w, req, file.Name(), fi.ModTime(), file) }