Fix setup tool when binding to external auth

We now query the external auth provider for the external service's identifier before adding the linking row into the database. This fixes the case where the external service resolves a different identifier for the same username.

Fixes #1477
This commit is contained in:
Joseph Schorr 2016-05-23 15:08:51 -04:00
parent d6b73a41de
commit 60bbca2185
6 changed files with 151 additions and 62 deletions

View file

@ -9,7 +9,7 @@ from endpoints.api import (ApiResource, nickname, resource, internal_only, show_
require_fresh_login, request, validate_json_request, verify_not_prod)
from endpoints.common import common_login
from app import app, config_provider, superusers
from app import app, config_provider, superusers, OVERRIDE_CONFIG_DIRECTORY
from data import model
from data.database import configure
from auth.permissions import SuperUserPermission
@ -19,7 +19,7 @@ from util.config.configutil import add_enterprise_config_defaults
from util.config.database import sync_database_with_config
from util.config.validator import validate_service_for_config, CONFIG_FILENAMES
from data.runmigration import run_alembic_migration
from data.users import get_federated_service_name
from data.users import get_federated_service_name, get_users_handler
import features
@ -175,7 +175,10 @@ class SuperUserConfig(ApiResource):
},
'hostname': {
'type': 'string'
}
},
'password': {
'type': 'string'
},
},
},
}
@ -213,9 +216,22 @@ class SuperUserConfig(ApiResource):
# If the authentication system is not the database, link the superuser account to the
# the authentication system chosen.
if config_object.get('AUTHENTICATION_TYPE', 'Database') != 'Database':
service_name = get_federated_service_name(config_object['AUTHENTICATION_TYPE'])
current_user = get_authenticated_user()
model.user.confirm_attached_federated_login(current_user, service_name)
if current_user is None:
abort(401)
service_name = get_federated_service_name(config_object['AUTHENTICATION_TYPE'])
if not model.user.lookup_federated_login(current_user, service_name):
# Verify the user's credentials and retrieve the user's external username+email.
handler = get_users_handler(config_object, config_provider, OVERRIDE_CONFIG_DIRECTORY)
(result, err_msg) = handler.verify_credentials(current_user.username,
request.get_json().get('password', ''))
if not result:
logger.error('Could not save configuration due to external auth failure: %s', err_msg)
abort(400)
# Link the existing user to the external user.
model.user.attach_federated_login(current_user, service_name, result.username)
# Ensure database is up-to-date with config
sync_database_with_config(config_object)