diff --git a/clientapi/auth/authtypes/stages.go b/clientapi/auth/authtypes/stages.go new file mode 100644 index 000000000..49024504c --- /dev/null +++ b/clientapi/auth/authtypes/stages.go @@ -0,0 +1,19 @@ +// Copyright 2021 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package authtypes + +const ( + LoginStagePublicKeyNewSession = "m.login.publickey.newsession" +) diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go index 455bbf8cb..55bb0df87 100644 --- a/clientapi/routing/register.go +++ b/clientapi/routing/register.go @@ -750,8 +750,8 @@ func handleRegistrationFlow( } } - switch r.Auth.Type { - case authtypes.LoginTypeRecaptcha: + switch true { + case r.Auth.Type == authtypes.LoginTypeRecaptcha: // Check given captcha response resErr := validateRecaptcha(cfg, r.Auth.Response, req.RemoteAddr) if resErr != nil { @@ -761,24 +761,20 @@ func handleRegistrationFlow( // Add Recaptcha to the list of completed registration stages sessions.addCompletedSessionStage(sessionID, authtypes.LoginTypeRecaptcha) - case authtypes.LoginTypeDummy: + case r.Auth.Type == authtypes.LoginTypeDummy && !cfg.PasswordAuthenticationDisabled: // there is nothing to do // Add Dummy to the list of completed registration stages sessions.addCompletedSessionStage(sessionID, authtypes.LoginTypeDummy) - case authtypes.LoginTypePublicKey: - isCompleted, authType, err := handlePublicKeyRegistration(cfg, reqBody, &r, userAPI) + case r.Auth.Type == authtypes.LoginTypePublicKey: + _, authType, err := handlePublicKeyRegistration(cfg, reqBody, &r, userAPI) if err != nil { return *err } - if isCompleted { - sessions.addCompletedSessionStage(sessionID, authType) - } else { - newPublicKeyAuthSession(&r, sessions, sessionID) - } + sessions.addCompletedSessionStage(sessionID, authType) - case "": + case r.Auth.Type == "": // An empty auth type means that we want to fetch the available // flows. It can also mean that we want to register as an appservice // but that is handed above. diff --git a/clientapi/routing/register_publickey.go b/clientapi/routing/register_publickey.go index 2ab2b6ca1..6132530d0 100644 --- a/clientapi/routing/register_publickey.go +++ b/clientapi/routing/register_publickey.go @@ -26,14 +26,6 @@ import ( "github.com/tidwall/gjson" ) -func newPublicKeyAuthSession(request *registerRequest, sessions *sessionsDict, sessionID string) { - sessions.sessions[sessionID] = append(sessions.sessions[sessionID], authtypes.LoginTypePublicKey) - // Public key auth does not use password. But the registration flow - // requires setting a password in order to create the account. - // Create a random password to satisfy the requirement. - request.Password = util.RandomString(sessionIDLength) -} - func handlePublicKeyRegistration( cfg *config.ClientAPI, reqBytes []byte, @@ -67,7 +59,7 @@ func handlePublicKeyRegistration( authHandler = pkEthHandler default: // No response. Client is asking for a new registration session - return false, "", nil + return false, authtypes.LoginStagePublicKeyNewSession, nil } if _, ok := sessions.sessions[authHandler.GetSession()]; !ok { @@ -85,7 +77,7 @@ func handlePublicKeyRegistration( } } - isCompleted, jerr := authHandler.ValidateLoginResponse() + isValidated, jerr := authHandler.ValidateLoginResponse() if jerr != nil { return false, "", &util.JSONResponse{ Code: http.StatusUnauthorized, @@ -93,5 +85,19 @@ func handlePublicKeyRegistration( } } - return isCompleted, authtypes.LoginType(authHandler.GetType()), nil + // Registration flow requires a password to + // create a user account. Create a random one + // to satisfy the requirement. This is not used + // for public key cryptography. + createPassword(r) + + return isValidated, authtypes.LoginType(authHandler.GetType()), nil +} + +func createPassword(request *registerRequest) { + // Public key auth does not use password. + // Create a random one that is never used. + // Login validation will be done using public / private + // key cryptography. + request.Password = util.RandomString(sessionIDLength) }