diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 896dd3d4bd805f2eab4e5a1458308cf0e8eff12e..163d6460e76fce92b7650552e0113815d89303c2 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -61,6 +61,7 @@ Fixed
 * Invitations for existing short name did not work.
 * Invitations for persons without pre-defined e-mail address did not behave correctly
 * OIDC scope "phone" had no claims.
+* 2FA via messages or phone calls didn't work.
 * [Dev] Site reference on extensible models can no longer cause name clashes
   because of its related name.
 
diff --git a/aleksis/core/frontend/mixins/menus.js b/aleksis/core/frontend/mixins/menus.js
index 8afed7f424ebf1bd4b33b316dc311f14831161fc..375bd04994d46d0d53139150d361ae0487858c77 100644
--- a/aleksis/core/frontend/mixins/menus.js
+++ b/aleksis/core/frontend/mixins/menus.js
@@ -19,12 +19,19 @@ const menusMixin = {
       let permArray = [];
 
       for (const route of this.$router.getRoutes()) {
-        if (
-          route.meta &&
-          route.meta["permission"] &&
-          !(route.meta["permission"] in permArray)
-        ) {
-          permArray.push(route.meta["permission"]);
+        if (route.meta) {
+          if (
+            route.meta["permission"] &&
+            !(route.meta["permission"] in permArray)
+          ) {
+            permArray.push(route.meta["permission"]);
+          }
+          if (
+            route.meta["menuPermission"] &&
+            !(route.meta["menuPermission"] in permArray)
+          ) {
+            permArray.push(route.meta["menuPermission"]);
+          }
         }
       }
 
@@ -41,9 +48,12 @@ const menusMixin = {
           route.meta &&
           route.meta[menuKey] &&
           !route.parent &&
-          (route.meta.permission
+          (route.meta.menuPermission
+            ? this.checkPermission(route.meta.menuPermission)
+            : route.meta.permission
             ? this.checkPermission(route.meta.permission)
-            : true) &&
+            : true
+          ) &&
           (route.meta.validators
             ? this.checkValidators(route.meta.validators)
             : true)
@@ -67,9 +77,12 @@ const menusMixin = {
           route.parent &&
           route.parent.name &&
           route.parent.name in menu &&
-          (route.meta.permission
+          (route.meta.menuPermission
+            ? this.checkPermission(route.meta.menuPermission)
+            : route.meta.permission
             ? this.checkPermission(route.meta.permission)
-            : true) &&
+            : true
+          ) &&
           (route.meta.validators
             ? this.checkValidators(route.meta.validators)
             : true)
diff --git a/aleksis/core/frontend/routes.js b/aleksis/core/frontend/routes.js
index 9d4a03d40d224ab5de3e6d1f4d4ca27e3661b114..f165248e00cf9e802e7706a220f26e3c14e4b85e 100644
--- a/aleksis/core/frontend/routes.js
+++ b/aleksis/core/frontend/routes.js
@@ -37,6 +37,7 @@ const routes = [
       inMenu: true,
       icon: "mdi-account-plus-outline",
       titleKey: "accounts.signup.menu_title",
+      menuPermission: "core.signup_rule",
       validators: [notLoggedInValidator],
       invalidate: "leave",
     },
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index c8c81525bc32b3ff91c3301328c7002b04fc12ed..0cd27e97ac422b7da054fe4beddca57a239a4ff8 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -750,8 +750,8 @@ if _settings.get("2fa.sms.enabled", False):
     TWO_FACTOR_SMS_GATEWAY = "two_factor.gateways.twilio.gateway.Twilio"
 
 if _settings.get("twilio.sid", None):
-    TWILIO_SID = _settings.get("twilio.sid")
-    TWILIO_TOKEN = _settings.get("twilio.token")
+    TWILIO_ACCOUNT_SID = _settings.get("twilio.sid")
+    TWILIO_AUTH_TOKEN = _settings.get("twilio.token")
     TWILIO_CALLER_ID = _settings.get("twilio.callerid")
 
 CELERY_BROKER_URL = _settings.get("celery.broker", REDIS_URL)