Handle AS with auth header (#548)

* Handle AS with auth header

* fix lint (gocyclo)
main
krombel 2018-07-23 15:40:35 +02:00 committed by Andrew Morgan
parent d2ae425752
commit 68131ca7a3
2 changed files with 13 additions and 32 deletions

View File

@ -72,7 +72,7 @@ func VerifyUserFromRequest(
} }
// Try to find the Application Service user // Try to find the Application Service user
token, err := extractAccessToken(req) token, err := ExtractAccessToken(req)
if err != nil { if err != nil {
return nil, &util.JSONResponse{ return nil, &util.JSONResponse{
Code: http.StatusUnauthorized, 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 // 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. // 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) { func verifyAccessToken(req *http.Request, deviceDB DeviceDatabase) (device *authtypes.Device, resErr *util.JSONResponse) {
token, err := extractAccessToken(req) token, err := ExtractAccessToken(req)
if err != nil { if err != nil {
resErr = &util.JSONResponse{ resErr = &util.JSONResponse{
Code: http.StatusUnauthorized, Code: http.StatusUnauthorized,
@ -184,9 +184,9 @@ func GenerateAccessToken() (string, error) {
return base64.RawURLEncoding.EncodeToString(b), nil 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. // 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 // cf https://github.com/matrix-org/synapse/blob/v0.19.2/synapse/api/auth.py#L631
authBearer := req.Header.Get("Authorization") authBearer := req.Header.Get("Authorization")
queryToken := req.URL.Query().Get("access_token") queryToken := req.URL.Query().Get("access_token")

View File

@ -374,7 +374,13 @@ func validateApplicationService(
) (string, *util.JSONResponse) { ) (string, *util.JSONResponse) {
// Check if the token if the application service is valid with one we have // Check if the token if the application service is valid with one we have
// registered in the config. // 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 var matchedApplicationService *config.ApplicationService
for _, appservice := range cfg.Derived.ApplicationServices { for _, appservice := range cfg.Derived.ApplicationServices {
if appservice.ASToken == accessToken { if appservice.ASToken == accessToken {
@ -419,22 +425,6 @@ func validateApplicationService(
return matchedApplicationService.ID, nil 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. // Register processes a /register request.
// http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register // http://matrix.org/speculator/spec/HEAD/client_server/unstable.html#post-matrix-client-unstable-register
func Register( func Register(
@ -474,16 +464,6 @@ func Register(
r.Username = strconv.FormatInt(id, 10) 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 // Squash username to all lowercase letters
r.Username = strings.ToLower(r.Username) r.Username = strings.ToLower(r.Username)
@ -562,7 +542,8 @@ func handleRegistrationFlow(
// Add SharedSecret to the list of completed registration stages // Add SharedSecret to the list of completed registration stages
sessions.AddCompletedStage(sessionID, authtypes.LoginTypeSharedSecret) 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. // Check application service register user request is valid.
// The application service's ID is returned if so. // The application service's ID is returned if so.
appserviceID, err := validateApplicationService(cfg, req, r.Username) appserviceID, err := validateApplicationService(cfg, req, r.Username)