File tree 4 files changed +27
-19
lines changed
features/sign-in/components
4 files changed +27
-19
lines changed Original file line number Diff line number Diff line change @@ -5,19 +5,20 @@ import { z } from 'zod'
5
5
6
6
import { safeSchemaJsonParse } from '~/utils/zod'
7
7
import { HOME } from '~/lib/routes'
8
+ import { callbackUrlSchema } from '~/schemas/url'
8
9
import { SgidErrorModal } from './SgidErrorModal'
9
10
10
11
export const SgidErrorFallback : ComponentType < FallbackProps > = ( { error } ) => {
11
12
const router = useRouter ( )
12
13
const redirectUrl = useMemo ( ( ) => {
13
14
const parsed = safeSchemaJsonParse (
14
15
z . object ( {
15
- landingUrl : z . string ( ) ,
16
+ landingUrl : callbackUrlSchema ,
16
17
} ) ,
17
18
String ( router . query . state ) ,
18
19
)
19
20
if ( parsed . success ) {
20
- return parsed . data . landingUrl
21
+ return parsed . data . landingUrl . href
21
22
}
22
23
return HOME
23
24
} , [ router . query . state ] )
Original file line number Diff line number Diff line change @@ -5,6 +5,7 @@ import { Button } from '@opengovsg/design-system-react'
5
5
import { trpc } from '~/utils/trpc'
6
6
import { getRedirectUrl } from '~/utils/url'
7
7
import { SingpassFullLogo } from '~/components/Svg/SingpassFullLogo'
8
+ import { callbackUrlSchema } from '~/schemas/url'
8
9
9
10
export const SgidLoginButton = ( ) : JSX . Element | null => {
10
11
const router = useRouter ( )
@@ -14,7 +15,7 @@ export const SgidLoginButton = (): JSX.Element | null => {
14
15
} ,
15
16
} )
16
17
17
- const landingUrl = getRedirectUrl ( router . query )
18
+ const landingUrl = callbackUrlSchema . parse ( getRedirectUrl ( router . query ) ) . href
18
19
19
20
const handleSgidLogin = ( ) => {
20
21
return sgidLoginMutation . mutate ( {
Original file line number Diff line number Diff line change @@ -6,17 +6,27 @@ import { HOME } from '~/lib/routes'
6
6
7
7
const baseUrl = new URL ( getBaseUrl ( ) )
8
8
9
+ const urlSchema = createUrlSchema ( {
10
+ baseOrigin : baseUrl . origin ,
11
+ whitelist : {
12
+ protocols : [ 'http' , 'https' ] ,
13
+ hosts : [ baseUrl . host ] ,
14
+ } ,
15
+ } )
16
+
9
17
export const callbackUrlSchema = z
10
18
. string ( )
11
19
. optional ( )
12
20
. default ( HOME )
13
- . pipe (
14
- createUrlSchema ( {
15
- baseOrigin : baseUrl . origin ,
16
- whitelist : {
17
- protocols : [ 'http' , 'https' ] ,
18
- hosts : [ baseUrl . host ] ,
19
- } ,
20
- } ) ,
21
- )
21
+ . transform ( ( val , ctx ) => {
22
+ try {
23
+ return urlSchema . parse ( val )
24
+ } catch {
25
+ ctx . addIssue ( {
26
+ code : z . ZodIssueCode . custom ,
27
+ message : 'URL validation error' ,
28
+ } )
29
+ return z . NEVER
30
+ }
31
+ } )
22
32
. catch ( new URL ( HOME , baseUrl . origin ) )
Original file line number Diff line number Diff line change @@ -22,16 +22,12 @@ import {
22
22
} from './sgid.utils'
23
23
24
24
const sgidCallbackStateSchema = z . object ( {
25
- landingUrl : z . string ( ) ,
25
+ landingUrl : callbackUrlSchema ,
26
26
} )
27
27
28
28
export const sgidRouter = router ( {
29
29
login : publicProcedure
30
- . input (
31
- z . object ( {
32
- landingUrl : callbackUrlSchema ,
33
- } ) ,
34
- )
30
+ . input ( sgidCallbackStateSchema )
35
31
. mutation ( async ( { ctx, input : { landingUrl } } ) => {
36
32
if ( ! sgid ) {
37
33
throw new TRPCError ( {
@@ -158,7 +154,7 @@ export const sgidRouter = router({
158
154
selectProfileStep : true ,
159
155
redirectUrl : appendWithRedirect (
160
156
`${ SIGN_IN } ${ SIGN_IN_SELECT_PROFILE_SUBROUTE } ` ,
161
- parsedState . data . landingUrl ,
157
+ parsedState . data . landingUrl . href ,
162
158
) ,
163
159
}
164
160
} ) ,
You can’t perform that action at this time.
0 commit comments