diff --git a/homeassistant/components/config/auth_provider_homeassistant.py b/homeassistant/components/config/auth_provider_homeassistant.py
index fca03ad8fa9f01cde226b5b644d7691beba6ec43..960e8f5e7b4e4244b3f06342a4b3c3b6131ad38e 100644
--- a/homeassistant/components/config/auth_provider_homeassistant.py
+++ b/homeassistant/components/config/auth_provider_homeassistant.py
@@ -20,6 +20,13 @@ SCHEMA_WS_DELETE = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
     vol.Required('username'): str,
 })
 
+WS_TYPE_CHANGE_PASSWORD = 'config/auth_provider/homeassistant/change_password'
+SCHEMA_WS_CHANGE_PASSWORD = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
+    vol.Required('type'): WS_TYPE_CHANGE_PASSWORD,
+    vol.Required('current_password'): str,
+    vol.Required('new_password'): str
+})
+
 
 async def async_setup(hass):
     """Enable the Home Assistant views."""
@@ -31,6 +38,10 @@ async def async_setup(hass):
         WS_TYPE_DELETE, websocket_delete,
         SCHEMA_WS_DELETE
     )
+    hass.components.websocket_api.async_register_command(
+        WS_TYPE_CHANGE_PASSWORD, websocket_change_password,
+        SCHEMA_WS_CHANGE_PASSWORD
+    )
     return True
 
 
@@ -118,3 +129,46 @@ def websocket_delete(hass, connection, msg):
             websocket_api.result_message(msg['id']))
 
     hass.async_add_job(delete_creds())
+
+
+@callback
+def websocket_change_password(hass, connection, msg):
+    """Change user password."""
+    async def change_password():
+        """Change user password."""
+        user = connection.request.get('hass_user')
+        if user is None:
+            connection.send_message_outside(websocket_api.error_message(
+                msg['id'], 'user_not_found', 'User not found'))
+            return
+
+        provider = _get_provider(hass)
+        await provider.async_initialize()
+
+        username = None
+        for credential in user.credentials:
+            if credential.auth_provider_type == provider.type:
+                username = credential.data['username']
+                break
+
+        if username is None:
+            connection.send_message_outside(websocket_api.error_message(
+                msg['id'], 'credentials_not_found', 'Credentials not found'))
+            return
+
+        try:
+            await provider.async_validate_login(
+                username, msg['current_password'])
+        except auth_ha.InvalidAuth:
+            connection.send_message_outside(websocket_api.error_message(
+                msg['id'], 'invalid_password', 'Invalid password'))
+            return
+
+        await hass.async_add_executor_job(
+            provider.data.change_password, username, msg['new_password'])
+        await provider.data.async_save()
+
+        connection.send_message_outside(
+            websocket_api.result_message(msg['id']))
+
+    hass.async_add_job(change_password())
diff --git a/tests/components/config/test_auth_provider_homeassistant.py b/tests/components/config/test_auth_provider_homeassistant.py
index fa4ab612bb12c5d49f1ee18d516fb0d00ebabb1c..cd2cbc445399675abcaa5464e48b8e8c65ea0ffa 100644
--- a/tests/components/config/test_auth_provider_homeassistant.py
+++ b/tests/components/config/test_auth_provider_homeassistant.py
@@ -227,3 +227,77 @@ async def test_delete_unknown_auth(hass, hass_ws_client, hass_access_token):
     result = await client.receive_json()
     assert not result['success'], result
     assert result['error']['code'] == 'auth_not_found'
+
+
+async def test_change_password(hass, hass_ws_client, hass_access_token):
+    """Test that change password succeeds with valid password."""
+    provider = hass.auth.auth_providers[0]
+    await provider.async_initialize()
+    await hass.async_add_executor_job(
+        provider.data.add_auth, 'test-user', 'test-pass')
+
+    credentials = await provider.async_get_or_create_credentials({
+        'username': 'test-user'
+    })
+
+    user = hass_access_token.refresh_token.user
+    await hass.auth.async_link_user(user, credentials)
+
+    client = await hass_ws_client(hass, hass_access_token)
+    await client.send_json({
+        'id': 6,
+        'type': auth_ha.WS_TYPE_CHANGE_PASSWORD,
+        'current_password': 'test-pass',
+        'new_password': 'new-pass'
+    })
+
+    result = await client.receive_json()
+    assert result['success'], result
+    await provider.async_validate_login('test-user', 'new-pass')
+
+
+async def test_change_password_wrong_pw(hass, hass_ws_client,
+                                        hass_access_token):
+    """Test that change password fails with invalid password."""
+    provider = hass.auth.auth_providers[0]
+    await provider.async_initialize()
+    await hass.async_add_executor_job(
+        provider.data.add_auth, 'test-user', 'test-pass')
+
+    credentials = await provider.async_get_or_create_credentials({
+        'username': 'test-user'
+    })
+
+    user = hass_access_token.refresh_token.user
+    await hass.auth.async_link_user(user, credentials)
+
+    client = await hass_ws_client(hass, hass_access_token)
+    await client.send_json({
+        'id': 6,
+        'type': auth_ha.WS_TYPE_CHANGE_PASSWORD,
+        'current_password': 'wrong-pass',
+        'new_password': 'new-pass'
+    })
+
+    result = await client.receive_json()
+    assert not result['success'], result
+    assert result['error']['code'] == 'invalid_password'
+    with pytest.raises(prov_ha.InvalidAuth):
+        await provider.async_validate_login('test-user', 'new-pass')
+
+
+async def test_change_password_no_creds(hass, hass_ws_client,
+                                        hass_access_token):
+    """Test that change password fails with no credentials."""
+    client = await hass_ws_client(hass, hass_access_token)
+
+    await client.send_json({
+        'id': 6,
+        'type': auth_ha.WS_TYPE_CHANGE_PASSWORD,
+        'current_password': 'test-pass',
+        'new_password': 'new-pass'
+    })
+
+    result = await client.receive_json()
+    assert not result['success'], result
+    assert result['error']['code'] == 'credentials_not_found'