11import type { CountryCode } from '@guardian/libs' ;
2- import { log } from '@guardian/libs' ;
2+ import { isObject , log } from '@guardian/libs' ;
33import type { TAction , TComponentType } from '@guardian/ophan-tracker-js' ;
44import { submitComponentEvent } from '../client/ophan/ophan' ;
5+ import type { Result } from '../lib/result' ;
6+ import { error , ok , okOrThrow } from '../lib/result' ;
57import { useIsSignedIn } from '../lib/useAuthStatus' ;
68import { useConsent } from '../lib/useConsent' ;
79import { useCountryCode } from '../lib/useCountryCode' ;
@@ -59,13 +61,21 @@ const getStage = (hostname: string): StageType => {
5961 * @param token A JWT Token
6062 * @returns extracted email address
6163 */
62- export const extractEmailFromToken = ( token : string ) : string | undefined => {
64+ export const extractEmailFromToken = (
65+ token : string ,
66+ ) : Result < 'ParsingError' , string > => {
6367 const payload = token . split ( '.' ) [ 1 ] ;
64- if ( ! payload ) return ;
65- const decoded = atob ( payload ) ;
66- const parsed = JSON . parse ( decoded ) as Record < string , unknown > ;
67- if ( typeof parsed . email !== 'string' ) return ;
68- return parsed . email ;
68+ if ( ! payload ) return error ( 'ParsingError' ) ;
69+ try {
70+ const decoded = Buffer . from ( payload , 'base64' ) . toString ( ) ;
71+ const parsed = JSON . parse ( decoded ) as unknown ;
72+ if ( ! isObject ( parsed ) || typeof parsed . email !== 'string' ) {
73+ return error ( 'ParsingError' ) ;
74+ }
75+ return ok ( parsed . email ) ;
76+ } catch ( e ) {
77+ return error ( 'ParsingError' ) ;
78+ }
6979} ;
7080
7181export const getRedirectUrl = ( {
@@ -189,7 +199,7 @@ export const initializeFedCM = async ({
189199 providers : getProviders ( stage ) ,
190200 } ,
191201 } )
192- . catch ( ( error ) => {
202+ . catch ( ( e ) => {
193203 /**
194204 * The fedcm API hides issues with the user's federated login state
195205 * behind a generic NetworkError. This error is thrown up to 60
@@ -201,13 +211,13 @@ export const initializeFedCM = async ({
201211 * Unfortunately for us it means we can't differentiate between
202212 * a genuine network error and a user declining the FedCM prompt.
203213 */
204- if ( error instanceof Error && error . name === 'NetworkError' ) {
214+ if ( e instanceof Error && e . name === 'NetworkError' ) {
205215 log (
206216 'identity' ,
207217 'FedCM prompt failed, potentially due to user declining' ,
208218 ) ;
209219 } else {
210- throw error ;
220+ throw e ;
211221 }
212222 } ) ;
213223
@@ -216,16 +226,10 @@ export const initializeFedCM = async ({
216226 credentials,
217227 } ) ;
218228
219- const signInEmail = extractEmailFromToken ( credentials . token ) ;
220- if ( signInEmail ) {
221- log ( 'identity' , `FedCM ID token for ${ signInEmail } received` ) ;
222- } else {
223- log (
224- 'identity' ,
225- 'FedCM token received but email could not be extracted from token' ,
226- ) ;
227- return ;
228- }
229+ const signInEmail = okOrThrow (
230+ extractEmailFromToken ( credentials . token ) ,
231+ 'Failed to extract email from FedCM token' ,
232+ ) ;
229233
230234 await submitComponentEvent (
231235 {
0 commit comments