Skip to content

Commit

Permalink
redact email returned in register flows
Browse files Browse the repository at this point in the history
  • Loading branch information
aryaniyaps committed Mar 5, 2024
1 parent 204e407 commit 1254506
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 19 deletions.
6 changes: 3 additions & 3 deletions client/app/(authentication)/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default async function RegisterPage() {
const cookieStore = cookies();
const flowId = cookieStore.get(REGISTER_FLOW_ID_COOKIE);

let flowData;
let flow;

if (flowId) {
try {
Expand All @@ -19,7 +19,7 @@ export default async function RegisterPage() {
});
if (data) {
console.log('GOT FLOW DATA');
flowData = data;
flow = data;
}
} catch (err) {
console.log(typeof err);
Expand All @@ -31,7 +31,7 @@ export default async function RegisterPage() {
}

return (
<RegisterFlowProvider flowData={flowData}>
<RegisterFlowProvider flow={flow}>
<RegisterForm />
</RegisterFlowProvider>
);
Expand Down
2 changes: 1 addition & 1 deletion client/components/register/email-verification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const registerVerificationSchema = yup
.required();

export default function RegisterEmailVerification() {
const { setCurrentStep, flowData } = useRegisterFlow();
const { setCurrentStep, flow: flowData } = useRegisterFlow();

const router = useRouter();

Expand Down
12 changes: 6 additions & 6 deletions client/components/register/flow-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,35 @@ import { createContext, useContext, useState } from 'react';
interface RegisterFlowContextType {
setCurrentStep: (step: string | null) => void;
currentStep: string | null;
flowData: { email: string; currentStep: string; id: string } | undefined;
flow: { email: string; currentStep: string; id: string } | undefined;
}

// TODO: pass register flow email here
const RegisterFlowContext = createContext<RegisterFlowContextType>({
setCurrentStep(step) {},
currentStep: null,
flowData: undefined,
flow: undefined,
});

export const useRegisterFlow = () => useContext(RegisterFlowContext);

interface RegisterFlowProviderProps {
flowData: { email: string; currentStep: string; id: string } | undefined;
flow: { email: string; currentStep: string; id: string } | undefined;
}

export const RegisterFlowProvider: React.FC<
React.PropsWithChildren<RegisterFlowProviderProps>
> = ({ children, flowData }) => {
> = ({ children, flow }) => {
const [localCurrentStep, setCurrentStep] = useState<string | null>(
flowData ? flowData.currentStep : null
flow ? flow.currentStep : null
);

return (
<RegisterFlowContext.Provider
value={{
setCurrentStep,
currentStep: localCurrentStep,
flowData,
flow,
}}
>
{children}
Expand Down
2 changes: 1 addition & 1 deletion client/components/register/webauthn-registration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function RegisterWebAuthnRegistration() {
const { handleSubmit, formState, setError } = useForm({});

const router = useRouter();
const { flowData } = useRegisterFlow();
const { flow: flowData } = useRegisterFlow();
const searchParams = useSearchParams();

const returnTo = searchParams.get('returnTo') || DEFAULT_REDIRECT_TO;
Expand Down
14 changes: 7 additions & 7 deletions client/lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ import createClient, { Middleware } from 'openapi-fetch';
import type { paths } from '../generated/api/v1';
import { env } from './env';

function getBaseUrl(): string {
if (typeof window !== 'undefined') {
return env.NEXT_PUBLIC_API_BASE_URL; // browser should use public URL
}
return env.API_BASE_URL; // SSR should use server side URL
}

const errorMiddleware: Middleware = {
async onResponse(res) {
if (!res.ok) {
Expand All @@ -17,13 +24,6 @@ const errorMiddleware: Middleware = {
},
};

function getBaseUrl(): string {
if (typeof window !== 'undefined') {
return env.NEXT_PUBLIC_API_BASE_URL; // browser should use relative url
}
return env.API_BASE_URL; // SSR should use localhost
}

export const client = createClient<paths>({
baseUrl: getBaseUrl(),
headers: { 'Content-Type': 'application/json' },
Expand Down
9 changes: 8 additions & 1 deletion server/app/schemas/auth.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Annotated
from uuid import UUID

from pydantic import EmailStr, Field, Json, RootModel
from pydantic import EmailStr, Field, Json, RootModel, field_serializer
from webauthn.helpers.structs import (
PublicKeyCredentialCreationOptions,
PublicKeyCredentialRequestOptions,
Expand All @@ -10,6 +10,7 @@
from app.lib.enums import RegisterFlowStep
from app.schemas.base import BaseSchema
from app.schemas.user import UserSchema
from app.utils.formatting import redact_email


class RegisterFlowSchema(BaseSchema):
Expand All @@ -26,6 +27,12 @@ class RegisterFlowSchema(BaseSchema):
),
]

@field_serializer("email")
@classmethod
def serialize_email(cls, email: str) -> str:
"""Redact the given email (for security purposes)."""
return redact_email(email=email)


class RegisterFlowStartInput(BaseSchema):
email: Annotated[
Expand Down
15 changes: 15 additions & 0 deletions server/app/utils/formatting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
def redact_email(email: str) -> str:
"""
Redact the given email.
Replaces the characters in the username with asterisks,
except for the first and last character.
"""
# Split the email address into username and domain
username, domain = email.split("@")

# Redact the username
redacted_username = username[0] + "*" * (len(username) - 2) + username[-1]

# Reconstruct the redacted email
return redacted_username + "@" + domain

0 comments on commit 1254506

Please sign in to comment.