@@ -5,15 +5,21 @@ import {
55 createKeysForAuthStorage ,
66} from 'aws-amplify/adapter-core' ;
77
8- import { IS_SIGNING_OUT_COOKIE_NAME } from '../../../src/auth/constant' ;
8+ import {
9+ IS_SIGNING_OUT_COOKIE_NAME ,
10+ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
11+ } from '../../../src/auth/constant' ;
912import { handleSignOutCallbackRequest } from '../../../src/auth/handlers/handleSignOutCallbackRequest' ;
1013import { CreateAuthRoutesHandlersInput } from '../../../src/auth/types' ;
1114import {
1215 appendSetCookieHeaders ,
16+ createAuthFlowProofCookiesRemoveOptions ,
17+ createRedirectionIntermediary ,
1318 createTokenCookiesRemoveOptions ,
1419 createTokenRemoveCookies ,
1520 getCookieValuesFromRequest ,
1621 getRedirectOrDefault ,
22+ resolveRedirectSignOutUrl ,
1723 revokeAuthNTokens ,
1824} from '../../../src/auth/utils' ;
1925
@@ -32,6 +38,13 @@ const mockGetCookieValuesFromRequest = jest.mocked(getCookieValuesFromRequest);
3238const mockRevokeAuthNTokens = jest . mocked ( revokeAuthNTokens ) ;
3339const mockCreateKeysForAuthStorage = jest . mocked ( createKeysForAuthStorage ) ;
3440const mockGetRedirectOrDefault = jest . mocked ( getRedirectOrDefault ) ;
41+ const mockCreateAuthFlowProofCookiesRemoveOptions = jest . mocked (
42+ createAuthFlowProofCookiesRemoveOptions ,
43+ ) ;
44+ const mockCreateRedirectionIntermediary = jest . mocked (
45+ createRedirectionIntermediary ,
46+ ) ;
47+ const mockResolveRedirectSignOutUrl = jest . mocked ( resolveRedirectSignOutUrl ) ;
3548
3649describe ( 'handleSignOutCallbackRequest' , ( ) => {
3750 const mockRequest = new Request (
@@ -57,6 +70,9 @@ describe('handleSignOutCallbackRequest', () => {
5770 mockGetCookieValuesFromRequest . mockClear ( ) ;
5871 mockRevokeAuthNTokens . mockClear ( ) ;
5972 mockGetRedirectOrDefault . mockClear ( ) ;
73+ mockCreateAuthFlowProofCookiesRemoveOptions . mockClear ( ) ;
74+ mockCreateRedirectionIntermediary . mockClear ( ) ;
75+ mockResolveRedirectSignOutUrl . mockClear ( ) ;
6076 } ) ;
6177
6278 it ( `returns a 400 response when the request does not have the "${ IS_SIGNING_OUT_COOKIE_NAME } " cookie` , async ( ) => {
@@ -68,6 +84,7 @@ describe('handleSignOutCallbackRequest', () => {
6884 userPoolClientId : mockUserPoolClientId ,
6985 oAuthConfig : mockOAuthConfig ,
7086 setCookieOptions : mockSetCookieOptions ,
87+ origin : 'https://example.com' ,
7188 } ) ;
7289
7390 // verify the response
@@ -76,9 +93,88 @@ describe('handleSignOutCallbackRequest', () => {
7693 // verify the calls to dependencies
7794 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
7895 IS_SIGNING_OUT_COOKIE_NAME ,
96+ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
7997 ] ) ;
8098 } ) ;
8199
100+ it ( `returns a 200 response with the intermediate redirect HTML when the request has the "${ IS_SIGNING_OUT_COOKIE_NAME } " and "${ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME } " cookies` , async ( ) => {
101+ mockGetCookieValuesFromRequest . mockReturnValueOnce ( {
102+ [ IS_SIGNING_OUT_COOKIE_NAME ] : 'true' ,
103+ [ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ] : 'true' ,
104+ } ) ;
105+ const mockCreateTokenRemoveCookiesResult = [
106+ {
107+ name : IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
108+ value : '' ,
109+ } ,
110+ ] ;
111+ mockCreateTokenRemoveCookies . mockReturnValueOnce (
112+ mockCreateTokenRemoveCookiesResult ,
113+ ) ;
114+ const mockCreateTokenCookiesRemoveOptionsResult = {
115+ path : '/' ,
116+ maxAge : - 1 ,
117+ domain : mockSetCookieOptions . domain ,
118+ } ;
119+ mockCreateAuthFlowProofCookiesRemoveOptions . mockReturnValueOnce (
120+ mockCreateTokenCookiesRemoveOptionsResult ,
121+ ) ;
122+ const mockResolveRedirectSignOutUrlResult =
123+ 'https://example.com/sign-out-callback' ;
124+ mockResolveRedirectSignOutUrl . mockReturnValueOnce (
125+ mockResolveRedirectSignOutUrlResult ,
126+ ) ;
127+ const mockCreateOnSignInCompleteRedirectIntermediateResult =
128+ '<html><head><meta http-equiv="refresh" content="0;url=/"></head></html>' ;
129+ mockCreateRedirectionIntermediary . mockReturnValueOnce (
130+ mockCreateOnSignInCompleteRedirectIntermediateResult ,
131+ ) ;
132+ mockAppendSetCookieHeaders . mockImplementationOnce ( headers => {
133+ headers . append (
134+ 'Set-Cookie' ,
135+ 'mock_cookie1=; Domain=.example.com; Path=/' ,
136+ ) ;
137+ headers . append (
138+ 'Set-Cookie' ,
139+ 'mock_cookie2=; Domain=.example.com; Path=/' ,
140+ ) ;
141+ } ) ;
142+
143+ const response = await handleSignOutCallbackRequest ( {
144+ request : mockRequest ,
145+ handlerInput : mockHandlerInput ,
146+ userPoolClientId : mockUserPoolClientId ,
147+ oAuthConfig : mockOAuthConfig ,
148+ setCookieOptions : mockSetCookieOptions ,
149+ origin : 'https://example.com' ,
150+ } ) ;
151+
152+ // verify the response
153+ expect ( response . status ) . toBe ( 200 ) ;
154+ expect ( response . headers . get ( 'Content-Type' ) ) . toBe ( 'text/html' ) ;
155+ expect ( response . headers . get ( 'Set-Cookie' ) ) . toBe (
156+ 'mock_cookie1=; Domain=.example.com; Path=/, mock_cookie2=; Domain=.example.com; Path=/' ,
157+ ) ;
158+ expect ( await response . text ( ) ) . toBe (
159+ mockCreateOnSignInCompleteRedirectIntermediateResult ,
160+ ) ;
161+
162+ // verify the calls to dependencies
163+ expect ( mockCreateTokenRemoveCookies ) . toHaveBeenCalledWith ( [
164+ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
165+ ] ) ;
166+ expect ( mockCreateAuthFlowProofCookiesRemoveOptions ) . toHaveBeenCalledWith (
167+ mockSetCookieOptions ,
168+ ) ;
169+ expect ( mockResolveRedirectSignOutUrl ) . toHaveBeenCalledWith (
170+ 'https://example.com' ,
171+ mockOAuthConfig ,
172+ ) ;
173+ expect ( mockCreateRedirectionIntermediary ) . toHaveBeenCalledWith ( {
174+ redirectTo : mockResolveRedirectSignOutUrlResult ,
175+ } ) ;
176+ } ) ;
177+
82178 it ( 'returns a 302 response to redirect to handlerInput.redirectOnSignOutComplete when the request cookies do not have a username' , async ( ) => {
83179 mockGetCookieValuesFromRequest
84180 . mockReturnValueOnce ( {
@@ -92,6 +188,7 @@ describe('handleSignOutCallbackRequest', () => {
92188 userPoolClientId : mockUserPoolClientId ,
93189 oAuthConfig : mockOAuthConfig ,
94190 setCookieOptions : mockSetCookieOptions ,
191+ origin : 'https://example.com' ,
95192 } ) ;
96193
97194 // verify the response
@@ -101,6 +198,7 @@ describe('handleSignOutCallbackRequest', () => {
101198 // verify the calls to dependencies
102199 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
103200 IS_SIGNING_OUT_COOKIE_NAME ,
201+ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
104202 ] ) ;
105203 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
106204 `${ AUTH_KEY_PREFIX } .${ mockUserPoolClientId } .LastAuthUser` ,
@@ -126,6 +224,7 @@ describe('handleSignOutCallbackRequest', () => {
126224 userPoolClientId : mockUserPoolClientId ,
127225 oAuthConfig : mockOAuthConfig ,
128226 setCookieOptions : mockSetCookieOptions ,
227+ origin : 'https://example.com' ,
129228 } ) ;
130229
131230 // verify the response
@@ -136,6 +235,7 @@ describe('handleSignOutCallbackRequest', () => {
136235 // verify the calls to dependencies
137236 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
138237 IS_SIGNING_OUT_COOKIE_NAME ,
238+ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
139239 ] ) ;
140240 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
141241 `${ AUTH_KEY_PREFIX } .${ mockUserPoolClientId } .LastAuthUser` ,
@@ -167,6 +267,7 @@ describe('handleSignOutCallbackRequest', () => {
167267 userPoolClientId : mockUserPoolClientId ,
168268 oAuthConfig : mockOAuthConfig ,
169269 setCookieOptions : mockSetCookieOptions ,
270+ origin : 'https://example.com' ,
170271 } ) ;
171272
172273 // verify the response
@@ -176,6 +277,7 @@ describe('handleSignOutCallbackRequest', () => {
176277 // verify the calls to dependencies
177278 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
178279 IS_SIGNING_OUT_COOKIE_NAME ,
280+ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
179281 ] ) ;
180282 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
181283 `${ AUTH_KEY_PREFIX } .${ mockUserPoolClientId } .LastAuthUser` ,
@@ -257,6 +359,7 @@ describe('handleSignOutCallbackRequest', () => {
257359 userPoolClientId : mockUserPoolClientId ,
258360 oAuthConfig : mockOAuthConfig ,
259361 setCookieOptions : mockSetCookieOptions ,
362+ origin : 'https://example.com' ,
260363 } ) ;
261364
262365 // verify the calls to dependencies
@@ -269,6 +372,7 @@ describe('handleSignOutCallbackRequest', () => {
269372 // verify the calls to dependencies
270373 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
271374 IS_SIGNING_OUT_COOKIE_NAME ,
375+ IS_SIGNING_OUT_REDIRECTING_COOKIE_NAME ,
272376 ] ) ;
273377 expect ( mockGetCookieValuesFromRequest ) . toHaveBeenCalledWith ( mockRequest , [
274378 `${ AUTH_KEY_PREFIX } .${ mockUserPoolClientId } .LastAuthUser` ,
0 commit comments