From 48c4a5b477dbdc556b42e7bbe9889ab203e7e3d6 Mon Sep 17 00:00:00 2001 From: Ryan Kelly Date: Tue, 3 Apr 2018 10:33:35 +1000 Subject: [PATCH] Add an easy way to configure the identity provider. Setting the SYNCSERVER_IDENTITY_PROVIDER environment variable will cause syncserver to restrict both BrowserID and OAuth credentials to be issued from that server. --- syncserver.ini | 20 +++++++------------- syncserver/__init__.py | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/syncserver.ini b/syncserver.ini index 056fa2f..02e5826 100644 --- a/syncserver.ini +++ b/syncserver.ini @@ -13,6 +13,12 @@ use = egg:syncserver # i.e. the URL as seen by Firefox. public_url = http://localhost:5000/ +# By default, syncserver will accept identity assertions issued by +# any BrowserID issuer. The below restricts it to accept assertions +# from just the production Firefox Account servers. If you are hosting +# your own account server, put its public URL here instead. +identity_provider = https://accounts.firefox.com/ + # This defines the database in which to store all server data. #sqluri = sqlite:////tmp/syncserver.db @@ -26,7 +32,7 @@ public_url = http://localhost:5000/ #secret = INSERT_SECRET_KEY_HERE # Set this to "false" to disable new-user signups on the server. -# Only request by existing accounts will be honoured. +# Only requests by existing accounts will be honoured. # allow_new_users = false # Set this to "true" to work around a mismatch between public_url and @@ -36,15 +42,3 @@ public_url = http://localhost:5000/ # you tell the app that it's on HTTPS but it's really on HTTP, so it should # only be used as a last resort and after careful checking of server config. force_wsgi_environ = false - -[browserid] -# Uncomment and edit the following to use a local BrowserID verifier -# rather than posting assertions to the mozilla-hosted verifier. -# Audiences should be set to your public_url without a trailing slash. -#backend = tokenserver.verifiers.LocalVerifier -#audiences = https://localhost:5000 - -# By default, syncserver will accept identity assertions issues by -# any server. You can restrict this by setting the below to a list -# of allowed issuer domains. -#allowed_issuers = www.mysite.com myfriendsdomain.org diff --git a/syncserver/__init__.py b/syncserver/__init__.py index 5370064..108ac4b 100644 --- a/syncserver/__init__.py +++ b/syncserver/__init__.py @@ -4,7 +4,9 @@ import os import logging -from urlparse import urlparse, urlunparse +from urlparse import urlparse, urlunparse, urljoin + +import requests from pyramid.response import Response from pyramid.events import NewRequest, subscriber @@ -54,6 +56,13 @@ def includeme(config): rootdir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) sqluri = "sqlite:///" + os.path.join(rootdir, "syncserver.db") + # Automagically configure from IdP if one is given. + idp = settings.get("syncserver.identity_provider") + if idp is not None: + r = requests.get(urljoin(idp, '/.well-known/fxa-client-configuration')) + r.raise_for_status() + idp_config = r.json() + # Configure app-specific defaults based on top-level configuration. settings.pop("config", None) if "tokenserver.backend" not in settings: @@ -98,10 +107,15 @@ def includeme(config): settings["storage.batch_upload_enabled"] = False if "browserid.backend" not in settings: # Default to local verifier to reduce external dependencies. + settings["browserid.backend"] = "tokenserver.verifiers.LocalVerifier" # Use base of public_url as only audience audience = urlunparse(urlparse(public_url)._replace(path="")) - settings["browserid.backend"] = "tokenserver.verifiers.LocalVerifier" settings["browserid.audiences"] = audience + # If an IdP was specified, allow it and only it as issuer. + if idp is not None: + issuer = urlparse(idp_config["auth_server_base_url"]).netloc + settings["browserid.trusted_issuers"] = [issuer] + settings["browserid.allowed_issuers"] = [issuer] if "loggers" not in settings: # Default to basic logging config. root_logger = logging.getLogger("") @@ -140,6 +154,7 @@ def import_settings_from_environment_variables(settings, environ=None): ("SYNCSERVER_PUBLIC_URL", "syncserver.public_url", str), ("SYNCSERVER_SECRET", "syncserver.secret", str), ("SYNCSERVER_SQLURI", "syncserver.sqluri", str), + ("SYNCSERVER_IDENTITY_PROVIDER", "syncserver.identity_provider", str), ("SYNCSERVER_ALLOW_NEW_USERS", "syncserver.allow_new_users", str_to_bool),