Skip to content

Commit

Permalink
feat(sentry): improve sentry config and add masking
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulkeerthi committed Nov 2, 2023
1 parent 1384556 commit 8380498
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 13 deletions.
12 changes: 6 additions & 6 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,23 @@ const Home: NextPageWithLayout = () => {
const { removeItem: removeAccessToken } = useSessionStorage('accessToken', '')
const router = useRouter()

const [isCloseHostedSessionModalOpen, setisCloseHostedSessionModalOpen] =
const [isCloseHostedSessionModalOpen, setIsCloseHostedSessionModalOpen] =
useState(false)

const redirectAfterSession = (url: string) => {
// adding 2 second delay so users are aware of the redirection and we don't change the page abruptly
setTimeout(() => {
router.push(url)
removeAccessToken()
router.push(url)
}, 2000)
}

const onOpenCloseHostedSessionModal = () => {
setisCloseHostedSessionModalOpen(true)
setIsCloseHostedSessionModalOpen(true)
}

const onCloseHostedSessionModal = () => {
setisCloseHostedSessionModalOpen(false)
setIsCloseHostedSessionModalOpen(false)
}

const onCloseHostedSession = () => {
Expand All @@ -74,7 +74,7 @@ const Home: NextPageWithLayout = () => {
case HostedSessionStatus.Completed:
addSentryBreadcrumb({
category: BreadcrumbCategory.SESSION_COMPLETE,
data: session,
data: { session },
})
if (shouldRedirect) {
redirectAfterSession(session.success_url as string)
Expand All @@ -83,7 +83,7 @@ const Home: NextPageWithLayout = () => {
case HostedSessionStatus.Expired:
addSentryBreadcrumb({
category: BreadcrumbCategory.SESSION_EXPIRE,
data: session,
data: { session },
})
if (shouldRedirect) {
redirectAfterSession(session.cancel_url as string)
Expand Down
5 changes: 2 additions & 3 deletions sentry.client.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ Sentry.init({
}
return event
},
// debug: true, // Set this to `true` in development to see Sentry diagnostic information
integrations: [
new Sentry.Replay({
maskAllInputs: true,
Expand All @@ -57,8 +56,8 @@ Sentry.init({
'content-length',
'content-encoding',
],
// do not capture network bodies in production
networkCaptureBodies: !process.env.NODE_ENV.includes('prod'),
// TODO: Decide on capturing in production, if masking form data before send isn't good (enough)
// networkCaptureBodies: !process.env.NODE_ENV.includes('prod'),
}),
],
})
2 changes: 1 addition & 1 deletion src/components/AuthGuard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { FC } from 'react'
import { useAuthentication } from '../services/authentication'

export const AuthGuard: FC<{ children?: React.ReactNode }> = ({ children }) => {
const { isAuthenticated, error } = useAuthentication()
const { error } = useAuthentication()

if (error) {
return <p>ERROR: {JSON.stringify(error)}</p>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { LoadingPage } from '../LoadingPage'
import { useSubmitForm } from '../../hooks/useSubmitForm'
import { useTranslation } from 'next-i18next'
import { ErrorPage } from '../ErrorPage'
import { addSentryBreadcrumb } from '../../services/ErrorReporter'
import { addSentryBreadcrumb, masker } from '../../services/ErrorReporter'
import { BreadcrumbCategory } from '../../services/ErrorReporter/addSentryBreadcrumb'
import useLocalStorage from 'use-local-storage'
import { useHostedSession } from '../../hooks/useHostedSession'
Expand Down Expand Up @@ -46,6 +46,7 @@ export const Form: FC<FormProps> = ({ activity }) => {
category: BreadcrumbCategory.EVALUATE_FORM_RULES,
data: {
form_id: form?.id,
response: masker(response),
},
})

Expand All @@ -57,6 +58,7 @@ export const Form: FC<FormProps> = ({ activity }) => {
category: BreadcrumbCategory.SUBMIT_FORM,
data: {
form_id: form?.id,
response: masker(response),
},
})
await onSubmit(response)
Expand Down
2 changes: 2 additions & 0 deletions src/services/ErrorReporter/addSentryBreadcrumb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export enum BreadcrumbCategory {
READ_MESSAGE = 'READ_MESSAGE',
SUBMIT_CHECKLIST = 'SUBMIT_CHECKLIST',
GENERIC = 'generic',
NAVIGATION = 'navigation',
}

const SentryBreadcrumbMessageDictionary = {
Expand All @@ -21,6 +22,7 @@ const SentryBreadcrumbMessageDictionary = {
[BreadcrumbCategory.READ_MESSAGE]: 'Reading message',
[BreadcrumbCategory.SUBMIT_CHECKLIST]: 'Submitting checklist',
[BreadcrumbCategory.GENERIC]: 'Generic event',
[BreadcrumbCategory.NAVIGATION]: 'Navigation',
}

export const addSentryBreadcrumb = ({
Expand Down
1 change: 1 addition & 0 deletions src/services/ErrorReporter/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { addSentryBreadcrumb } from './addSentryBreadcrumb'
export { masker } from './masker'
32 changes: 32 additions & 0 deletions src/services/ErrorReporter/masker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Masker function to mask sensitive data from form related breadcrumbs. This assumes
* that the object(s) have a field called value that needs to be masked.
* @param value this is the value to be masked, can be an object or an array of
* objects with a value field
* @returns the masked object or array of objects
*/
export const masker = (
value: Record<string, any> | Array<Record<string, any>>
): any => {
if (Array.isArray(value)) {
return value.map(masker)
}

if (typeof value === 'object' && value !== null && value !== undefined) {
return Object.fromEntries(
Object.entries(value).map(([key, value]) => {
if (key !== 'value') {
return [key, value]
}
return [
key,
typeof value === 'string' || typeof value === 'number'
? '*'.repeat(value.toString().length)
: masker(value),
]
})
)
}

return value
}
20 changes: 18 additions & 2 deletions src/services/authentication/AuthenticationProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React, { FC, useEffect, useState } from 'react'
import { parse } from 'query-string'
import { AuthenticationContext } from './AuthenticationContext'
import { urlHasAuthState } from './urlHasAuthState'
import { useSessionStorage } from '../../hooks/useSessionStorage'
import { useRouter } from 'next/router'
import useSwr from 'swr'
import { ErrorPage, LoadingPage } from '../../components'
import { useTranslation } from 'next-i18next'
import { addBreadcrumb } from '@sentry/nextjs'
import { BreadcrumbCategory } from '../ErrorReporter/addSentryBreadcrumb'
interface AuthenticationProviderProps {
children?: React.ReactNode
}
Expand Down Expand Up @@ -55,11 +55,27 @@ export const AuthenticationProvider: FC<AuthenticationProviderProps> = ({
}

if (router.isReady && !router.query.sessionId) {
addBreadcrumb({
category: BreadcrumbCategory.NAVIGATION,
message: 'Invalid URL',
data: {
url: router.asPath,
sessionId: router.query.sessionId,
},
})
return <ErrorPage title={t('session.invalid_url')} />
}

// Wait while token is being generated
if (!router.isReady || tokenLoading) {
addBreadcrumb({
category: BreadcrumbCategory.NAVIGATION,
message: 'Preparing router and/or token',
data: {
url: router.asPath,
sessionId: router.query.sessionId,
},
})
return <LoadingPage title={t('session.authentication_loading')} />
}

Expand Down

0 comments on commit 8380498

Please sign in to comment.