diff --git a/x-pack/plugins/security/server/authentication/providers/saml.test.ts b/x-pack/plugins/security/server/authentication/providers/saml.test.ts index 1fc49d5d344840..7ef1d934a7d130 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.test.ts @@ -423,6 +423,44 @@ describe('SAMLAuthenticationProvider', () => { }); }); + it('prepends redirect URL fragment with `#` if it does not have one.', async () => { + const request = httpServerMock.createKibanaRequest(); + + mockOptions.client.callAsInternalUser.withArgs('shield.samlPrepare').resolves({ + id: 'some-request-id', + redirect: 'https://idp-host/path/login?SAMLRequest=some%20request%20', + }); + + const authenticationResult = await provider.login( + request, + { + step: SAMLLoginStep.RedirectURLFragmentCaptured, + redirectURLFragment: '../some-fragment', + }, + { redirectURL: '/test-base-path/some-path' } + ); + + sinon.assert.calledWithExactly( + mockOptions.client.callAsInternalUser, + 'shield.samlPrepare', + { body: { realm: 'test-realm' } } + ); + + expect(mockOptions.logger.warn).toHaveBeenCalledTimes(1); + expect(mockOptions.logger.warn).toHaveBeenCalledWith( + 'Redirect URL fragment does not start with `#`.' + ); + + expect(authenticationResult.redirected()).toBe(true); + expect(authenticationResult.redirectURL).toBe( + 'https://idp-host/path/login?SAMLRequest=some%20request%20' + ); + expect(authenticationResult.state).toEqual({ + requestId: 'some-request-id', + redirectURL: '/test-base-path/some-path#../some-fragment', + }); + }); + it('redirects non-AJAX requests to the IdP remembering only redirect URL path if fragment is too large.', async () => { const request = httpServerMock.createKibanaRequest(); diff --git a/x-pack/plugins/security/server/authentication/providers/saml.ts b/x-pack/plugins/security/server/authentication/providers/saml.ts index 712ddf3fb62109..b21a23718f8612 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.ts @@ -114,7 +114,13 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { return AuthenticationResult.failed(Boom.badRequest(message)); } - let redirectURL = `${state.redirectURL}${attempt.redirectURLFragment}`; + let redirectURLFragment = attempt.redirectURLFragment; + if (redirectURLFragment.length > 0 && !redirectURLFragment.startsWith('#')) { + this.logger.warn('Redirect URL fragment does not start with `#`.'); + redirectURLFragment = `#${redirectURLFragment}`; + } + + let redirectURL = `${state.redirectURL}${redirectURLFragment}`; const redirectURLSize = new ByteSizeValue(Buffer.byteLength(redirectURL)); if (this.maxRedirectURLSize.isLessThan(redirectURLSize)) { this.logger.warn(