67 lines
2.0 KiB
Python
67 lines
2.0 KiB
Python
"""Authentication for HTTP component."""
|
|
import asyncio
|
|
import hmac
|
|
import logging
|
|
|
|
from homeassistant.const import HTTP_HEADER_HA_AUTH
|
|
from .util import get_real_ip
|
|
from .const import KEY_TRUSTED_NETWORKS, KEY_AUTHENTICATED
|
|
|
|
DATA_API_PASSWORD = 'api_password'
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
@asyncio.coroutine
|
|
def auth_middleware(app, handler):
|
|
"""Authentication middleware."""
|
|
# If no password set, just always set authenticated=True
|
|
if app['hass'].http.api_password is None:
|
|
@asyncio.coroutine
|
|
def no_auth_middleware_handler(request):
|
|
"""Auth middleware to approve all requests."""
|
|
request[KEY_AUTHENTICATED] = True
|
|
return handler(request)
|
|
|
|
return no_auth_middleware_handler
|
|
|
|
@asyncio.coroutine
|
|
def auth_middleware_handler(request):
|
|
"""Auth middleware to check authentication."""
|
|
# Auth code verbose on purpose
|
|
authenticated = False
|
|
|
|
if (HTTP_HEADER_HA_AUTH in request.headers and
|
|
validate_password(request,
|
|
request.headers[HTTP_HEADER_HA_AUTH])):
|
|
# A valid auth header has been set
|
|
authenticated = True
|
|
|
|
elif (DATA_API_PASSWORD in request.GET and
|
|
validate_password(request, request.GET[DATA_API_PASSWORD])):
|
|
authenticated = True
|
|
|
|
elif is_trusted_ip(request):
|
|
authenticated = True
|
|
|
|
request[KEY_AUTHENTICATED] = authenticated
|
|
|
|
return handler(request)
|
|
|
|
return auth_middleware_handler
|
|
|
|
|
|
def is_trusted_ip(request):
|
|
"""Test if request is from a trusted ip."""
|
|
ip_addr = get_real_ip(request)
|
|
|
|
return ip_addr and any(
|
|
ip_addr in trusted_network for trusted_network
|
|
in request.app[KEY_TRUSTED_NETWORKS])
|
|
|
|
|
|
def validate_password(request, api_password):
|
|
"""Test if password is valid."""
|
|
return hmac.compare_digest(api_password,
|
|
request.app['hass'].http.api_password)
|