149 lines
3.5 KiB
Go
149 lines
3.5 KiB
Go
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)
|
|
}
|