From c9ffdd98d40695a0ecc819e35ff03b4f272c8a09 Mon Sep 17 00:00:00 2001 From: Kegan Dougal Date: Mon, 22 May 2017 17:25:39 +0100 Subject: [PATCH] Begin fleshing out how CS API endpoints do auth properly Without it being a GIGANTIC PITA --- .../dendrite/clientapi/auth/auth.go | 40 ++++++++++++++----- .../clientapi/auth/storage/devices/storage.go | 12 ++++++ .../dendrite/clientapi/routing/routing.go | 13 ++++++ 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/github.com/matrix-org/dendrite/clientapi/auth/auth.go b/src/github.com/matrix-org/dendrite/clientapi/auth/auth.go index c6c54d781..550bba9a8 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/auth.go +++ b/src/github.com/matrix-org/dendrite/clientapi/auth/auth.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +// Package auth implements authentication checks and storage. package auth import ( @@ -19,31 +20,48 @@ import ( "net/http" "strings" + "github.com/matrix-org/dendrite/clientapi/auth/storage/devices" + "github.com/matrix-org/dendrite/clientapi/auth/types" "github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/util" ) -// VerifyAccessToken verifies that an access token was supplied in the given HTTP request -// and returns the user ID it corresponds to. Returns resErr (an error response which can be -// sent to the client) if the token is invalid or there was a problem querying the database. +// VerifyAccessToken TODO: Remove me. func VerifyAccessToken(req *http.Request) (userID string, resErr *util.JSONResponse) { - token, tokenErr := extractAccessToken(req) - if tokenErr != nil { + token, err := extractAccessToken(req) + if err != nil { resErr = &util.JSONResponse{ Code: 401, - JSON: jsonerror.MissingToken(tokenErr.Error()), + JSON: jsonerror.MissingToken(err.Error()), } return } - if token == "fail" { - res := util.ErrorResponse(fmt.Errorf("Fatal error")) - resErr = &res - } - // TODO: Check the token against the database userID = token return } +// VerifyAccessTokenNew verifies that an access token was supplied in the given HTTP request +// and returns the device it corresponds to. Returns resErr (an error response which can be +// sent to the client) if the token is invalid or there was a problem querying the database. +func VerifyAccessTokenNew(req *http.Request, deviceDB *devices.Database) (device *types.Device, resErr *util.JSONResponse) { + token, err := extractAccessToken(req) + if err != nil { + resErr = &util.JSONResponse{ + Code: 401, + JSON: jsonerror.MissingToken(err.Error()), + } + return + } + device, err = deviceDB.GetDeviceByAccessToken(token) + if err != nil { + resErr = &util.JSONResponse{ + Code: 500, + JSON: jsonerror.Unknown("Failed to check access token"), + } + } + return +} + // extractAccessToken from a request, or return an error detailing what went wrong. The // error message MUST be human-readable and comprehensible to the client. func extractAccessToken(req *http.Request) (string, error) { diff --git a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/devices/storage.go b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/devices/storage.go index 842d6bbe5..9c2ae04ff 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/storage/devices/storage.go +++ b/src/github.com/matrix-org/dendrite/clientapi/auth/storage/devices/storage.go @@ -14,6 +14,10 @@ package devices +import ( + "github.com/matrix-org/dendrite/clientapi/auth/types" +) + // Database represents a device database. type Database struct { // TODO @@ -23,3 +27,11 @@ type Database struct { func NewDatabase() *Database { return &Database{} } + +// GetDeviceByAccessToken returns the device matching the given access token. +func (d *Database) GetDeviceByAccessToken(token string) (*types.Device, error) { + // TODO: Actual implementation + return &types.Device{ + UserID: token, + }, nil +} diff --git a/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go b/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go index 0e04dba86..df5278416 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go +++ b/src/github.com/matrix-org/dendrite/clientapi/routing/routing.go @@ -20,6 +20,7 @@ import ( "github.com/gorilla/mux" "github.com/matrix-org/dendrite/clientapi/auth/storage" + "github.com/matrix-org/dendrite/clientapi/auth/types" "github.com/matrix-org/dendrite/clientapi/config" "github.com/matrix-org/dendrite/clientapi/producers" "github.com/matrix-org/dendrite/clientapi/readers" @@ -151,6 +152,18 @@ func Setup(servMux *http.ServeMux, httpClient *http.Client, cfg config.ClientAPI servMux.Handle("/api/", http.StripPrefix("/api", apiMux)) } +// make a util.JSONRequestHandler function into an http.Handler which checks the access token in the request. +func makeAuthAPI(metricsName string, deviceDB *devices.Database, f func(*http.Request, types.Device) util.JSONResponse) http.Handler { + h := util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse { + device, resErr := auth.VerifyAccessToken(req, deviceDB) + if resErr != nil { + return resErr + } + return f(req, device) + }) + return prometheus.InstrumentHandler(metricsName, util.MakeJSONAPI(h)) +} + // make a util.JSONRequestHandler function into an http.Handler. func makeAPI(metricsName string, f func(*http.Request) util.JSONResponse) http.Handler { h := util.NewJSONRequestHandler(f)