HTTPAuthentificationOverXMPP/http/oauth.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)
}