diff --git a/homeassistant/components/auth/__init__.py b/homeassistant/components/auth/__init__.py
index 8c0c17844f9d384269e71a7e7d0b5b2bcc9be04a..19edfe5a618a42151a48b2ba04cb2562da849c06 100644
--- a/homeassistant/components/auth/__init__.py
+++ b/homeassistant/components/auth/__init__.py
@@ -459,6 +459,7 @@ async def websocket_current_user(
             'id': user.id,
             'name': user.name,
             'is_owner': user.is_owner,
+            'is_admin': user.is_admin,
             'credentials': [{'auth_provider_type': c.auth_provider_type,
                              'auth_provider_id': c.auth_provider_id}
                             for c in user.credentials],
diff --git a/homeassistant/components/config/auth.py b/homeassistant/components/config/auth.py
index 625dbefbbb3e2fcb95f7948df957e9d1fa18aa9e..e6451e09a98a84ffb65b2536daf29ac44347bb86 100644
--- a/homeassistant/components/config/auth.py
+++ b/homeassistant/components/config/auth.py
@@ -36,6 +36,7 @@ async def async_setup(hass):
         WS_TYPE_CREATE, websocket_create,
         SCHEMA_WS_CREATE
     )
+    hass.components.websocket_api.async_register_command(websocket_update)
     return True
 
 
@@ -84,6 +85,40 @@ async def websocket_create(hass, connection, msg):
         }))
 
 
+@websocket_api.require_admin
+@websocket_api.async_response
+@websocket_api.websocket_command({
+    vol.Required('type'): 'config/auth/update',
+    vol.Required('user_id'): str,
+    vol.Optional('name'): str,
+    vol.Optional('group_ids'): [str]
+})
+async def websocket_update(hass, connection, msg):
+    """Update a user."""
+    user = await hass.auth.async_get_user(msg.pop('user_id'))
+
+    if not user:
+        connection.send_message(websocket_api.error_message(
+            msg['id'], websocket_api.const.ERR_NOT_FOUND, 'User not found'))
+        return
+
+    if user.system_generated:
+        connection.send_message(websocket_api.error_message(
+            msg['id'], 'cannot_modify_system_generated',
+            'Unable to update system generated users.'))
+        return
+
+    msg.pop('type')
+    msg_id = msg.pop('id')
+
+    await hass.auth.async_update_user(user, **msg)
+
+    connection.send_message(
+        websocket_api.result_message(msg_id, {
+            'user': _user_info(user),
+        }))
+
+
 def _user_info(user):
     """Format a user."""
     return {
diff --git a/tests/components/config/test_auth.py b/tests/components/config/test_auth.py
index 5cc7b4bd82e6b4324bee333f4c47560aacedffb1..316740488e3aba817a8d5090dbd975f9c9bc47e0 100644
--- a/tests/components/config/test_auth.py
+++ b/tests/components/config/test_auth.py
@@ -112,7 +112,7 @@ async def test_list(hass, hass_ws_client, hass_admin_user):
 
 async def test_delete_requires_admin(hass, hass_ws_client,
                                      hass_read_only_access_token):
-    """Test delete command requires an owner."""
+    """Test delete command requires an admin."""
     client = await hass_ws_client(hass, hass_read_only_access_token)
 
     await client.send_json({
@@ -205,7 +205,7 @@ async def test_create(hass, hass_ws_client, hass_access_token):
 
 async def test_create_requires_admin(hass, hass_ws_client,
                                      hass_read_only_access_token):
-    """Test create command requires an owner."""
+    """Test create command requires an admin."""
     client = await hass_ws_client(hass, hass_read_only_access_token)
 
     await client.send_json({
@@ -217,3 +217,67 @@ async def test_create_requires_admin(hass, hass_ws_client,
     result = await client.receive_json()
     assert not result['success'], result
     assert result['error']['code'] == 'unauthorized'
+
+
+async def test_update(hass, hass_ws_client):
+    """Test update command works."""
+    client = await hass_ws_client(hass)
+
+    user = await hass.auth.async_create_user("Test user")
+
+    await client.send_json({
+        'id': 5,
+        'type': 'config/auth/update',
+        'user_id': user.id,
+        'name': 'Updated name',
+        'group_ids': ['system-read-only'],
+    })
+
+    result = await client.receive_json()
+    assert result['success'], result
+    data_user = result['result']['user']
+
+    assert user.name == "Updated name"
+    assert data_user['name'] == "Updated name"
+    assert len(user.groups) == 1
+    assert user.groups[0].id == "system-read-only"
+    assert data_user['group_ids'] == ["system-read-only"]
+
+
+async def test_update_requires_admin(hass, hass_ws_client,
+                                     hass_read_only_access_token):
+    """Test update command requires an admin."""
+    client = await hass_ws_client(hass, hass_read_only_access_token)
+
+    user = await hass.auth.async_create_user("Test user")
+
+    await client.send_json({
+        'id': 5,
+        'type': 'config/auth/update',
+        'user_id': user.id,
+        'name': 'Updated name',
+    })
+
+    result = await client.receive_json()
+    assert not result['success'], result
+    assert result['error']['code'] == 'unauthorized'
+    assert user.name == "Test user"
+
+
+async def test_update_system_generated(hass, hass_ws_client):
+    """Test update command cannot update a system generated."""
+    client = await hass_ws_client(hass)
+
+    user = await hass.auth.async_create_system_user("Test user")
+
+    await client.send_json({
+        'id': 5,
+        'type': 'config/auth/update',
+        'user_id': user.id,
+        'name': 'Updated name',
+    })
+
+    result = await client.receive_json()
+    assert not result['success'], result
+    assert result['error']['code'] == 'cannot_modify_system_generated'
+    assert user.name == "Test user"