diff --git a/docs/auth.md b/docs/auth.md index c89385a5819..b2d5c9535a8 100644 --- a/docs/auth.md +++ b/docs/auth.md @@ -228,6 +228,20 @@ Then, the client can retry by sending the two-factor token and code: } ``` +**Note:** if the two-factor authentication is enabled, and the cloudery has +already verified the email address, a parameter `email_verified_code` can be sent +to skip another 2FA code sent by mail. + + +```json +{ + "passphrase": "4f58133ea0f415424d0a856e0d3d2e0cd28e4358fce7e333cb524729796b2791", + "client_id": "64ce5cb0-bd4c-11e6-880e-b3b7dfda89d3", + "client_secret": "eyJpc3Mi[...omitted for brevity...]", + "email_verified_code": "987456321" +} +``` + **Note:** if the OAuth client has not been certified as the flagship app, this request will return: diff --git a/model/instance/auth.go b/model/instance/auth.go index 85d7a524537..28c9e2e3e30 100644 --- a/model/instance/auth.go +++ b/model/instance/auth.go @@ -219,5 +219,8 @@ func (i *Instance) CreateEmailVerifiedCode() (string, error) { // CheckEmailVerifiedCode will return true if the email verified code is valid. func (i *Instance) CheckEmailVerifiedCode(code string) bool { + if code == "" { + return false + } return GetStore().CheckEmailVerifiedCode(i, code) } diff --git a/web/auth/flagship.go b/web/auth/flagship.go index 342aae9b5d4..3ad0f5fada1 100644 --- a/web/auth/flagship.go +++ b/web/auth/flagship.go @@ -181,6 +181,7 @@ type loginFlagshipParameters struct { Passphrase string `json:"passphrase"` TwoFactorPasscode string `json:"two_factor_passcode"` TwoFactorToken string `json:"two_factor_token"` + EmailVerifiedCode string `json:"email_verified_code"` } func loginFlagship(c echo.Context) error { @@ -203,7 +204,7 @@ func loginFlagship(c echo.Context) error { }) } - if inst.HasAuthMode(instance.TwoFactorMail) { + if inst.HasAuthMode(instance.TwoFactorMail) && !inst.CheckEmailVerifiedCode(args.EmailVerifiedCode) { if len(args.TwoFactorToken) == 0 { twoFactorToken, err := lifecycle.SendTwoFactorPasscode(inst) if err != nil {