From 1fbb57921207b47b4f5e8f572119390b4194db6c Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Thu, 8 Sep 2016 13:43:18 +0100 Subject: [PATCH] Add /admin/removeAuthSession Allows users to nuke their OAuth credentials. Currently this just does a database `DELETE` as neither Github nor JIRA need you to hit any special `/logout` API. --- src/github.com/matrix-org/go-neb/api.go | 36 +++++++++++++++++++ .../matrix-org/go-neb/database/db.go | 8 +++++ .../matrix-org/go-neb/database/schema.go | 9 +++++ src/github.com/matrix-org/go-neb/goneb.go | 1 + 4 files changed, 54 insertions(+) diff --git a/src/github.com/matrix-org/go-neb/api.go b/src/github.com/matrix-org/go-neb/api.go index 6cb690a..9eec530 100644 --- a/src/github.com/matrix-org/go-neb/api.go +++ b/src/github.com/matrix-org/go-neb/api.go @@ -58,6 +58,42 @@ func (h *requestAuthSessionHandler) OnIncomingRequest(req *http.Request) (interf return response, nil } +type removeAuthSessionHandler struct { + db *database.ServiceDB +} + +func (h *removeAuthSessionHandler) OnIncomingRequest(req *http.Request) (interface{}, *errors.HTTPError) { + if req.Method != "POST" { + return nil, &errors.HTTPError{nil, "Unsupported Method", 405} + } + var body struct { + RealmID string + UserID string + } + if err := json.NewDecoder(req.Body).Decode(&body); err != nil { + return nil, &errors.HTTPError{err, "Error parsing request JSON", 400} + } + log.WithFields(log.Fields{ + "realm_id": body.RealmID, + "user_id": body.UserID, + }).Print("Incoming remove auth session request") + + if body.UserID == "" || body.RealmID == "" { + return nil, &errors.HTTPError{nil, `Must supply a "UserID", a "RealmID"`, 400} + } + + _, err := h.db.LoadAuthRealm(body.RealmID) + if err != nil { + return nil, &errors.HTTPError{err, "Unknown RealmID", 400} + } + + if err := h.db.RemoveAuthSession(body.RealmID, body.UserID); err != nil { + return nil, &errors.HTTPError{err, "Failed to remove auth session", 500} + } + + return []byte(`{}`), nil +} + type realmRedirectHandler struct { db *database.ServiceDB } diff --git a/src/github.com/matrix-org/go-neb/database/db.go b/src/github.com/matrix-org/go-neb/database/db.go index bb3fdc2..da4e9a5 100644 --- a/src/github.com/matrix-org/go-neb/database/db.go +++ b/src/github.com/matrix-org/go-neb/database/db.go @@ -197,6 +197,14 @@ func (d *ServiceDB) StoreAuthSession(session types.AuthSession) (old types.AuthS return } +// RemoveAuthSession removes the auth session for the given user on the given realm. +// No error is returned if the session did not exist in the first place. +func (d *ServiceDB) RemoveAuthSession(realmID, userID string) error { + return runTransaction(d.db, func(txn *sql.Tx) error { + return deleteAuthSessionTxn(txn, realmID, userID) + }) +} + // LoadAuthSessionByUser loads an AuthSession from the database based on the given // realm and user ID. // Returns sql.ErrNoRows if the session isn't in the database. diff --git a/src/github.com/matrix-org/go-neb/database/schema.go b/src/github.com/matrix-org/go-neb/database/schema.go index 0a56857..2f744ad 100644 --- a/src/github.com/matrix-org/go-neb/database/schema.go +++ b/src/github.com/matrix-org/go-neb/database/schema.go @@ -336,6 +336,15 @@ func insertAuthSessionTxn(txn *sql.Tx, now time.Time, session types.AuthSession) return err } +const deleteAuthSessionSQL = ` +DELETE FROM auth_sessions WHERE realm_id=$1 AND user_id=$2 +` + +func deleteAuthSessionTxn(txn *sql.Tx, realmID, userID string) error { + _, err := txn.Exec(deleteAuthSessionSQL, realmID, userID) + return err +} + const selectAuthSessionByUserSQL = ` SELECT session_id, realm_type, realm_json, session_json FROM auth_sessions JOIN auth_realms ON auth_sessions.realm_id = auth_realms.realm_id diff --git a/src/github.com/matrix-org/go-neb/goneb.go b/src/github.com/matrix-org/go-neb/goneb.go index 0d99e47..e0811ad 100644 --- a/src/github.com/matrix-org/go-neb/goneb.go +++ b/src/github.com/matrix-org/go-neb/goneb.go @@ -63,6 +63,7 @@ func main() { http.Handle("/admin/configureService", server.MakeJSONAPI(newConfigureServiceHandler(db, clients))) http.Handle("/admin/configureAuthRealm", server.MakeJSONAPI(&configureAuthRealmHandler{db: db})) http.Handle("/admin/requestAuthSession", server.MakeJSONAPI(&requestAuthSessionHandler{db: db})) + http.Handle("/admin/removeAuthSession", server.MakeJSONAPI(&removeAuthSessionHandler{db: db})) wh := &webhookHandler{db: db, clients: clients} http.HandleFunc("/services/hooks/", wh.handle) rh := &realmRedirectHandler{db: db}