Skip to content

Commit 8901b0f

Browse files
committed
Make the registration webhook be a blocker for undesired emails
Signed-off-by: Federico Busetti <[email protected]>
1 parent 5b106e0 commit 8901b0f

File tree

3 files changed

+61
-20
lines changed

3 files changed

+61
-20
lines changed

auth_volumes/kratos/kratos.yml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,26 +81,18 @@ selfservice:
8181
registration:
8282
lifespan: 10m
8383
ui_url: http://127.0.0.1:8080/registration
84+
8485
after:
8586
password:
8687
hooks:
87-
- hook: session
8888
- hook: web_hook
8989
config:
9090
url: http://dev:8000/user_registered/
9191
method: "POST"
92-
# headers: { }
93-
# https://www.ory.sh/docs/guides/integrate-with-ory-cloud-through-webhooks#jsonnet-templating
9492
body: file:///etc/config/kratos/user_registered.jsonnet
95-
can_interrupt: false
96-
emit_analytics_event: false
97-
# auth:
98-
# type: api_key
99-
# config:
100-
# name: ""
101-
# value: ""
102-
# in: header
103-
# - hook: show_verification_ui
93+
can_interrupt: true
94+
emit_analytics_event: true
95+
- hook: session
10496

10597
log:
10698
level: info
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
function(ctx) {
22
user_id: ctx.identity.id,
3-
traits: {
43
email: ctx.identity.traits.email,
5-
name: ctx.identity.traits.name,
6-
}
74
}
Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,64 @@
11
import logging
22

3-
from fastapi import APIRouter, Request
3+
from fastapi import APIRouter, status
4+
from fastapi.responses import JSONResponse, Response
5+
from pydantic import BaseModel
46

57
router = APIRouter(prefix="/user_registered")
68

79

10+
class UserRegisteredWebhook(BaseModel):
11+
user_id: str
12+
email: str
13+
14+
815
@router.post("/")
9-
async def user_registered(request: Request): # pragma: no cover
10-
# Here we could check the email and add staff metadata to the identity
11-
logging.info("User registered", extra={"body": await request.json()})
12-
return {"user_registered": "OK"}
16+
async def user_registered(user: UserRegisteredWebhook): # pragma: no cover
17+
"""
18+
Handles the user registration webhook.
19+
20+
This function is triggered when a user registration webhook is received.
21+
It logs the event details, evaluates the email validity, and returns an
22+
appropriate HTTP response based on the validation. If the user's email
23+
is invalid, it returns an error response along with a structured error
24+
message. Otherwise, it confirms successful processing with no additional
25+
content.
26+
27+
Args:
28+
user (UserRegisteredWebhook): The webhook payload received when a user
29+
registers, containing user details such as email and traits.
30+
31+
Returns:
32+
Response: An HTTP response with a 403 Forbidden status and structured
33+
error message if the user email is invalid.
34+
Otherwise, an HTTP 204 No Content response to confirm successful
35+
processing.
36+
"""
37+
logging.info("User registered", extra={"user": user.model_dump()})
38+
39+
error_message = {
40+
"messages": [
41+
{
42+
"instance_ptr": "#/traits/email",
43+
"messages": [
44+
{
45+
"id": 123, # Error id to be evaluated in frontend
46+
"text": "You are not allowed to register.",
47+
"type": "error",
48+
"context": { # Additional context we can send to the Frontend
49+
"value": "short value",
50+
"any": "additional information",
51+
},
52+
}
53+
],
54+
}
55+
]
56+
}
57+
58+
if user.email == "[email protected]":
59+
return JSONResponse(
60+
error_message,
61+
status.HTTP_403_FORBIDDEN,
62+
)
63+
else:
64+
return Response(status_code=status.HTTP_204_NO_CONTENT)

0 commit comments

Comments
 (0)