Foundation for users (#13968)

* Add initial user foundation to Home Assistant

* Address comments

* Address comments

* Allow non-ascii passwords

* One more utf-8 hmac compare digest

* Add new line
This commit is contained in:
Paulus Schoutsen 2018-05-01 12:20:41 -04:00 committed by Pascal Vizeli
parent b994c10d7f
commit cdd45e7878
22 changed files with 1774 additions and 59 deletions

View file

@ -32,17 +32,19 @@ def setup_auth(app, trusted_networks, api_password):
if (HTTP_HEADER_HA_AUTH in request.headers and
hmac.compare_digest(
api_password, request.headers[HTTP_HEADER_HA_AUTH])):
api_password.encode('utf-8'),
request.headers[HTTP_HEADER_HA_AUTH].encode('utf-8'))):
# A valid auth header has been set
authenticated = True
elif (DATA_API_PASSWORD in request.query and
hmac.compare_digest(api_password,
request.query[DATA_API_PASSWORD])):
hmac.compare_digest(
api_password.encode('utf-8'),
request.query[DATA_API_PASSWORD].encode('utf-8'))):
authenticated = True
elif (hdrs.AUTHORIZATION in request.headers and
validate_authorization_header(api_password, request)):
await async_validate_auth_header(api_password, request)):
authenticated = True
elif _is_trusted_ip(request, trusted_networks):
@ -70,23 +72,38 @@ def _is_trusted_ip(request, 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)
api_password.encode('utf-8'),
request.app['hass'].http.api_password.encode('utf-8'))
def validate_authorization_header(api_password, request):
async def async_validate_auth_header(api_password, request):
"""Test an authorization header if valid password."""
if hdrs.AUTHORIZATION not in request.headers:
return False
auth_type, auth = request.headers.get(hdrs.AUTHORIZATION).split(' ', 1)
auth_type, auth_val = request.headers.get(hdrs.AUTHORIZATION).split(' ', 1)
if auth_type != 'Basic':
if auth_type == 'Basic':
decoded = base64.b64decode(auth_val).decode('utf-8')
try:
username, password = decoded.split(':', 1)
except ValueError:
# If no ':' in decoded
return False
if username != 'homeassistant':
return False
return hmac.compare_digest(api_password.encode('utf-8'),
password.encode('utf-8'))
if auth_type != 'Bearer':
return False
decoded = base64.b64decode(auth).decode('utf-8')
username, password = decoded.split(':', 1)
if username != 'homeassistant':
hass = request.app['hass']
access_token = hass.auth.async_get_access_token(auth_val)
if access_token is None:
return False
return hmac.compare_digest(api_password, password)
request['hass_user'] = access_token.refresh_token.user
return True