Onboarding to validate redirect uri (#36863)

This commit is contained in:
Paulus Schoutsen 2020-06-17 12:13:28 -07:00 committed by GitHub
parent 43cee39528
commit 903db07feb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 55 additions and 10 deletions

View File

@ -2,7 +2,9 @@
"domain": "frontend",
"name": "Home Assistant Frontend",
"documentation": "https://www.home-assistant.io/integrations/frontend",
"requirements": ["home-assistant-frontend==20200613.0"],
"requirements": [
"home-assistant-frontend==20200617.0"
],
"dependencies": [
"api",
"auth",
@ -15,6 +17,8 @@
"system_log",
"websocket_api"
],
"codeowners": ["@home-assistant/frontend"],
"codeowners": [
"@home-assistant/frontend"
],
"quality_scale": "internal"
}
}

View File

@ -4,9 +4,10 @@ import asyncio
import voluptuous as vol
from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.components.auth import indieauth
from homeassistant.components.http.data_validator import RequestDataValidator
from homeassistant.components.http.view import HomeAssistantView
from homeassistant.const import HTTP_FORBIDDEN
from homeassistant.const import HTTP_BAD_REQUEST, HTTP_FORBIDDEN
from homeassistant.core import callback
from .const import (
@ -168,7 +169,9 @@ class IntegrationOnboardingView(_BaseOnboardingView):
name = "api:onboarding:integration"
step = STEP_INTEGRATION
@RequestDataValidator(vol.Schema({vol.Required("client_id"): str}))
@RequestDataValidator(
vol.Schema({vol.Required("client_id"): str, vol.Required("redirect_uri"): str})
)
async def post(self, request, data):
"""Handle token creation."""
hass = request.app["hass"]
@ -182,6 +185,14 @@ class IntegrationOnboardingView(_BaseOnboardingView):
await self._async_mark_done(hass)
# Validate client ID and redirect uri
if not await indieauth.verify_redirect_uri(
request.app["hass"], data["client_id"], data["redirect_uri"]
):
return self.json_message(
"invalid client id or redirect uri", HTTP_BAD_REQUEST
)
# Return authorization code so we can redirect user and log them in
auth_code = hass.components.auth.create_auth_code(data["client_id"], user)
return self.json({"auth_code": auth_code})

View File

@ -12,7 +12,7 @@ cryptography==2.9.2
defusedxml==0.6.0
distro==1.5.0
hass-nabucasa==0.34.6
home-assistant-frontend==20200613.0
home-assistant-frontend==20200617.0
importlib-metadata==1.6.0;python_version<'3.8'
jinja2>=2.11.1
netdisco==2.7.0

View File

@ -735,7 +735,7 @@ hole==0.5.1
holidays==0.10.2
# homeassistant.components.frontend
home-assistant-frontend==20200613.0
home-assistant-frontend==20200617.0
# homeassistant.components.zwave
homeassistant-pyozw==0.1.10

View File

@ -331,7 +331,7 @@ hole==0.5.1
holidays==0.10.2
# homeassistant.components.frontend
home-assistant-frontend==20200613.0
home-assistant-frontend==20200617.0
# homeassistant.components.zwave
homeassistant-pyozw==0.1.10

View File

@ -11,7 +11,7 @@ from homeassistant.setup import async_setup_component
from . import mock_storage
from tests.async_mock import patch
from tests.common import CLIENT_ID, register_auth_provider
from tests.common import CLIENT_ID, CLIENT_REDIRECT_URI, register_auth_provider
from tests.components.met.conftest import mock_weather # noqa: F401
@ -192,7 +192,8 @@ async def test_onboarding_integration(hass, hass_storage, hass_client):
client = await hass_client()
resp = await client.post(
"/api/onboarding/integration", json={"client_id": CLIENT_ID}
"/api/onboarding/integration",
json={"client_id": CLIENT_ID, "redirect_uri": CLIENT_REDIRECT_URI},
)
assert resp.status == 200
@ -217,6 +218,35 @@ async def test_onboarding_integration(hass, hass_storage, hass_client):
await hass.auth.async_validate_access_token(tokens["access_token"]) is not None
)
# Onboarding refresh token and new refresh token
for user in await hass.auth.async_get_users():
assert len(user.refresh_tokens) == 2, user
async def test_onboarding_integration_invalid_redirect_uri(
hass, hass_storage, hass_client
):
"""Test finishing integration step."""
mock_storage(hass_storage, {"done": [const.STEP_USER]})
assert await async_setup_component(hass, "onboarding", {})
client = await hass_client()
resp = await client.post(
"/api/onboarding/integration",
json={"client_id": CLIENT_ID, "redirect_uri": "http://invalid-redirect.uri"},
)
assert resp.status == 400
# We will still mark the last step as done because there is nothing left.
assert const.STEP_INTEGRATION in hass_storage[const.DOMAIN]["data"]["done"]
# Only refresh token from onboarding should be there
for user in await hass.auth.async_get_users():
assert len(user.refresh_tokens) == 1, user
async def test_onboarding_integration_requires_auth(hass, hass_storage, aiohttp_client):
"""Test finishing integration step."""