diff --git a/hooks/horizon_contexts.py b/hooks/horizon_contexts.py
index bb99848cb84b57fe8f37e608f7a1fb10036d5964..6b74a835e7cf4cfdb140eaee00dc6becbb66e9d9 100644
--- a/hooks/horizon_contexts.py
+++ b/hooks/horizon_contexts.py
@@ -44,6 +44,7 @@ from charmhelpers.core.host import pwgen
 
 from base64 import b64decode
 import os
+import json
 
 VALID_ENDPOINT_TYPES = {
     'PUBLICURL': 'publicURL',
@@ -282,3 +283,30 @@ class LocalSettingsContext(OSContextGenerator):
                                     key=lambda r: r[1]['priority'])]
         }
         return ctxt
+
+
+class WebSSOFIDServiceProviderContext(OSContextGenerator):
+    interfaces = ['websso-fid-service-provider']
+
+    def __call__(self):
+        websso_keys = ['protocol-name', 'idp-name', 'user-facing-name']
+
+        relations = []
+        for rid in relation_ids("websso-fid-service-provider"):
+            try:
+                # the first unit will do - the assumption is that all
+                # of them should advertise the same data. This needs
+                # refactoring if juju gets per-application relation data
+                # support
+                unit = related_units(rid)[0]
+            except IndexError:
+                pass
+            else:
+                rdata = relation_get(unit=unit, rid=rid)
+                if set(rdata).issuperset(set(websso_keys)):
+                    relations.append({k: json.loads(rdata[k])
+                                      for k in websso_keys})
+        # populate the context with data from one or more
+        # service providers
+        ctxt = {'websso_data': relations} if relations else {}
+        return ctxt
diff --git a/hooks/horizon_hooks.py b/hooks/horizon_hooks.py
index 913d925a4d66e78a6de015849e2fc58ff89b507d..ba9978d7fdd87113169945488f23607bc124223e 100755
--- a/hooks/horizon_hooks.py
+++ b/hooks/horizon_hooks.py
@@ -31,6 +31,7 @@ from charmhelpers.core.hookenv import (
     is_leader,
     local_unit,
     WARNING,
+    network_get,
 )
 from charmhelpers.fetch import (
     apt_update, apt_install,
@@ -152,6 +153,8 @@ def config_changed():
     open_port(80)
     open_port(443)
 
+    websso_trusted_dashboard_changed()
+
 
 @hooks.hook('identity-service-relation-joined')
 def keystone_joined(rel_id=None):
@@ -342,6 +345,47 @@ def db_changed():
         log('Not running neutron database migration, not leader')
 
 
+@hooks.hook('websso-fid-service-provider-relation-joined',
+            'websso-fid-service-provider-relation-changed',
+            'websso-fid-service-provider-relation-departed')
+@restart_on_change(restart_map(), stopstart=True, sleep=3)
+def websso_sp_changed():
+    CONFIGS.write_all()
+
+
+@hooks.hook('websso-trusted-dashboard-relation-joined',
+            'websso-trusted-dashboard-relation-changed')
+def websso_trusted_dashboard_changed():
+    """
+    Provide L7 endpoint details for the dashboard and also
+    handle any config changes that may affect those.
+    """
+    relations = relation_ids('websso-trusted-dashboard')
+    if not relations:
+        return
+
+    # TODO: check for vault relation in order to determine url scheme
+    tls_configured = config('ssl-key') or config('enforce-ssl')
+    scheme = 'https://' if tls_configured else 'http://'
+
+    if config('dns-ha') or config('os-public-hostname'):
+        hostname = config('os-public-hostname')
+    elif config('vip'):
+        hostname = config('vip')
+    else:
+        # use an ingress-address of a given unit as a fallback
+        netinfo = network_get('websso-trusted-dashboard')
+        hostname = netinfo['ingress-addresses'][0]
+
+    # provide trusted dashboard URL details
+    for rid in relations:
+        relation_set(relation_id=rid, relation_settings={
+            "scheme": scheme,
+            "hostname": hostname,
+            "path": "/auth/websso/"
+        })
+
+
 def main():
     try:
         hooks.execute(sys.argv)
diff --git a/hooks/horizon_utils.py b/hooks/horizon_utils.py
index 0af36725e705ac34b9c7218c753f2dd10f4d8dbb..1c7c4722a4f4cef149eec5f1d43d41bf6acba083 100644
--- a/hooks/horizon_utils.py
+++ b/hooks/horizon_utils.py
@@ -93,7 +93,8 @@ CONFIG_FILES = OrderedDict([
                           horizon_contexts.IdentityServiceContext(),
                           context.SyslogContext(),
                           horizon_contexts.LocalSettingsContext(),
-                          horizon_contexts.ApacheSSLContext()],
+                          horizon_contexts.ApacheSSLContext(),
+                          horizon_contexts.WebSSOFIDServiceProviderContext()],
         'services': ['apache2', 'memcached']
     }),
     (APACHE_CONF, {
diff --git a/hooks/websso-fid-service-provider-relation-broken b/hooks/websso-fid-service-provider-relation-broken
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-fid-service-provider-relation-broken
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/hooks/websso-fid-service-provider-relation-changed b/hooks/websso-fid-service-provider-relation-changed
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-fid-service-provider-relation-changed
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/hooks/websso-fid-service-provider-relation-departed b/hooks/websso-fid-service-provider-relation-departed
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-fid-service-provider-relation-departed
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/hooks/websso-fid-service-provider-relation-joined b/hooks/websso-fid-service-provider-relation-joined
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-fid-service-provider-relation-joined
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/hooks/websso-trusted-dashboard-relation-broken b/hooks/websso-trusted-dashboard-relation-broken
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-trusted-dashboard-relation-broken
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/hooks/websso-trusted-dashboard-relation-changed b/hooks/websso-trusted-dashboard-relation-changed
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-trusted-dashboard-relation-changed
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/hooks/websso-trusted-dashboard-relation-departed b/hooks/websso-trusted-dashboard-relation-departed
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-trusted-dashboard-relation-departed
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/hooks/websso-trusted-dashboard-relation-joined b/hooks/websso-trusted-dashboard-relation-joined
new file mode 120000
index 0000000000000000000000000000000000000000..3195386e535c48512196bb8461cbf221c81f7383
--- /dev/null
+++ b/hooks/websso-trusted-dashboard-relation-joined
@@ -0,0 +1 @@
+horizon_hooks.py
\ No newline at end of file
diff --git a/metadata.yaml b/metadata.yaml
index 0502d80d3147fee3af15549a98125ff943d6a247..242aeb97881a80f7e19d0de25249b0cebe87740b 100644
--- a/metadata.yaml
+++ b/metadata.yaml
@@ -23,6 +23,8 @@ provides:
   dashboard-plugin:
     interface: dashboard-plugin
     scope: container
+  websso-trusted-dashboard:
+    interface: websso-trusted-dashboard
 requires:
   identity-service:
     interface: keystone
@@ -31,6 +33,8 @@ requires:
     scope: container
   shared-db:
     interface: mysql-shared
+  websso-fid-service-provider:
+    interface: websso-fid-service-provider
 peers:
   cluster:
     interface: openstack-dashboard-ha
diff --git a/templates/ocata/local_settings.py b/templates/ocata/local_settings.py
index fd6217ba4f6249d6c2d5cf63fc11be2b57349179..3d43c562a773068afac56130599ef8d216976b13 100644
--- a/templates/ocata/local_settings.py
+++ b/templates/ocata/local_settings.py
@@ -991,3 +991,19 @@ ALLOWED_PRIVATE_SUBNET_CIDR = {'ipv4': [], 'ipv6': []}
 #   'phone_num': _('Phone Number'),
 #}
 {{ settings|join('\n\n') }}
+
+{% if websso_data %}
+WEBSSO_ENABLED = True
+WEBSSO_CHOICES = (
+{% for provider_data in websso_data -%}
+    ("{{ '{}_{}'.format(provider_data['idp-name'], provider_data['protocol-name']) }}", "{{ provider_data['user-facing-name'] }}"),
+{% endfor -%}
+    ("credentials", _("Keystone Credentials"))
+)
+
+WEBSSO_IDP_MAPPING = {
+{% for provider_data in websso_data -%}
+    "{{ '{}_{}'.format(provider_data['idp-name'], provider_data['protocol-name']) }}": ("{{ provider_data['idp-name'] }}", "{{ provider_data['protocol-name'] }}"),
+{% endfor -%}
+}
+{% endif %}
diff --git a/unit_tests/test_horizon_contexts.py b/unit_tests/test_horizon_contexts.py
index 90c2d071d32b31d0df3e2d08fb384d8767bd348e..8f5cea728ab90f4f99173b7a963e3e58608c7f8b 100644
--- a/unit_tests/test_horizon_contexts.py
+++ b/unit_tests/test_horizon_contexts.py
@@ -650,3 +650,76 @@ class TestHorizonContexts(CharmTestCase):
                                        'BAR = False',
                                        '# horizon-plugin/0\n'
                                        'FOO = True']})
+
+    def test_WebSSOFIDServiceProviderContext(self):
+        def relation_ids_side_effect(rname):
+            return {
+                'websso-fid-service-provider': [
+                    'websso-fid-service-provider:0',
+                    'websso-fid-service-provider:1',
+                ]
+            }[rname]
+        self.relation_ids.side_effect = relation_ids_side_effect
+
+        def related_units_side_effect(rid):
+            return {
+                'websso-fid-service-provider:0': [
+                    'keystone-saml-mellon-red/0',
+                    'keystone-saml-mellon-red/1',
+                ],
+                'websso-fid-service-provider:1': [
+                    'keystone-saml-mellon-green/0',
+                    'keystone-saml-mellon-green/1',
+                ],
+            }[rid]
+        self.related_units.side_effect = related_units_side_effect
+
+        def relation_get_side_effect(unit, rid):
+            return {
+                'websso-fid-service-provider:0': {
+                    'keystone-saml-mellon-red/0': {
+                        'ingress-address': '10.0.0.10',
+                        'protocol-name': '"saml2"',
+                        'idp-name': '"red"',
+                        'user-facing-name': '"Red IDP"',
+                    },
+                    'keystone-saml-mellon-red/1': {
+                        'ingress-address': '10.0.0.11',
+                        'protocol-name': '"saml2"',
+                        'idp-name': '"red"',
+                        'user-facing-name': '"Red IDP"',
+                    },
+                },
+                'websso-fid-service-provider:1': {
+                    'keystone-saml-mellon-green/0': {
+                        'ingress-address': '10.0.0.12',
+                        'protocol-name': '"mapped"',
+                        'idp-name': '"green"',
+                        'user-facing-name': '"Green IDP"',
+                    },
+                    'keystone-saml-mellon-green/1': {
+                        'ingress-address': '10.0.0.13',
+                        'protocol-name': '"mapped"',
+                        'idp-name': '"green"',
+                        'user-facing-name': '"Green IDP"',
+                    },
+                },
+            }[rid][unit]
+        self.relation_get.side_effect = relation_get_side_effect
+
+        self.assertEqual(
+            horizon_contexts.WebSSOFIDServiceProviderContext()(),
+            {
+                'websso_data': [
+                    {
+                        'protocol-name': 'saml2',
+                        'idp-name': 'red',
+                        'user-facing-name': "Red IDP",
+                    },
+                    {
+                        'protocol-name': 'mapped',
+                        'idp-name': 'green',
+                        'user-facing-name': "Green IDP",
+                    },
+                ]
+            })
diff --git a/unit_tests/test_horizon_hooks.py b/unit_tests/test_horizon_hooks.py
index 60f5116bf27483d565274c3c6ce32096a9bb080f..4d0d3f0ef0f9be3c422045c72e3348e684f2e196 100644
--- a/unit_tests/test_horizon_hooks.py
+++ b/unit_tests/test_horizon_hooks.py
@@ -260,7 +260,30 @@ class TestHorizonHooks(CharmTestCase):
 
     @patch('horizon_hooks.keystone_joined')
     def test_config_changed_no_upgrade(self, _joined):
-        self.relation_ids.return_value = ['identity/0']
+        def relation_ids_side_effect(rname):
+            return {
+                'websso-trusted-dashboard': [
+                    'websso-trusted-dashboard:0',
+                    'websso-trusted-dashboard:1',
+                ],
+                'identity-service': [
+                    'identity/0',
+                ],
+            }[rname]
+        self.relation_ids.side_effect = relation_ids_side_effect
+
+        def config_side_effect(key):
+            return {
+                'ssl-key': 'somekey',
+                'enforce-ssl': True,
+                'dns-ha': True,
+                'os-public-hostname': 'dashboard.intranet.test',
+                'prefer-ipv6': False,
+                'action-managed-upgrade': False,
+                'webroot': '/horizon',
+            }[key]
+        self.config.side_effect = config_side_effect
+
         self.openstack_upgrade_available.return_value = False
         self._call_hook('config-changed')
         _joined.assert_called_with('identity/0')
@@ -331,3 +354,41 @@ class TestHorizonHooks(CharmTestCase):
             openstack_dir='/usr/share/openstack-dashboard',
             relation_id=None
         )
+
+    def test_websso_fid_service_provider_changed(self):
+        self._call_hook('websso-fid-service-provider-relation-changed')
+        self.CONFIGS.write_all.assert_called_with()
+
+    def test_websso_trusted_dashboard_changed(self):
+        def relation_ids_side_effect(rname):
+            return {
+                'websso-trusted-dashboard': [
+                    'websso-trusted-dashboard:0',
+                    'websso-trusted-dashboard:1',
+                ]
+            }[rname]
+        self.relation_ids.side_effect = relation_ids_side_effect
+
+        def config_side_effect(key):
+            return {
+                'ssl-key': 'somekey',
+                'enforce-ssl': True,
+                'dns-ha': True,
+                'os-public-hostname': 'dashboard.intranet.test',
+            }[key]
+        self.config.side_effect = config_side_effect
+        self._call_hook('websso-trusted-dashboard-relation-changed')
+        self.relation_set.assert_has_calls([
+            call(relation_id='websso-trusted-dashboard:0',
+                 relation_settings={
+                     "scheme": "https://",
+                     "hostname": "dashboard.intranet.test",
+                     "path": "/auth/websso/",
+                 }),
+            call(relation_id='websso-trusted-dashboard:1',
+                 relation_settings={
+                     "scheme": "https://",
+                     "hostname": "dashboard.intranet.test",
+                     "path": "/auth/websso/",
+                 }),
+        ])