diff --git a/x-pack/plugins/security/public/authentication/login/login_page.tsx b/x-pack/plugins/security/public/authentication/login/login_page.tsx index 40438ac1c78f36..e65eb2b0d01822 100644 --- a/x-pack/plugins/security/public/authentication/login/login_page.tsx +++ b/x-pack/plugins/security/public/authentication/login/login_page.tsx @@ -46,6 +46,15 @@ const messageMap = new Map([ }), }, ], + [ + 'AUTHENTICATION_ERROR', + { + type: LoginFormMessageType.Info, + content: i18n.translate('xpack.security.login.authenticationErrorDescription', { + defaultMessage: 'An unexpected authentication error occured. Please log in again.', + }), + }, + ], [ 'LOGGED_OUT', { @@ -77,7 +86,7 @@ export class LoginPage extends Component { try { this.setState({ loginState: await this.props.http.get('/internal/security/login_state') }); } catch (err) { - this.props.fatalErrors.add(err); + this.props.fatalErrors.add(err as Error); } loadingCount$.next(0); diff --git a/x-pack/plugins/security/public/session/session_expired.test.ts b/x-pack/plugins/security/public/session/session_expired.test.ts index 40059722cee876..d3ac2e6e4581a2 100644 --- a/x-pack/plugins/security/public/session/session_expired.test.ts +++ b/x-pack/plugins/security/public/session/session_expired.test.ts @@ -49,6 +49,16 @@ describe('#logout', () => { ); }); + it(`redirects user to the logout URL with custom reason 'msg'`, async () => { + const sessionExpired = new SessionExpired(LOGOUT_URL, TENANT); + sessionExpired.logout('CUSTOM_REASON'); + + const next = `&next=${encodeURIComponent(CURRENT_URL)}`; + await expect(window.location.assign).toHaveBeenCalledWith( + `${LOGOUT_URL}?msg=CUSTOM_REASON${next}` + ); + }); + it(`adds 'provider' parameter when sessionStorage contains the provider name for this tenant`, async () => { const providerName = 'basic'; mockGetItem.mockReturnValueOnce(providerName); diff --git a/x-pack/plugins/security/public/session/session_expired.ts b/x-pack/plugins/security/public/session/session_expired.ts index 0bfbde1f31b366..144ded9aa3517e 100644 --- a/x-pack/plugins/security/public/session/session_expired.ts +++ b/x-pack/plugins/security/public/session/session_expired.ts @@ -32,11 +32,11 @@ const getProviderParameter = (tenant: string) => { export class SessionExpired { constructor(private logoutUrl: string, private tenant: string) {} - logout() { + logout(reason = 'SESSION_EXPIRED') { const next = getNextParameter(); const provider = getProviderParameter(this.tenant); window.location.assign( - `${this.logoutUrl}?${LOGOUT_REASON_QUERY_STRING_PARAMETER}=SESSION_EXPIRED${next}${provider}` + `${this.logoutUrl}?${LOGOUT_REASON_QUERY_STRING_PARAMETER}=${reason}${next}${provider}` ); } } diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts index 35bdb911b6ed11..6d955bb5ad89ec 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.test.ts @@ -56,6 +56,7 @@ it(`logs out 401 responses`, async () => { await drainPromiseQueue(); expect(fetchResolved).toBe(false); expect(fetchRejected).toBe(false); + expect(sessionExpired.logout).toHaveBeenCalledWith('AUTHENTICATION_ERROR'); }); it(`ignores anonymous paths`, async () => { diff --git a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts index 43945c8f43c0fc..4f3405b1ebcecd 100644 --- a/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts +++ b/x-pack/plugins/security/public/session/unauthorized_response_http_interceptor.ts @@ -39,7 +39,7 @@ export class UnauthorizedResponseHttpInterceptor implements HttpInterceptor { } if (response.status === 401) { - this.sessionExpired.logout(); + this.sessionExpired.logout('AUTHENTICATION_ERROR'); controller.halt(); } }