@@ -22,24 +22,54 @@ type LinkedInType = {
2222 redirectUri : string ;
2323 clientId : string ;
2424 onSuccess : ( code : string ) => void ;
25- onFailure ?: ( {
25+ onError ?: ( {
2626 error,
2727 errorMessage,
2828 } : {
2929 error : string ;
3030 errorMessage : string ;
3131 } ) => void ;
3232 scope ?: string ;
33+ closePopupMessage ?: string ;
3334} ;
3435
3536export function useLinkedIn ( {
3637 redirectUri,
3738 clientId,
3839 onSuccess,
39- onFailure ,
40+ onError ,
4041 scope = 'r_emailaddress' ,
42+ closePopupMessage = 'User closed the popup' ,
4143} : LinkedInType ) {
4244 const popupRef = useRef < Window > ( null ) ;
45+ const popUpIntervalRef = useRef < number > ( null ) ;
46+
47+ const receiveMessage = useCallback (
48+ ( event : MessageEvent ) => {
49+ const state = localStorage . getItem ( LINKEDIN_OAUTH2_STATE ) ;
50+ if ( event . origin === window . location . origin ) {
51+ if ( event . data . errorMessage && event . data . from === 'Linked In' ) {
52+ // Prevent CSRF attack by testing state
53+ if ( event . data . state !== state ) {
54+ popupRef . current && popupRef . current . close ( ) ;
55+ return ;
56+ }
57+ onError && onError ( event . data ) ;
58+ popupRef . current && popupRef . current . close ( ) ;
59+ } else if ( event . data . code && event . data . from === 'Linked In' ) {
60+ // Prevent CSRF attack by testing state
61+ if ( event . data . state !== state ) {
62+ console . error ( 'State does not match' ) ;
63+ popupRef . current && popupRef . current . close ( ) ;
64+ return ;
65+ }
66+ onSuccess && onSuccess ( event . data . code ) ;
67+ popupRef . current && popupRef . current . close ( ) ;
68+ }
69+ }
70+ } ,
71+ [ onError , onSuccess ] ,
72+ ) ;
4373
4474 useEffect ( ( ) => {
4575 return ( ) => {
@@ -49,8 +79,19 @@ export function useLinkedIn({
4979 popupRef . current . close ( ) ;
5080 popupRef . current = null ;
5181 }
82+ if ( popUpIntervalRef . current ) {
83+ window . clearInterval ( popUpIntervalRef . current ) ;
84+ popUpIntervalRef . current = null ;
85+ }
86+ } ;
87+ } , [ receiveMessage ] ) ;
88+
89+ useEffect ( ( ) => {
90+ window . addEventListener ( 'message' , receiveMessage , false ) ;
91+ return ( ) => {
92+ window . removeEventListener ( 'message' , receiveMessage , false ) ;
5293 } ;
53- } , [ ] ) ;
94+ } , [ receiveMessage ] ) ;
5495
5596 const getUrl = ( ) => {
5697 const scopeParam = `&scope=${ encodeURI ( scope ) } ` ;
@@ -61,38 +102,36 @@ export function useLinkedIn({
61102 } ;
62103
63104 const linkedInLogin = ( ) => {
64- window . removeEventListener ( 'message' , receiveMessage , false ) ;
105+ popupRef . current ?. close ( ) ;
65106 popupRef . current = window . open (
66107 getUrl ( ) ,
67108 '_blank' ,
68109 getPopupPositionProperties ( { width : 600 , height : 600 } ) ,
69110 ) ;
70- window . addEventListener ( 'message' , receiveMessage , false ) ;
71- } ;
72111
73- const receiveMessage = useCallback ( ( event : MessageEvent ) => {
74- const state = localStorage . getItem ( LINKEDIN_OAUTH2_STATE ) ;
75- if ( event . origin === window . location . origin ) {
76- if ( event . data . errorMessage && event . data . from === 'Linked In' ) {
77- // Prevent CSRF attack by testing state
78- if ( event . data . state !== state ) {
79- popupRef . current && popupRef . current . close ( ) ;
80- return ;
81- }
82- onFailure ( event . data ) ;
83- popupRef . current && popupRef . current . close ( ) ;
84- } else if ( event . data . code && event . data . from === 'Linked In' ) {
85- // Prevent CSRF attack by testing state
86- if ( event . data . state !== state ) {
87- console . error ( 'State does not match' ) ;
88- popupRef . current && popupRef . current . close ( ) ;
89- return ;
112+ if ( popUpIntervalRef . current ) {
113+ window . clearInterval ( popUpIntervalRef . current ) ;
114+ popUpIntervalRef . current = null ;
115+ }
116+ popUpIntervalRef . current = window . setInterval ( ( ) => {
117+ try {
118+ if ( popupRef . current && popupRef . current . closed ) {
119+ window . clearInterval ( popUpIntervalRef . current ) ;
120+ popUpIntervalRef . current = null ;
121+ if ( onError ) {
122+ onError ( {
123+ error : 'user_closed_popup' ,
124+ errorMessage : closePopupMessage ,
125+ } ) ;
126+ }
90127 }
91- onSuccess ( event . data . code ) ;
92- popupRef . current && popupRef . current . close ( ) ;
128+ } catch ( error ) {
129+ console . error ( error ) ;
130+ window . clearInterval ( popUpIntervalRef . current ) ;
131+ popUpIntervalRef . current = null ;
93132 }
94- }
95- } , [ ] ) ;
133+ } , 1000 ) ;
134+ } ;
96135
97136 return {
98137 linkedInLogin,
0 commit comments