diff --git a/x-pack/plugins/security/server/authentication/authentication_service.ts b/x-pack/plugins/security/server/authentication/authentication_service.ts
index cf99084d4d0b..5498175cfd93 100644
--- a/x-pack/plugins/security/server/authentication/authentication_service.ts
+++ b/x-pack/plugins/security/server/authentication/authentication_service.ts
@@ -194,9 +194,7 @@ export class AuthenticationService {
}
const isAuthRoute = request.route.options.tags.includes(ROUTE_TAG_AUTH_FLOW);
- const isLogoutRoute =
- request.route.path === '/api/security/logout' ||
- request.route.path === '/api/v1/security/logout';
+ const isLogoutRoute = request.route.path === '/api/security/logout';
// If users can eventually re-login we want to redirect them directly to the page they tried
// to access initially, but we only want to do that for routes that aren't part of the various
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 15ff615af9ad..1674ea347986 100644
--- a/x-pack/plugins/security/server/authentication/providers/saml.test.ts
+++ b/x-pack/plugins/security/server/authentication/providers/saml.test.ts
@@ -788,7 +788,7 @@ describe('SAMLAuthenticationProvider', () => {
method: 'POST',
path: '/_security/saml/prepare',
body: {
- acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/v1/saml',
+ acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/saml/callback',
},
});
@@ -830,7 +830,7 @@ describe('SAMLAuthenticationProvider', () => {
method: 'POST',
path: '/_security/saml/prepare',
body: {
- acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/v1/saml',
+ acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/saml/callback',
},
});
@@ -900,7 +900,7 @@ describe('SAMLAuthenticationProvider', () => {
method: 'POST',
path: '/_security/saml/prepare',
body: {
- acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/v1/saml',
+ acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/saml/callback',
},
});
});
@@ -1003,7 +1003,7 @@ describe('SAMLAuthenticationProvider', () => {
method: 'POST',
path: '/_security/saml/prepare',
body: {
- acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/v1/saml',
+ acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/saml/callback',
},
});
});
@@ -1294,7 +1294,7 @@ describe('SAMLAuthenticationProvider', () => {
path: '/_security/saml/invalidate',
body: {
query_string: 'SAMLRequest=xxx%20yyy',
- acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/v1/saml',
+ acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/saml/callback',
},
});
});
@@ -1408,7 +1408,7 @@ describe('SAMLAuthenticationProvider', () => {
path: '/_security/saml/invalidate',
body: {
query_string: 'SAMLRequest=xxx%20yyy',
- acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/v1/saml',
+ acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/saml/callback',
},
});
});
@@ -1430,7 +1430,7 @@ describe('SAMLAuthenticationProvider', () => {
path: '/_security/saml/invalidate',
body: {
query_string: 'SAMLRequest=xxx%20yyy',
- acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/v1/saml',
+ acs: 'test-protocol://test-hostname:1234/mock-server-basepath/api/security/saml/callback',
},
});
});
diff --git a/x-pack/plugins/security/server/authentication/providers/saml.ts b/x-pack/plugins/security/server/authentication/providers/saml.ts
index 56dbd78b2ef3..5f8545003d04 100644
--- a/x-pack/plugins/security/server/authentication/providers/saml.ts
+++ b/x-pack/plugins/security/server/authentication/providers/saml.ts
@@ -659,7 +659,7 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider {
private getACS() {
return `${this.options.getServerBaseURL()}${
this.options.basePath.serverBasePath
- }/api/security/v1/saml`;
+ }/api/security/saml/callback`;
}
/**
diff --git a/x-pack/plugins/security/server/routes/authentication/common.ts b/x-pack/plugins/security/server/routes/authentication/common.ts
index 4ee2e57a3351..0b182f706ada 100644
--- a/x-pack/plugins/security/server/routes/authentication/common.ts
+++ b/x-pack/plugins/security/server/routes/authentication/common.ts
@@ -7,7 +7,6 @@
import type { TypeOf } from '@kbn/config-schema';
import { schema } from '@kbn/config-schema';
-import { i18n } from '@kbn/i18n';
import { parseNextURL } from '@kbn/std';
import type { RouteDefinitionParams } from '..';
@@ -36,124 +35,67 @@ export function defineCommonRoutes({
buildFlavor,
docLinks,
}: RouteDefinitionParams) {
- // Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
- // For a serverless build, do not register deprecated versioned routes
- for (const path of [
- '/api/security/logout',
- ...(buildFlavor !== 'serverless' ? ['/api/security/v1/logout'] : []),
- ]) {
- const isDeprecated = path === '/api/security/v1/logout';
- router.get(
- {
- path,
- security: {
- authz: {
- enabled: false,
- reason: 'This route must remain accessible to 3rd-party IdPs',
- },
- },
- // Allow unknown query parameters as this endpoint can be hit by the 3rd-party with any
- // set of query string parameters (e.g. SAML/OIDC logout request/response parameters).
- validate: { query: schema.object({}, { unknowns: 'allow' }) },
- options: {
- access: 'public',
- excludeFromOAS: true,
- authRequired: false,
- tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
- ...(isDeprecated && {
- deprecated: {
- documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
- severity: 'warning',
- message: i18n.translate('xpack.security.deprecations.logoutRouteMessage', {
- defaultMessage:
- 'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/logout" instead.',
- values: { path },
- }),
- reason: {
- type: 'migrate',
- newApiMethod: 'GET',
- newApiPath: '/api/security/logout',
- },
- },
- }),
+ router.get(
+ {
+ path: '/api/security/logout',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'This route must remain accessible to 3rd-party IdPs',
},
},
- async (context, request, response) => {
- const serverBasePath = basePath.serverBasePath;
- if (isDeprecated) {
- logger.warn(
- `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/logout" URL instead.`,
- { tags: ['deprecation'] }
- );
- }
+ // Allow unknown query parameters as this endpoint can be hit by the 3rd-party with any
+ // set of query string parameters (e.g. SAML/OIDC logout request/response parameters).
+ validate: { query: schema.object({}, { unknowns: 'allow' }) },
+ options: {
+ access: 'public',
+ excludeFromOAS: true,
+ authRequired: false,
+ tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
+ },
+ },
+ async (context, request, response) => {
+ const serverBasePath = basePath.serverBasePath;
+ if (!canRedirectRequest(request)) {
+ return response.badRequest({
+ body: 'Client should be able to process redirect response.',
+ });
+ }
- if (!canRedirectRequest(request)) {
- return response.badRequest({
- body: 'Client should be able to process redirect response.',
- });
+ try {
+ const deauthenticationResult = await getAuthenticationService().logout(request);
+ if (deauthenticationResult.failed()) {
+ return response.customError(wrapIntoCustomErrorResponse(deauthenticationResult.error));
}
- try {
- const deauthenticationResult = await getAuthenticationService().logout(request);
- if (deauthenticationResult.failed()) {
- return response.customError(wrapIntoCustomErrorResponse(deauthenticationResult.error));
- }
-
- return response.redirected({
- headers: { location: deauthenticationResult.redirectURL || `${serverBasePath}/` },
- });
- } catch (error) {
- return response.customError(wrapIntoCustomErrorResponse(error));
- }
+ return response.redirected({
+ headers: { location: deauthenticationResult.redirectURL || `${serverBasePath}/` },
+ });
+ } catch (error) {
+ return response.customError(wrapIntoCustomErrorResponse(error));
}
- );
- }
+ }
+ );
- // Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
- // For a serverless build, do not register deprecated versioned routes
- for (const path of [
- '/internal/security/me',
- ...(buildFlavor !== 'serverless' ? ['/api/security/v1/me'] : []),
- ]) {
- const isDeprecated = path === '/api/security/v1/me';
- router.get(
- {
- path,
- security: {
- authz: {
- enabled: false,
- reason: `This route delegates authorization to Core's security service; there must be an authenticated user for this route to return information`,
- },
- },
- validate: false,
- options: {
- access: isDeprecated ? 'public' : 'internal',
- ...(isDeprecated && {
- deprecated: {
- documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
- severity: 'warning',
- message: i18n.translate('xpack.security.deprecations.meRouteMessage', {
- defaultMessage:
- 'The "{path}" endpoint is deprecated and will be removed in the next major version.',
- values: { path },
- }),
- reason: { type: 'remove' },
- },
- }),
+ router.get(
+ {
+ path: '/internal/security/me',
+ security: {
+ authz: {
+ enabled: false,
+ reason: `This route delegates authorization to Core's security service; there must be an authenticated user for this route to return information`,
},
},
- createLicensedRouteHandler(async (context, request, response) => {
- if (isDeprecated) {
- logger.warn(
- `The "${basePath.serverBasePath}${path}" endpoint is deprecated and will be removed in the next major version.`,
- { tags: ['deprecation'] }
- );
- }
- const { security: coreSecurity } = await context.core;
- return response.ok({ body: coreSecurity.authc.getCurrentUser()! });
- })
- );
- }
+ validate: false,
+ options: {
+ access: 'internal',
+ },
+ },
+ createLicensedRouteHandler(async (context, request, response) => {
+ const { security: coreSecurity } = await context.core;
+ return response.ok({ body: coreSecurity.authc.getCurrentUser()! });
+ })
+ );
const basicParamsSchema = schema.object({
username: schema.string({ minLength: 1 }),
diff --git a/x-pack/plugins/security/server/routes/authentication/oidc.ts b/x-pack/plugins/security/server/routes/authentication/oidc.ts
index d1d31f4c49a6..c3e7673e3a19 100644
--- a/x-pack/plugins/security/server/routes/authentication/oidc.ts
+++ b/x-pack/plugins/security/server/routes/authentication/oidc.ts
@@ -27,58 +27,32 @@ export function defineOIDCRoutes({
basePath,
docLinks,
}: RouteDefinitionParams) {
- // Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
- for (const path of ['/api/security/oidc/implicit', '/api/security/v1/oidc/implicit']) {
- const isDeprecated = path === '/api/security/v1/oidc/implicit';
- /**
- * The route should be configured as a redirect URI in OP when OpenID Connect implicit flow
- * is used, so that we can extract authentication response from URL fragment and send it to
- * the `/api/security/oidc/callback` route.
- */
- httpResources.register(
- {
- path,
- validate: false,
- options: {
- authRequired: false,
- excludeFromOAS: true,
- ...(isDeprecated && {
- deprecated: {
- documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
- severity: 'warning',
- message: i18n.translate('xpack.security.deprecations.oidcImplicitRouteMessage', {
- defaultMessage:
- 'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/implicit" instead.',
- values: { path },
- }),
- reason: {
- type: 'migrate',
- newApiMethod: 'GET',
- newApiPath: '/api/security/oidc/implicit',
- },
- },
- }),
- },
+ /**
+ * The route should be configured as a redirect URI in OP when OpenID Connect implicit flow
+ * is used, so that we can extract authentication response from URL fragment and send it to
+ * the `/api/security/oidc/callback` route.
+ */
+ httpResources.register(
+ {
+ path: '/api/security/oidc/implicit',
+ validate: false,
+ options: {
+ authRequired: false,
+ excludeFromOAS: true,
},
- (context, request, response) => {
- const serverBasePath = basePath.serverBasePath;
- if (isDeprecated) {
- logger.warn(
- `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/implicit" URL instead.`,
- { tags: ['deprecation'] }
- );
- }
- return response.renderHtml({
- body: `
+ },
+ (context, request, response) => {
+ const serverBasePath = basePath.serverBasePath;
+ return response.renderHtml({
+ body: `
Kibana OpenID Connect Login
`,
- });
- }
- );
- }
+ });
+ }
+ );
/**
* The route that accompanies `/api/security/oidc/implicit` and renders a JavaScript snippet
@@ -103,183 +77,122 @@ export function defineOIDCRoutes({
}
);
- // Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
- for (const path of ['/api/security/oidc/callback', '/api/security/v1/oidc']) {
- const isDeprecated = path === '/api/security/v1/oidc';
- router.get(
- {
- path,
- security: {
- authz: {
- enabled: false,
- reason: 'This route must remain accessible to 3rd-party OIDC providers',
- },
- },
- validate: {
- query: schema.object(
- {
- authenticationResponseURI: schema.maybe(schema.uri()),
- code: schema.maybe(schema.string()),
- error: schema.maybe(schema.string()),
- error_description: schema.maybe(schema.string()),
- error_uri: schema.maybe(schema.uri()),
- iss: schema.maybe(schema.uri({ scheme: ['https'] })),
- login_hint: schema.maybe(schema.string()),
- target_link_uri: schema.maybe(schema.uri()),
- state: schema.maybe(schema.string()),
- },
- // The client MUST ignore unrecognized response parameters according to
- // https://openid.net/specs/openid-connect-core-1_0.html#AuthResponseValidation and
- // https://tools.ietf.org/html/rfc6749#section-4.1.2.
- { unknowns: 'allow' }
- ),
- },
- options: {
- access: 'public',
- excludeFromOAS: true,
- authRequired: false,
- tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
- ...(isDeprecated && {
- deprecated: {
- documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
- severity: 'warning',
- message: i18n.translate('xpack.security.deprecations.oidcCallbackRouteMessage', {
- defaultMessage:
- 'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/callback" instead.',
- values: { path },
- }),
- reason: {
- type: 'migrate',
- newApiMethod: 'GET',
- newApiPath: '/api/security/oidc/callback',
- },
- },
- }),
+ router.get(
+ {
+ path: '/api/security/oidc/callback',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'This route must remain accessible to 3rd-party OIDC providers',
},
},
- createLicensedRouteHandler(async (context, request, response) => {
- const serverBasePath = basePath.serverBasePath;
-
- // An HTTP GET request with a query parameter named `authenticationResponseURI` that includes URL fragment OpenID
- // Connect Provider sent during implicit authentication flow to the Kibana own proxy page that extracted that URL
- // fragment and put it into `authenticationResponseURI` query string parameter for this endpoint. See more details
- // at https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth
- let loginAttempt: ProviderLoginAttempt | undefined;
- if (request.query.authenticationResponseURI) {
- loginAttempt = {
- type: OIDCLogin.LoginWithImplicitFlow,
- authenticationResponseURI: request.query.authenticationResponseURI,
- };
- } else if (request.query.code || request.query.error) {
- if (isDeprecated) {
- logger.warn(
- `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/callback" URL instead.`,
- { tags: ['deprecation'] }
- );
- }
-
- // An HTTP GET request with a query parameter named `code` (or `error`) as the response to a successful (or
- // failed) authentication from an OpenID Connect Provider during authorization code authentication flow.
- // See more details at https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth.
- loginAttempt = {
- type: OIDCLogin.LoginWithAuthorizationCodeFlow,
- // We pass the path only as we can't be sure of the full URL and Elasticsearch doesn't need it anyway.
- authenticationResponseURI: request.url.pathname + request.url.search,
- };
- } else if (request.query.iss) {
- logger.warn(
- `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/initiate_login" URL for Third-Party Initiated login instead.`,
- { tags: ['deprecation'] }
- );
- // An HTTP GET request with a query parameter named `iss` as part of a 3rd party initiated authentication.
- // See more details at https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin
- loginAttempt = {
- type: OIDCLogin.LoginInitiatedBy3rdParty,
- iss: request.query.iss,
- loginHint: request.query.login_hint,
- };
- }
+ validate: {
+ query: schema.object(
+ {
+ authenticationResponseURI: schema.maybe(schema.uri()),
+ code: schema.maybe(schema.string()),
+ error: schema.maybe(schema.string()),
+ error_description: schema.maybe(schema.string()),
+ error_uri: schema.maybe(schema.uri()),
+ iss: schema.maybe(schema.uri({ scheme: ['https'] })),
+ login_hint: schema.maybe(schema.string()),
+ target_link_uri: schema.maybe(schema.uri()),
+ state: schema.maybe(schema.string()),
+ },
+ // The client MUST ignore unrecognized response parameters according to
+ // https://openid.net/specs/openid-connect-core-1_0.html#AuthResponseValidation and
+ // https://tools.ietf.org/html/rfc6749#section-4.1.2.
+ { unknowns: 'allow' }
+ ),
+ },
+ options: {
+ access: 'public',
+ excludeFromOAS: true,
+ authRequired: false,
+ tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
+ },
+ },
+ createLicensedRouteHandler(async (context, request, response) => {
+ // An HTTP GET request with a query parameter named `authenticationResponseURI` that includes URL fragment OpenID
+ // Connect Provider sent during implicit authentication flow to the Kibana own proxy page that extracted that URL
+ // fragment and put it into `authenticationResponseURI` query string parameter for this endpoint. See more details
+ // at https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth
+ let loginAttempt: ProviderLoginAttempt | undefined;
+ if (request.query.authenticationResponseURI) {
+ loginAttempt = {
+ type: OIDCLogin.LoginWithImplicitFlow,
+ authenticationResponseURI: request.query.authenticationResponseURI,
+ };
+ } else if (request.query.code || request.query.error) {
+ // An HTTP GET request with a query parameter named `code` (or `error`) as the response to a successful (or
+ // failed) authentication from an OpenID Connect Provider during authorization code authentication flow.
+ // See more details at https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth.
+ loginAttempt = {
+ type: OIDCLogin.LoginWithAuthorizationCodeFlow,
+ // We pass the path only as we can't be sure of the full URL and Elasticsearch doesn't need it anyway.
+ authenticationResponseURI: request.url.pathname + request.url.search,
+ };
+ } else if (request.query.iss) {
+ // An HTTP GET request with a query parameter named `iss` as part of a 3rd party initiated authentication.
+ // See more details at https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin
+ loginAttempt = {
+ type: OIDCLogin.LoginInitiatedBy3rdParty,
+ iss: request.query.iss,
+ loginHint: request.query.login_hint,
+ };
+ }
- if (!loginAttempt) {
- return response.badRequest({
- body: 'Unrecognized login attempt.',
- });
- }
+ if (!loginAttempt) {
+ return response.badRequest({
+ body: 'Unrecognized login attempt.',
+ });
+ }
- return performOIDCLogin(request, response, loginAttempt);
- })
- );
- }
+ return performOIDCLogin(request, response, loginAttempt);
+ })
+ );
- // Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
- for (const path of ['/api/security/oidc/initiate_login', '/api/security/v1/oidc']) {
- const isDeprecated = path === '/api/security/v1/oidc';
- /**
- * An HTTP POST request with the payload parameter named `iss` as part of a 3rd party initiated authentication.
- * See more details at https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin
- */
- router.post(
- {
- path,
- security: {
- authz: {
- enabled: false,
- reason: 'This route must remain accessible to 3rd-party OIDC providers',
- },
- },
- validate: {
- body: schema.object(
- {
- iss: schema.uri({ scheme: ['https'] }),
- login_hint: schema.maybe(schema.string()),
- target_link_uri: schema.maybe(schema.uri()),
- },
- // Other parameters MAY be sent, if defined by extensions. Any parameters used that are not understood MUST
- // be ignored by the Client according to https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin.
- { unknowns: 'allow' }
- ),
- },
- options: {
- access: 'public',
- excludeFromOAS: true,
- authRequired: false,
- xsrfRequired: false,
- tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
- ...(isDeprecated && {
- deprecated: {
- documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
- severity: 'warning',
- message: i18n.translate('xpack.security.deprecations.oidcInitiateRouteMessage', {
- defaultMessage:
- 'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/oidc/initiate_login" instead.',
- values: { path },
- }),
- reason: {
- type: 'migrate',
- newApiMethod: 'POST',
- newApiPath: '/api/security/oidc/initiate_login',
- },
- },
- }),
+ /**
+ * An HTTP POST request with the payload parameter named `iss` as part of a 3rd party initiated authentication.
+ * See more details at https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin
+ */
+ router.post(
+ {
+ path: '/api/security/oidc/initiate_login',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'This route must remain accessible to 3rd-party OIDC providers',
},
},
- createLicensedRouteHandler(async (context, request, response) => {
- const serverBasePath = basePath.serverBasePath;
- if (isDeprecated) {
- logger.warn(
- `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version. Use "${serverBasePath}/api/security/oidc/initiate_login" URL for Third-Party Initiated login instead.`,
- { tags: ['deprecation'] }
- );
- }
-
- return performOIDCLogin(request, response, {
- type: OIDCLogin.LoginInitiatedBy3rdParty,
- iss: request.body.iss,
- loginHint: request.body.login_hint,
- });
- })
- );
- }
+ validate: {
+ body: schema.object(
+ {
+ iss: schema.uri({ scheme: ['https'] }),
+ login_hint: schema.maybe(schema.string()),
+ target_link_uri: schema.maybe(schema.uri()),
+ },
+ // Other parameters MAY be sent, if defined by extensions. Any parameters used that are not understood MUST
+ // be ignored by the Client according to https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin.
+ { unknowns: 'allow' }
+ ),
+ },
+ options: {
+ access: 'public',
+ excludeFromOAS: true,
+ authRequired: false,
+ xsrfRequired: false,
+ tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
+ },
+ },
+ createLicensedRouteHandler(async (context, request, response) => {
+ return performOIDCLogin(request, response, {
+ type: OIDCLogin.LoginInitiatedBy3rdParty,
+ iss: request.body.iss,
+ loginHint: request.body.login_hint,
+ });
+ })
+ );
/**
* An HTTP GET request with the query string parameter named `iss` as part of a 3rd party initiated authentication.
diff --git a/x-pack/plugins/security/server/routes/authentication/saml.test.ts b/x-pack/plugins/security/server/routes/authentication/saml.test.ts
index f693d20354e8..e7aa7bc5cc4b 100644
--- a/x-pack/plugins/security/server/routes/authentication/saml.test.ts
+++ b/x-pack/plugins/security/server/routes/authentication/saml.test.ts
@@ -43,15 +43,6 @@ describe('SAML authentication routes', () => {
routeHandler = acsRouteHandler;
});
- it('additionally registers BWC route', () => {
- expect(
- router.post.mock.calls.find(([{ path }]) => path === '/api/security/saml/callback')
- ).toBeDefined();
- expect(
- router.post.mock.calls.find(([{ path }]) => path === '/api/security/v1/saml')
- ).toBeDefined();
- });
-
it('correctly defines route.', () => {
expect(routeConfig.options).toEqual({
access: 'public',
diff --git a/x-pack/plugins/security/server/routes/authentication/saml.ts b/x-pack/plugins/security/server/routes/authentication/saml.ts
index c45f1eed3aff..8da7ff284a4b 100644
--- a/x-pack/plugins/security/server/routes/authentication/saml.ts
+++ b/x-pack/plugins/security/server/routes/authentication/saml.ts
@@ -6,7 +6,6 @@
*/
import { schema } from '@kbn/config-schema';
-import { i18n } from '@kbn/i18n';
import type { RouteDefinitionParams } from '..';
import { SAMLAuthenticationProvider, SAMLLogin } from '../../authentication';
@@ -23,79 +22,47 @@ export function defineSAMLRoutes({
buildFlavor,
docLinks,
}: RouteDefinitionParams) {
- // Generate two identical routes with new and deprecated URL and issue a warning if route with deprecated URL is ever used.
- // For a serverless build, do not register deprecated versioned routes
- for (const path of [
- '/api/security/saml/callback',
- ...(buildFlavor !== 'serverless' ? ['/api/security/v1/saml'] : []),
- ]) {
- const isDeprecated = path === '/api/security/v1/saml';
- router.post(
- {
- path,
- security: {
- authz: {
- enabled: false,
- reason: 'This route must remain accessible to 3rd-party SAML providers',
- },
- },
- validate: {
- body: schema.object(
- { SAMLResponse: schema.string(), RelayState: schema.maybe(schema.string()) },
- { unknowns: 'ignore' }
- ),
- },
- options: {
- access: 'public',
- excludeFromOAS: true,
- authRequired: false,
- xsrfRequired: false,
- tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
- ...(isDeprecated && {
- deprecated: {
- documentationUrl: docLinks.links.security.deprecatedV1Endpoints,
- severity: 'warning',
- message: i18n.translate('xpack.security.deprecations.samlPostRouteMessage', {
- defaultMessage:
- 'The "{path}" URL is deprecated and will be removed in the next major version. Use "/api/security/saml/callback" instead.',
- values: { path },
- }),
- reason: {
- type: 'migrate',
- newApiMethod: 'POST',
- newApiPath: '/api/security/saml/callback',
- },
- },
- }),
+ router.post(
+ {
+ path: '/api/security/saml/callback',
+ security: {
+ authz: {
+ enabled: false,
+ reason: 'This route must remain accessible to 3rd-party SAML providers',
},
},
- async (context, request, response) => {
- if (isDeprecated) {
- const serverBasePath = basePath.serverBasePath;
- logger.warn(
- // When authenticating using SAML we _expect_ to redirect to the SAML Identity provider.
- `The "${serverBasePath}${path}" URL is deprecated and might stop working in a future release. Use "${serverBasePath}/api/security/saml/callback" URL instead.`
- );
- }
+ validate: {
+ body: schema.object(
+ { SAMLResponse: schema.string(), RelayState: schema.maybe(schema.string()) },
+ { unknowns: 'ignore' }
+ ),
+ },
+ options: {
+ access: 'public',
+ excludeFromOAS: true,
+ authRequired: false,
+ xsrfRequired: false,
+ tags: [ROUTE_TAG_CAN_REDIRECT, ROUTE_TAG_AUTH_FLOW],
+ },
+ },
+ async (context, request, response) => {
+ // When authenticating using SAML we _expect_ to redirect to the Kibana target location.
+ const authenticationResult = await getAuthenticationService().login(request, {
+ provider: { type: SAMLAuthenticationProvider.type },
+ value: {
+ type: SAMLLogin.LoginWithSAMLResponse,
+ samlResponse: request.body.SAMLResponse,
+ relayState: request.body.RelayState,
+ },
+ });
- // When authenticating using SAML we _expect_ to redirect to the Kibana target location.
- const authenticationResult = await getAuthenticationService().login(request, {
- provider: { type: SAMLAuthenticationProvider.type },
- value: {
- type: SAMLLogin.LoginWithSAMLResponse,
- samlResponse: request.body.SAMLResponse,
- relayState: request.body.RelayState,
- },
+ if (authenticationResult.redirected()) {
+ return response.redirected({
+ headers: { location: authenticationResult.redirectURL! },
});
-
- if (authenticationResult.redirected()) {
- return response.redirected({
- headers: { location: authenticationResult.redirectURL! },
- });
- }
-
- return response.unauthorized({ body: authenticationResult.error });
}
- );
- }
+
+ return response.unauthorized({ body: authenticationResult.error });
+ }
+ );
}