Skip to content

Commit 21013e7

Browse files
committed
Application header for web3 auth
1 parent 575737a commit 21013e7

File tree

5 files changed

+83
-13
lines changed

5 files changed

+83
-13
lines changed

brood/actions.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
VerificationEmail,
4141
)
4242
from .settings import (
43-
APPLICATION_NAME,
4443
BUGOUT_FROM_EMAIL,
4544
BUGOUT_URL,
4645
DEFAULT_USER_GROUP_LIMIT,
@@ -463,7 +462,10 @@ def create_user(
463462
payload_json = base64.decodebytes(signature.encode()).decode("utf-8")
464463
payload = json.loads(payload_json)
465464
verified = verify(
466-
authorization_payload=payload, application_to_check=APPLICATION_NAME
465+
authorization_payload=payload,
466+
application_to_check=str(application_id)
467+
if application_id is not None
468+
else "",
467469
)
468470
if not verified:
469471
logger.info("Web3 registration verification error")

brood/api.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
from fastapi.middleware.cors import CORSMiddleware
2222
from fastapi.security import OAuth2PasswordRequestForm
2323
from fastapi.security.utils import get_authorization_scheme_param
24-
from web3login.exceptions import Web3VerificationError
24+
from web3login.exceptions import (
25+
Web3AuthorizationExpired,
26+
Web3AuthorizationWrongApplication,
27+
Web3VerificationError,
28+
)
2529

2630
from . import actions, data, exceptions, models, subscriptions
2731
from .db import yield_db_session_from_env
@@ -160,8 +164,12 @@ async def create_user_handler(
160164
status_code=422,
161165
detail=invalid_password_error.generic_error_message,
162166
)
167+
except Web3AuthorizationExpired:
168+
raise HTTPException(status_code=403, detail="Signature not verified")
169+
except Web3AuthorizationWrongApplication:
170+
raise HTTPException(status_code=403, detail="Signature not verified")
163171
except Web3VerificationError:
164-
raise HTTPException(status_code=400, detail="Invalid user signature")
172+
raise HTTPException(status_code=403, detail="Signature not verified")
165173
except Exception:
166174
raise HTTPException(status_code=500)
167175

brood/middleware.py

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
import base64
22
import json
33
import logging
4-
from typing import Optional
4+
from typing import cast, Optional
55
from uuid import UUID
66

77
from fastapi import Depends, HTTPException, Request
88
from fastapi.exceptions import HTTPException
99
from fastapi.security.utils import get_authorization_scheme_param
1010
from web3login.auth import to_checksum_address, verify
11-
from web3login.exceptions import Web3VerificationError
11+
from web3login.exceptions import (
12+
Web3AuthorizationExpired,
13+
Web3AuthorizationWrongApplication,
14+
Web3VerificationError,
15+
)
1216
from web3login.middlewares.fastapi import OAuth2BearerOrWeb3
1317

1418
from . import actions, data
1519
from .db import yield_db_read_only_session
1620
from .settings import (
17-
APPLICATION_NAME,
1821
BOT_INSTALLATION_TOKEN,
1922
BOT_INSTALLATION_TOKEN_HEADER,
23+
BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER,
2024
)
2125

2226
logger = logging.getLogger(__name__)
@@ -41,13 +45,27 @@ async def get_current_user(
4145
if token is None or token == "":
4246
raise HTTPException(status_code=404, detail="Access token not found")
4347

48+
signature_application: str = request.headers.get(
49+
BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER
50+
)
51+
application_id = None
52+
if signature_application is not None:
53+
try:
54+
application_id = cast(UUID, signature_application)
55+
except Exception:
56+
raise HTTPException(
57+
status_code=403, detail="Wrong Web3 signature application provided"
58+
)
59+
4460
try:
4561
if scheme == "web3":
4662
payload_json = base64.decodebytes(str(token).encode()).decode("utf-8")
4763
payload = json.loads(payload_json)
4864
verified = verify(
4965
authorization_payload=payload,
50-
application_to_check=APPLICATION_NAME,
66+
application_to_check=str(application_id)
67+
if application_id is not None
68+
else "",
5169
)
5270
if not verified:
5371
logger.info("Web3 verification error")
@@ -57,7 +75,11 @@ async def get_current_user(
5775
logger.error("Web3 address in payload could not be None")
5876
raise Exception()
5977
web3_address = to_checksum_address(web3_address)
60-
user = actions.get_user(session=db_session, web3_address=web3_address)
78+
user = actions.get_user(
79+
session=db_session,
80+
web3_address=web3_address,
81+
application_id=application_id,
82+
)
6183

6284
elif scheme == "bearer":
6385
is_token_active, user = actions.get_current_user_by_token(
@@ -82,6 +104,10 @@ async def get_current_user(
82104
except actions.UserInvalidParameters as e:
83105
logger.info(e)
84106
raise HTTPException(status_code=500)
107+
except Web3AuthorizationExpired:
108+
raise HTTPException(status_code=403, detail="Signature not verified")
109+
except Web3AuthorizationWrongApplication:
110+
raise HTTPException(status_code=403, detail="Signature not verified")
85111
except Web3VerificationError:
86112
raise HTTPException(status_code=403, detail="Signature not verified")
87113
except Exception:
@@ -117,13 +143,27 @@ async def get_current_user_with_groups(
117143
if token is None or token == "":
118144
raise HTTPException(status_code=404, detail="Access token not found")
119145

146+
signature_application: str = request.headers.get(
147+
BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER
148+
)
149+
application_id = None
150+
if signature_application is not None:
151+
try:
152+
application_id = cast(UUID, signature_application)
153+
except Exception:
154+
raise HTTPException(
155+
status_code=403, detail="Wrong Web3 signature application provided"
156+
)
157+
120158
try:
121159
if scheme == "web3":
122160
payload_json = base64.decodebytes(str(token).encode()).decode("utf-8")
123161
payload = json.loads(payload_json)
124162
verified = verify(
125163
authorization_payload=payload,
126-
application_to_check=APPLICATION_NAME,
164+
application_to_check=str(application_id)
165+
if application_id is not None
166+
else "",
127167
)
128168
if not verified:
129169
logger.info("Web3 authorization verification error")
@@ -134,7 +174,9 @@ async def get_current_user_with_groups(
134174
raise Exception()
135175
web3_address = to_checksum_address(web3_address)
136176
user_extended = actions.get_user_with_groups(
137-
session=db_session, web3_address=web3_address
177+
session=db_session,
178+
web3_address=web3_address,
179+
application_id=application_id,
138180
)
139181

140182
elif scheme == "bearer":
@@ -163,6 +205,10 @@ async def get_current_user_with_groups(
163205
except actions.UserInvalidParameters as e:
164206
logger.info(e)
165207
raise HTTPException(status_code=500)
208+
except Web3AuthorizationExpired:
209+
raise HTTPException(status_code=403, detail="Signature not verified")
210+
except Web3AuthorizationWrongApplication:
211+
raise HTTPException(status_code=403, detail="Signature not verified")
166212
except Web3VerificationError:
167213
raise HTTPException(status_code=403, detail="Signature not verified")
168214
except Exception:

brood/settings.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
import stripe # type: ignore
55

6-
APPLICATION_NAME = "brood"
7-
86
RAW_ORIGIN = os.environ.get("BROOD_CORS_ALLOWED_ORIGINS")
97
if RAW_ORIGIN is None:
108
raise ValueError(
@@ -98,3 +96,16 @@ def group_invite_link_from_env(code: str, email: Optional[str] = None) -> str:
9896
BROOD_OPENAPI_LIST_RAW = os.environ.get("BROOD_OPENAPI_LIST")
9997
if BROOD_OPENAPI_LIST_RAW is not None:
10098
BROOD_OPENAPI_LIST = BROOD_OPENAPI_LIST_RAW.split(",")
99+
100+
# Web3 signature
101+
BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER_RAW = os.environ.get(
102+
"BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER"
103+
)
104+
if BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER_RAW is not None:
105+
BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER = (
106+
BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER_RAW
107+
)
108+
else:
109+
raise ValueError(
110+
"BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER environment variable must be set"
111+
)

configs/sample.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export MOONSTREAM_APPLICATION_ID="<moonstream_app_id>"
1313
export BUGOUT_BOT_INSTALLATION_TOKEN="<token_for_autogenerated_users>"
1414
export BUGOUT_BOT_INSTALLATION_TOKEN_HEADER="<bugout_installation_token_header>"
1515

16+
# Web3 signature variables
17+
export BUGOUT_WEB3_SIGNATURE_APPLICATION_HEADER="x-bugout-web3-signature-application"
18+
1619
# Set the following variables in the most reasonable manner for your development environment
1720
export STRIPE_SECRET_KEY="<Stripe_API_secret_key>"
1821
export STRIPE_SIGNING_SECRET="<Stripe_Webhook_signing_key>"

0 commit comments

Comments
 (0)