From 68131ca7a37bded8a00f745cb71fa538d26746e9 Mon Sep 17 00:00:00 2001 From: krombel Date: Mon, 23 Jul 2018 15:40:35 +0200 Subject: [PATCH] Handle AS with auth header (#548) * Handle AS with auth header * fix lint (gocyclo) --- .../dendrite/clientapi/auth/auth.go | 8 ++-- .../dendrite/clientapi/routing/register.go | 37 +++++-------------- 2 files changed, 13 insertions(+), 32 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 80df0e728..a5a9b2bf9 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/auth/auth.go +++ b/src/github.com/matrix-org/dendrite/clientapi/auth/auth.go @@ -72,7 +72,7 @@ func VerifyUserFromRequest( } // Try to find the Application Service user - token, err := extractAccessToken(req) + token, err := ExtractAccessToken(req) if err != nil { return nil, &util.JSONResponse{ Code: http.StatusUnauthorized, @@ -150,7 +150,7 @@ func verifyUserParameters(req *http.Request) *util.JSONResponse { // 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 verifyAccessToken(req *http.Request, deviceDB DeviceDatabase) (device *authtypes.Device, resErr *util.JSONResponse) { - token, err := extractAccessToken(req) + token, err := ExtractAccessToken(req) if err != nil { resErr = &util.JSONResponse{ Code: http.StatusUnauthorized, @@ -184,9 +184,9 @@ func GenerateAccessToken() (string, error) { return base64.RawURLEncoding.EncodeToString(b), nil } -// extractAccessToken from a request, or return an error detailing what went wrong. The +// 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) { +func ExtractAccessToken(req *http.Request) (string, error) { // cf https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/api/auth.py#L631 authBearer := req.Header.Get("Authorization") queryToken := req.URL.Query().Get("access_token") diff --git a/src/github.com/matrix-org/dendrite/clientapi/routing/register.go b/src/github.com/matrix-org/dendrite/clientapi/routing/register.go index ee8259315..ef8577709 100644 --- a/src/github.com/matrix-org/dendrite/clientapi/routing/register.go +++ b/src/github.com/matrix-org/dendrite/clientapi/routing/register.go @@ -374,7 +374,13 @@ func validateApplicationService( ) (string, *util.JSONResponse) { // Check if the token if the application service is valid with one we have // registered in the config. - accessToken := req.URL.Query().Get("access_token") + accessToken, err := auth.ExtractAccessToken(req) + if err != nil { + return "", &util.JSONResponse{ + Code: http.StatusUnauthorized, + JSON: jsonerror.MissingToken(err.Error()), + } + } var matchedApplicationService *config.ApplicationService for _, appservice := range cfg.Derived.ApplicationServices { if appservice.ASToken == accessToken { @@ -419,22 +425,6 @@ func validateApplicationService( return matchedApplicationService.ID, nil } -// authTypeIsValid checks the registration authentication type of the request -// and returns true or false depending on whether the auth type is valid -func authTypeIsValid(authType *authtypes.LoginType, req *http.Request) bool { - // If no auth type is specified by the client, send back the list of available flows - if *authType == "" && req.URL.Query().Get("access_token") != "" { - // Assume this is an application service registering a user if an empty login - // type was provided alongside an access token - *authType = authtypes.LoginTypeApplicationService - } else if *authType == "" { - // Not an access token, and no login type. Send back the flows - return false - } - - return true -} - // Register processes a /register request. // http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register func Register( @@ -474,16 +464,6 @@ func Register( r.Username = strconv.FormatInt(id, 10) } - // Check r.Auth.Type is correct for the client requesting (handles application - // services requesting without an auth type) - if !authTypeIsValid(&r.Auth.Type, req) { - return util.JSONResponse{ - Code: http.StatusUnauthorized, - JSON: newUserInteractiveResponse(sessionID, - cfg.Derived.Registration.Flows, cfg.Derived.Registration.Params), - } - } - // Squash username to all lowercase letters r.Username = strings.ToLower(r.Username) @@ -562,7 +542,8 @@ func handleRegistrationFlow( // Add SharedSecret to the list of completed registration stages sessions.AddCompletedStage(sessionID, authtypes.LoginTypeSharedSecret) - case authtypes.LoginTypeApplicationService: + case "", authtypes.LoginTypeApplicationService: + // not passing a Auth.Type is allowed for ApplicationServices. So assume that as well // Check application service register user request is valid. // The application service's ID is returned if so. appserviceID, err := validateApplicationService(cfg, req, r.Username)