diff --git a/etc/refstack.conf.sample b/etc/refstack.conf.sample
index af65d549..bb349fe3 100644
--- a/etc/refstack.conf.sample
+++ b/etc/refstack.conf.sample
@@ -271,6 +271,9 @@
 # OpenStackID Auth Server URI. (string value)
 #openstack_openid_endpoint = https://openstackid.org/accounts/openid2
 
+# OpenStackID logout URI. (string value)
+#openid_logout_endpoint = https://openstackid.org/accounts/user/logout
+
 # Interaction mode. Specifies whether Openstack Id IdP may interact
 # with the user to determine the outcome of the request. (string
 # value)
diff --git a/refstack-ui/app/app.js b/refstack-ui/app/app.js
index 359825cc..be1e3228 100644
--- a/refstack-ui/app/app.js
+++ b/refstack-ui/app/app.js
@@ -73,6 +73,11 @@
                 url: '/auth_failure/:message',
                 templateUrl: '/components/home/home.html',
                 controller: 'AuthFailureController as ctrl'
+            }).
+            state('logout', {
+                url: '/logout',
+                templateUrl: '/components/logout/logout.html',
+                controller: 'LogoutController as ctrl'
             });
     }
 
@@ -108,10 +113,6 @@
      */
     function setup($http, $rootScope, $window, $state, refstackApiUrl) {
 
-        /**
-         * This function injects sign in function in all scopes
-         */
-
         $rootScope.auth = {};
         $rootScope.auth.doSignIn = doSignIn;
         $rootScope.auth.doSignOut = doSignOut;
diff --git a/refstack-ui/app/components/logout/logout.html b/refstack-ui/app/components/logout/logout.html
new file mode 100644
index 00000000..38a5c369
--- /dev/null
+++ b/refstack-ui/app/components/logout/logout.html
@@ -0,0 +1 @@
+<div cg-busy="{promise:ctrl.redirectWait,message:'Logging you out...'}"></div>
diff --git a/refstack-ui/app/components/logout/logoutController.js b/refstack-ui/app/components/logout/logoutController.js
new file mode 100644
index 00000000..86acb4af
--- /dev/null
+++ b/refstack-ui/app/components/logout/logoutController.js
@@ -0,0 +1,44 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function () {
+    'use strict';
+
+    angular
+        .module('refstackApp')
+        .controller('LogoutController', LogoutController);
+
+    LogoutController.$inject = [
+        '$location', '$window', '$timeout'
+    ];
+
+    /**
+     * Refstack Logout Controller
+     * This controller handles logging out. In order to fully logout, the
+     * openstackid_session cookie must also be removed. The way to do that
+     * is to have the user's browser make a request to the openstackid logout
+     * page. We do this by placing the logout link as the src for an html
+     * image. After some time, the user is redirected home.
+     */
+    function LogoutController($location, $window, $timeout) {
+        var ctrl = this;
+
+        ctrl.openid_logout_url = $location.search().openid_logout;
+        var img = new Image(0, 0);
+        img.src = ctrl.openid_logout_url;
+        ctrl.redirectWait = $timeout(function() {
+            $window.location.href = '/';
+        }, 500);
+    }
+})();
diff --git a/refstack-ui/app/index.html b/refstack-ui/app/index.html
index 80a75058..dacb5f8b 100644
--- a/refstack-ui/app/index.html
+++ b/refstack-ui/app/index.html
@@ -45,6 +45,7 @@
         <script src="components/results-report/resultsReportController.js"></script>
         <script src="components/profile/profileController.js"></script>
         <script src="components/auth-failure/authFailureController.js"></script>
+        <script src="components/logout/logoutController.js"></script>
 
         <!-- Filters -->
         <script src="shared/filters.js"></script>
diff --git a/refstack-ui/tests/unit/ControllerSpec.js b/refstack-ui/tests/unit/ControllerSpec.js
index 784dddf6..ae67fd19 100644
--- a/refstack-ui/tests/unit/ControllerSpec.js
+++ b/refstack-ui/tests/unit/ControllerSpec.js
@@ -42,6 +42,22 @@ describe('Refstack controllers', function () {
             });
     });
 
+    describe('LogoutController', function () {
+        var $location, ctrl;
+
+        beforeEach(inject(function ($controller, _$location_) {
+            $location = _$location_;
+            $location.url('/logout?openid_logout=some_url');
+            ctrl = $controller('LogoutController', {});
+        }));
+
+        it('should set the openID logout URL based on query string',
+            function () {
+                expect($location.url()).toBe('/logout?openid_logout=some_url');
+                expect(ctrl.openid_logout_url).toBe('some_url');
+            });
+    });
+
     describe('CapabilitiesController', function () {
         var ctrl;
 
diff --git a/refstack/api/controllers/auth.py b/refstack/api/controllers/auth.py
index 1d8373e9..9e388dad 100644
--- a/refstack/api/controllers/auth.py
+++ b/refstack/api/controllers/auth.py
@@ -33,6 +33,10 @@ OPENID_OPTS = [
                default='https://openstackid.org/accounts/openid2',
                help='OpenStackID Auth Server URI.'
                ),
+    cfg.StrOpt('openid_logout_endpoint',
+               default='https://openstackid.org/accounts/user/logout',
+               help='OpenStackID logout URI.'
+               ),
     cfg.StrOpt('openid_mode',
                default='checkid_setup',
                help='Interaction mode. Specifies whether Openstack Id '
@@ -167,9 +171,15 @@ class AuthController(rest.RestController):
 
         pecan.redirect(CONF.ui_url)
 
-    @pecan.expose()
+    @pecan.expose('json')
     def signout(self):
         """Handle signout request."""
         if api_utils.is_authenticated():
             api_utils.delete_params_from_user_session([const.USER_OPENID])
-        pecan.redirect(CONF.ui_url)
+
+        params = {
+            'openid_logout': CONF.osid.openid_logout_endpoint
+        }
+        url = parse.urljoin(CONF.ui_url,
+                            '/#/logout?' + parse.urlencode(params))
+        pecan.redirect(url)
diff --git a/refstack/tests/unit/test_api.py b/refstack/tests/unit/test_api.py
index 0239ac97..10edf7cb 100644
--- a/refstack/tests/unit/test_api.py
+++ b/refstack/tests/unit/test_api.py
@@ -413,6 +413,8 @@ class AuthControllerTestCase(BaseControllerTestCase):
         self.CONF = self.useFixture(self.config_fixture).conf
         self.CONF.set_override('app_dev_mode', True, 'api')
         self.CONF.set_override('ui_url', 'http://127.0.0.1')
+        self.CONF.set_override('openid_logout_endpoint', 'http://some-url',
+                               'osid')
 
     @mock.patch('refstack.api.utils.get_user_session')
     @mock.patch('pecan.redirect', side_effect=webob.exc.HTTPRedirection)
@@ -527,7 +529,8 @@ class AuthControllerTestCase(BaseControllerTestCase):
             const.CSRF_TOKEN: 42
         }
         self.assertRaises(webob.exc.HTTPRedirection, self.controller.signout)
-        mock_redirect.assert_called_with('http://127.0.0.1')
+        mock_redirect.assert_called_with('http://127.0.0.1/#/logout?'
+                                         'openid_logout=http%3A%2F%2Fsome-url')
         self.assertNotIn(const.CSRF_TOKEN,
                          mock_request.environ['beaker.session'])