feat: implement local cookie authentication

This is only useful for application running directly on the Raspiblitz.
This will create a file in ~/.blitz_api/.cookie with a valid JWT token.
Local applications can use this to authenticate to the API without
having to ask for the password. This is similar to how Bitcoin Cores
cookie auth works.
This commit is contained in:
Stefan Stammberger 2021-11-28 08:42:52 +01:00
parent 782464b61d
commit 71f87e06d7
No known key found for this signature in database
GPG key ID: 645FA807E935D9D5
3 changed files with 51 additions and 0 deletions

View file

@ -6,6 +6,11 @@ jwt_expiry_time=300
# login password
login_password=12345678
# Enable this if you want to run blitz_gui locally.
# This will create a file called ~/blitz_api/.cookie with a
# JWT token.
# enable_local_cookie_auth = false
# Amount of seconds the app will wait until it'll
# send another hardware update
gather_hw_info_interval = 2

View file

@ -1,3 +1,5 @@
import asyncio
import os
import time
from typing import Dict
@ -29,3 +31,39 @@ def decodeJWT(token: str) -> dict:
except Exception as e:
print(f"Unable to decode jwt_token {e}")
return {}
def handle_local_cookie():
remove_local_cookie()
blitz_path = os.path.join(os.path.expanduser("~"), ".blitz_api")
full_cookie_file_path = os.path.join(blitz_path, ".cookie")
enabled = config("enable_local_cookie_auth", default=False, cast=bool)
if not os.path.exists(blitz_path):
os.makedirs(blitz_path)
if enabled:
f = open(full_cookie_file_path, "w")
f.write(signJWT()["access_token"])
f.close()
def remove_local_cookie():
full_cookie_file_path = os.path.join(
os.path.expanduser("~"), ".blitz_api", ".cookie"
)
if os.path.exists(path=full_cookie_file_path):
os.remove(full_cookie_file_path)
def register_cookie_updater():
# We need to update the cookie file once the cookie is expired
async def _cookie_updater():
while True:
await asyncio.sleep(JWT_EXPIRY_TIME - 10)
handle_local_cookie()
loop = asyncio.get_event_loop()
loop.create_task(_cookie_updater())

View file

@ -15,6 +15,11 @@ from starlette import status
from starlette.middleware.cors import CORSMiddleware
from starlette.responses import RedirectResponse
from app.auth.auth_handler import (
handle_local_cookie,
register_cookie_updater,
remove_local_cookie,
)
from app.external.fastapi_versioning import VersionedFastAPI
from app.external.sse_startlette import EventSourceResponse
from app.repositories.bitcoin import (
@ -73,11 +78,14 @@ async def on_startup():
await redis_plugin.init_app(app, config=config)
await redis_plugin.init()
await register_all_handlers(redis_plugin.redis)
handle_local_cookie()
register_cookie_updater()
@app.on_event("shutdown")
async def on_shutdown() -> None:
await redis_plugin.terminate()
remove_local_cookie()
@app.get("/")