diff --git a/check_migrations.py b/check_migrations.py
index 70f5d25796ddcf7ea4484f11b9c69469b84dcfc0..643f30fbf1eb413dcd86deb8add7da1148f0984b 100755
--- a/check_migrations.py
+++ b/check_migrations.py
@@ -27,7 +27,22 @@ def run_test(dburi, revision):
 		'SELF_SIGNUP': True,
 		'ENABLE_INVITE': True,
 		'ENABLE_PASSWORDRESET': True,
-		'LDAP_SERVICE_MOCK': True
+		'LDAP_SERVICE_MOCK': True,
+		'OAUTH2_CLIENTS': {
+				'test': {
+					'service_name': 'test',
+					'client_secret': 'testsecret',
+					'redirect_uris': ['http://localhost:5004/oauthproxy/callback'],
+					'logout_urls': ['http://localhost:5004/oauthproxy/logout']
+				}
+		},
+		'API_CLIENTS_2': {
+			'test': {
+				'service_name': 'test',
+				'client_secret': 'testsecret',
+				'scopes': ['checkpassword', 'getusers', 'getmails']
+			},
+		},
 	}
 	app = create_app(config)
 	with app.test_request_context():
diff --git a/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py b/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py
index 7a4011280a707cb9afdf9c35404d26e5f58e8172..8933610d6ea6032407268bbe304c14d12b926cbb 100644
--- a/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py
+++ b/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py
@@ -14,6 +14,16 @@ branch_labels = None
 depends_on = None
 
 def upgrade():
+	# Retrospective fix of this migration: Originally server_default was not set,
+	# which caused "Cannot add a NOT NULL column with default value NULL" errors.
+	# This only happens with recent Alembic versions that render
+	# batch_op.add_column as an "ALTER TABLE" statement instead of recreating the
+	# table. To keep the resulting database consistent, we remove the
+	# server_default afterwards.
+	with op.batch_alter_table('api_client') as batch_op:
+		batch_op.add_column(sa.Column('perm_remailer', sa.Boolean(), nullable=False, server_default=sa.false()))
+	with op.batch_alter_table('service') as batch_op:
+		batch_op.add_column(sa.Column('use_remailer', sa.Boolean(), nullable=False, server_default=sa.false()))
 	meta = sa.MetaData(bind=op.get_bind())
 	api_client = sa.Table('api_client', meta,
     sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
@@ -23,6 +33,7 @@ def upgrade():
     sa.Column('perm_users', sa.Boolean(), nullable=False),
     sa.Column('perm_checkpassword', sa.Boolean(), nullable=False),
     sa.Column('perm_mail_aliases', sa.Boolean(), nullable=False),
+    sa.Column('perm_remailer', sa.Boolean(), nullable=False, server_default=sa.false()),
     sa.ForeignKeyConstraint(['service_id'], ['service.id'], name=op.f('fk_api_client_service_id_service'), onupdate='CASCADE', ondelete='CASCADE'),
     sa.PrimaryKeyConstraint('id', name=op.f('pk_api_client')),
     sa.UniqueConstraint('auth_username', name=op.f('uq_api_client_auth_username'))
@@ -32,14 +43,15 @@ def upgrade():
     sa.Column('name', sa.String(length=255), nullable=False),
     sa.Column('limit_access', sa.Boolean(), nullable=False),
     sa.Column('access_group_id', sa.Integer(), nullable=True),
+    sa.Column('use_remailer', sa.Boolean(), nullable=False, server_default=sa.false()),
     sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'),
     sa.PrimaryKeyConstraint('id', name=op.f('pk_service')),
     sa.UniqueConstraint('name', name=op.f('uq_service_name'))
 	)
 	with op.batch_alter_table('api_client', copy_from=api_client) as batch_op:
-		batch_op.add_column(sa.Column('perm_remailer', sa.Boolean(), nullable=False, default=False))
+		batch_op.alter_column('perm_remailer', server_default=None)
 	with op.batch_alter_table('service', copy_from=service) as batch_op:
-		batch_op.add_column(sa.Column('use_remailer', sa.Boolean(), nullable=False, default=False))
+		batch_op.alter_column('use_remailer', server_default=None)
 
 def downgrade():
 	meta = sa.MetaData(bind=op.get_bind())
diff --git a/uffd/migrations/versions/a60ce68b9214_fix_not_null_on_role_groups_group_id.py b/uffd/migrations/versions/a60ce68b9214_fix_not_null_on_role_groups_group_id.py
new file mode 100644
index 0000000000000000000000000000000000000000..3f97f8c113a8ca7f8d586a7f6f9562e3df9dcf1f
--- /dev/null
+++ b/uffd/migrations/versions/a60ce68b9214_fix_not_null_on_role_groups_group_id.py
@@ -0,0 +1,44 @@
+"""Fix NOT NULL on role_groups.group_id
+
+Revision 878b25c4fae7 wrongly left the column without a NOT NULL constraint.
+The missing constraint is only detected by newer Alembic versions.
+
+Revision ID: a60ce68b9214
+Revises: 704d1245331c
+Create Date: 2022-08-14 02:54:56.609390
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = 'a60ce68b9214'
+down_revision = '704d1245331c'
+branch_labels = None
+depends_on = None
+
+def upgrade():
+	meta = sa.MetaData(bind=op.get_bind())
+	role_groups = sa.Table('role_groups', meta,
+		sa.Column('role_id', sa.Integer(), nullable=False),
+		sa.Column('group_id', sa.Integer(), nullable=True),
+		sa.Column('requires_mfa', sa.Boolean(), nullable=False),
+		sa.ForeignKeyConstraint(['group_id'], ['group.id'], name=op.f('fk_role_groups_group_id_group'), onupdate='CASCADE', ondelete='CASCADE'),
+		sa.ForeignKeyConstraint(['role_id'], ['role.id'], name=op.f('fk_role_groups_role_id_role'), onupdate='CASCADE', ondelete='CASCADE'),
+		sa.PrimaryKeyConstraint('role_id', 'group_id', name=op.f('pk_role_groups'))
+	)
+	with op.batch_alter_table('role_groups', copy_from=role_groups) as batch_op:
+		batch_op.alter_column('group_id', existing_type=sa.INTEGER(), nullable=False)
+
+def downgrade():
+	meta = sa.MetaData(bind=op.get_bind())
+	role_groups = sa.Table('role_groups', meta,
+		sa.Column('role_id', sa.Integer(), nullable=False),
+		sa.Column('group_id', sa.Integer(), nullable=False),
+		sa.Column('requires_mfa', sa.Boolean(), nullable=False),
+		sa.ForeignKeyConstraint(['group_id'], ['group.id'], name=op.f('fk_role_groups_group_id_group'), onupdate='CASCADE', ondelete='CASCADE'),
+		sa.ForeignKeyConstraint(['role_id'], ['role.id'], name=op.f('fk_role_groups_role_id_role'), onupdate='CASCADE', ondelete='CASCADE'),
+		sa.PrimaryKeyConstraint('role_id', 'group_id', name=op.f('pk_role_groups'))
+	)
+	with op.batch_alter_table('role_groups', copy_from=role_groups) as batch_op:
+		batch_op.alter_column('group_id', existing_type=sa.INTEGER(), nullable=True)