diff --git a/homeassistant/components/auth/__init__.py b/homeassistant/components/auth/__init__.py
index 5839b7ec403e7ecc8e9f8091e6a9c54901178398..5fac423f27a2cd5d276f4138514557d603ac7252 100644
--- a/homeassistant/components/auth/__init__.py
+++ b/homeassistant/components/auth/__init__.py
@@ -156,6 +156,19 @@ SCHEMA_WS_LONG_LIVED_ACCESS_TOKEN = \
         vol.Optional('client_icon'): str,
     })
 
+WS_TYPE_REFRESH_TOKENS = 'auth/refresh_tokens'
+SCHEMA_WS_REFRESH_TOKENS = \
+    websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
+        vol.Required('type'): WS_TYPE_REFRESH_TOKENS,
+    })
+
+WS_TYPE_DELETE_REFRESH_TOKEN = 'auth/delete_refresh_token'
+SCHEMA_WS_DELETE_REFRESH_TOKEN = \
+    websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
+        vol.Required('type'): WS_TYPE_DELETE_REFRESH_TOKEN,
+        vol.Required('refresh_token_id'): str,
+    })
+
 RESULT_TYPE_CREDENTIALS = 'credentials'
 RESULT_TYPE_USER = 'user'
 
@@ -178,6 +191,16 @@ async def async_setup(hass, config):
         websocket_create_long_lived_access_token,
         SCHEMA_WS_LONG_LIVED_ACCESS_TOKEN
     )
+    hass.components.websocket_api.async_register_command(
+        WS_TYPE_REFRESH_TOKENS,
+        websocket_refresh_tokens,
+        SCHEMA_WS_REFRESH_TOKENS
+    )
+    hass.components.websocket_api.async_register_command(
+        WS_TYPE_DELETE_REFRESH_TOKEN,
+        websocket_delete_refresh_token,
+        SCHEMA_WS_DELETE_REFRESH_TOKEN
+    )
 
     await login_flow.async_setup(hass, store_result)
     await mfa_setup_flow.async_setup(hass)
@@ -445,3 +468,40 @@ def websocket_create_long_lived_access_token(
 
     hass.async_create_task(
         async_create_long_lived_access_token(connection.user))
+
+
+@websocket_api.ws_require_user()
+@callback
+def websocket_refresh_tokens(
+        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
+    """Return metadata of users refresh tokens."""
+    connection.to_write.put_nowait(websocket_api.result_message(msg['id'], [{
+        'id': refresh.id,
+        'client_id': refresh.client_id,
+        'client_name': refresh.client_name,
+        'client_icon': refresh.client_icon,
+        'type': refresh.token_type,
+        'created_at': refresh.created_at,
+    } for refresh in connection.user.refresh_tokens.values()]))
+
+
+@websocket_api.ws_require_user()
+@callback
+def websocket_delete_refresh_token(
+        hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg):
+    """Handle a delete refresh token request."""
+    async def async_delete_refresh_token(user, refresh_token_id):
+        """Delete a refresh token."""
+        refresh_token = connection.user.refresh_tokens.get(refresh_token_id)
+
+        if refresh_token is None:
+            return websocket_api.error_message(
+                msg['id'], 'invalid_token_id', 'Received invalid token')
+
+        await hass.auth.async_remove_refresh_token(refresh_token)
+
+        connection.send_message_outside(
+            websocket_api.result_message(msg['id'], {}))
+
+    hass.async_create_task(
+        async_delete_refresh_token(connection.user, msg['refresh_token_id']))
diff --git a/tests/components/auth/test_init.py b/tests/components/auth/test_init.py
index e0fe00bd9d8b918997d0d8c9ba23ad5ed2fdd332..a8e95c73a36fa2f441981ab04898b14fd0d7ecfa 100644
--- a/tests/components/auth/test_init.py
+++ b/tests/components/auth/test_init.py
@@ -2,18 +2,15 @@
 from datetime import timedelta
 from unittest.mock import patch
 
-from homeassistant import const
-from homeassistant.auth import auth_manager_from_config
 from homeassistant.auth.models import Credentials
 from homeassistant.components.auth import RESULT_TYPE_USER
 from homeassistant.setup import async_setup_component
 from homeassistant.util.dt import utcnow
 from homeassistant.components import auth
 
-from . import async_setup_auth
+from tests.common import CLIENT_ID, CLIENT_REDIRECT_URI, MockUser
 
-from tests.common import CLIENT_ID, CLIENT_REDIRECT_URI, MockUser, \
-    ensure_auth_manager_loaded
+from . import async_setup_auth
 
 
 async def test_login_new_user_and_trying_refresh_token(hass, aiohttp_client):
@@ -272,28 +269,12 @@ async def test_revoking_refresh_token(hass, aiohttp_client):
     assert resp.status == 400
 
 
-async def test_ws_long_lived_access_token(hass, hass_ws_client):
+async def test_ws_long_lived_access_token(hass, hass_ws_client,
+                                          hass_access_token):
     """Test generate long-lived access token."""
-    hass.auth = await auth_manager_from_config(
-        hass, provider_configs=[{
-            'type': 'insecure_example',
-            'users': [{
-                'username': 'test-user',
-                'password': 'test-pass',
-                'name': 'Test Name',
-            }]
-        }], module_configs=[])
-    ensure_auth_manager_loaded(hass.auth)
     assert await async_setup_component(hass, 'auth', {'http': {}})
-    assert await async_setup_component(hass, 'api', {'http': {}})
 
-    user = MockUser(id='mock-user').add_to_hass(hass)
-    cred = await hass.auth.auth_providers[0].async_get_or_create_credentials(
-        {'username': 'test-user'})
-    await hass.auth.async_link_user(user, cred)
-
-    ws_client = await hass_ws_client(hass, hass.auth.async_create_access_token(
-        await hass.auth.async_create_refresh_token(user, CLIENT_ID)))
+    ws_client = await hass_ws_client(hass, hass_access_token)
 
     # verify create long-lived access token
     await ws_client.send_json({
@@ -315,12 +296,51 @@ async def test_ws_long_lived_access_token(hass, hass_ws_client):
     assert refresh_token.client_name == 'GPS Logger'
     assert refresh_token.client_icon is None
 
-    # verify long-lived access token can be used as bearer token
-    api_client = ws_client.client
-    resp = await api_client.get(const.URL_API)
-    assert resp.status == 401
 
-    resp = await api_client.get(const.URL_API, headers={
-        'Authorization': 'Bearer {}'.format(long_lived_access_token)
+async def test_ws_refresh_tokens(hass, hass_ws_client, hass_access_token):
+    """Test fetching refresh token metadata."""
+    assert await async_setup_component(hass, 'auth', {'http': {}})
+
+    ws_client = await hass_ws_client(hass, hass_access_token)
+
+    await ws_client.send_json({
+        'id': 5,
+        'type': auth.WS_TYPE_REFRESH_TOKENS,
     })
-    assert resp.status == 200
+
+    result = await ws_client.receive_json()
+    assert result['success'], result
+    assert len(result['result']) == 1
+    token = result['result'][0]
+    refresh_token = await hass.auth.async_validate_access_token(
+        hass_access_token)
+    assert token['id'] == refresh_token.id
+    assert token['type'] == refresh_token.token_type
+    assert token['client_id'] == refresh_token.client_id
+    assert token['client_name'] == refresh_token.client_name
+    assert token['client_icon'] == refresh_token.client_icon
+    assert token['created_at'] == refresh_token.created_at.isoformat()
+
+
+async def test_ws_delete_refresh_token(hass, hass_ws_client,
+                                       hass_access_token):
+    """Test deleting a refresh token."""
+    assert await async_setup_component(hass, 'auth', {'http': {}})
+
+    refresh_token = await hass.auth.async_validate_access_token(
+        hass_access_token)
+
+    ws_client = await hass_ws_client(hass, hass_access_token)
+
+    # verify create long-lived access token
+    await ws_client.send_json({
+        'id': 5,
+        'type': auth.WS_TYPE_DELETE_REFRESH_TOKEN,
+        'refresh_token_id': refresh_token.id
+    })
+
+    result = await ws_client.receive_json()
+    assert result['success'], result
+    refresh_token = await hass.auth.async_validate_access_token(
+        hass_access_token)
+    assert refresh_token is None
diff --git a/tests/components/conftest.py b/tests/components/conftest.py
index 7cec790c84712fd2c402e0b3b37e7840e21afaf7..232405a632c5eb3a576ddafdfc6cf1d3103fef50 100644
--- a/tests/components/conftest.py
+++ b/tests/components/conftest.py
@@ -1,4 +1,6 @@
 """Fixtures for component testing."""
+from unittest.mock import patch
+
 import pytest
 
 from homeassistant.setup import async_setup_component
@@ -16,23 +18,37 @@ def hass_ws_client(aiohttp_client):
         assert await async_setup_component(hass, 'websocket_api')
 
         client = await aiohttp_client(hass.http.app)
-        websocket = await client.ws_connect(wapi.URL)
-        auth_resp = await websocket.receive_json()
 
-        if auth_resp['type'] == wapi.TYPE_AUTH_OK:
-            assert access_token is None, \
-                'Access token given but no auth required'
-            return websocket
+        patching = None
+
+        if access_token is not None:
+            patching = patch('homeassistant.auth.AuthManager.active',
+                             return_value=True)
+            patching.start()
+
+        try:
+            websocket = await client.ws_connect(wapi.URL)
+            auth_resp = await websocket.receive_json()
+
+            if auth_resp['type'] == wapi.TYPE_AUTH_OK:
+                assert access_token is None, \
+                    'Access token given but no auth required'
+                return websocket
+
+            assert access_token is not None, \
+                'Access token required for fixture'
 
-        assert access_token is not None, 'Access token required for fixture'
+            await websocket.send_json({
+                'type': websocket_api.TYPE_AUTH,
+                'access_token': access_token
+            })
 
-        await websocket.send_json({
-            'type': websocket_api.TYPE_AUTH,
-            'access_token': access_token
-        })
+            auth_ok = await websocket.receive_json()
+            assert auth_ok['type'] == wapi.TYPE_AUTH_OK
 
-        auth_ok = await websocket.receive_json()
-        assert auth_ok['type'] == wapi.TYPE_AUTH_OK
+        finally:
+            if patching is not None:
+                patching.stop()
 
         # wrap in client
         websocket.client = client