From 73128d776604035fbb7ba21a0692d937cbc2b06d Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Thu, 12 Dec 2019 12:07:21 +0100 Subject: [PATCH] Drop deprecated v1 prefixed routes. --- .../server/routes/authentication/common.ts | 95 +++---- .../server/routes/authentication/oidc.ts | 257 +++++++----------- 2 files changed, 135 insertions(+), 217 deletions(-) diff --git a/x-pack/plugins/security/server/routes/authentication/common.ts b/x-pack/plugins/security/server/routes/authentication/common.ts index cb4ec196459ee..420b57b89d2aa 100644 --- a/x-pack/plugins/security/server/routes/authentication/common.ts +++ b/x-pack/plugins/security/server/routes/authentication/common.ts @@ -13,66 +13,47 @@ import { RouteDefinitionParams } from '..'; /** * Defines routes that are common to various authentication mechanisms. */ -export function defineCommonRoutes({ router, authc, basePath, logger }: 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/logout', '/api/security/v1/logout']) { - router.get( - { - path, - // 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 parameters). - validate: { query: schema.object({}, { allowUnknowns: true }) }, - options: { authRequired: false }, - }, - async (context, request, response) => { - const serverBasePath = basePath.serverBasePath; - if (path === '/api/security/v1/logout') { - logger.warn( - `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/logout" URL instead.`, - { tags: ['deprecation'] } - ); - } +export function defineCommonRoutes({ router, authc, basePath }: RouteDefinitionParams) { + router.get( + { + path: '/api/security/logout', + // 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 parameters). + validate: { query: schema.object({}, { allowUnknowns: true }) }, + options: { authRequired: false }, + }, + async (context, request, response) => { + 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 authc.logout(request); + if (deauthenticationResult.failed()) { + return response.customError(wrapIntoCustomErrorResponse(deauthenticationResult.error)); } - try { - const deauthenticationResult = await authc.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 || `${basePath.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 (const path of ['/internal/security/me', '/api/security/v1/me']) { - router.get( - { path, validate: false }, - createLicensedRouteHandler(async (context, request, response) => { - if (path === '/api/security/v1/me') { - logger.warn( - `The "${basePath.serverBasePath}${path}" endpoint is deprecated and will be removed in the next major version.`, - { tags: ['deprecation'] } - ); - } - - try { - return response.ok({ body: (await authc.getCurrentUser(request)) as any }); - } catch (error) { - return response.customError(wrapIntoCustomErrorResponse(error)); - } - }) - ); - } + router.get( + { path: '/internal/security/me', validate: false }, + createLicensedRouteHandler(async (context, request, response) => { + try { + return response.ok({ body: (await authc.getCurrentUser(request)) as any }); + } catch (error) { + return response.customError(wrapIntoCustomErrorResponse(error)); + } + }) + ); } diff --git a/x-pack/plugins/security/server/routes/authentication/oidc.ts b/x-pack/plugins/security/server/routes/authentication/oidc.ts index 232fdd26f7838..5c942c1da9584 100644 --- a/x-pack/plugins/security/server/routes/authentication/oidc.ts +++ b/x-pack/plugins/security/server/routes/authentication/oidc.ts @@ -17,43 +17,33 @@ import { RouteDefinitionParams } from '..'; /** * Defines routes required for SAML authentication. */ -export function defineOIDCRoutes({ router, logger, authc, csp, basePath }: 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']) { - /** - * 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. - */ - router.get( - { - path, - validate: false, - options: { authRequired: false }, - }, - (context, request, response) => { - const serverBasePath = basePath.serverBasePath; - if (path === '/api/security/v1/oidc/implicit') { - logger.warn( - `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/implicit" URL instead.`, - { tags: ['deprecation'] } - ); - } - return response.custom( - createCustomResourceResponse( - ` +export function defineOIDCRoutes({ router, authc, csp, basePath }: RouteDefinitionParams) { + /** + * 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. + */ + router.get( + { + path: '/api/security/oidc/implicit', + validate: false, + options: { authRequired: false }, + }, + (context, request, response) => { + return response.custom( + createCustomResourceResponse( + ` Kibana OpenID Connect Login - + `, - 'text/html', - csp.header - ) - ); - } - ); - } + 'text/html', + csp.header + ) + ); + } + ); /** * The route that accompanies `/api/security/oidc/implicit` and renders a JavaScript snippet @@ -82,146 +72,93 @@ export function defineOIDCRoutes({ router, logger, authc, csp, basePath }: Route } ); - // 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']) { - router.get( - { - path, - 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. - { allowUnknowns: true } - ), - }, - options: { authRequired: false }, + router.get( + { + path: '/api/security/oidc/callback', + 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()), + 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. + { allowUnknowns: true } + ), }, - 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 = { - flow: OIDCAuthenticationFlow.Implicit, - authenticationResponseURI: request.query.authenticationResponseURI, - }; - } else if (request.query.code || request.query.error) { - if (path === '/api/security/v1/oidc') { - logger.warn( - `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please 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 = { - flow: OIDCAuthenticationFlow.AuthorizationCode, - // 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.path!, - }; - } else if (request.query.iss) { - logger.warn( - `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please 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 = { - flow: OIDCAuthenticationFlow.InitiatedBy3rdParty, - iss: request.query.iss, - loginHint: request.query.login_hint, - }; - } + options: { authRequired: false }, + }, + 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 = { + flow: OIDCAuthenticationFlow.Implicit, + 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 = { + flow: OIDCAuthenticationFlow.AuthorizationCode, + // 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.path!, + }; + } - 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']) { - /** - * 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( + const initiateLoginRouteParameters = { + path: '/api/security/oidc/initiate_login', + validate: schema.object( { - path, - 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. - { allowUnknowns: true } - ), - }, - options: { authRequired: false }, + iss: schema.uri({ scheme: ['https'] }), + login_hint: schema.maybe(schema.string()), + target_link_uri: schema.maybe(schema.uri()), }, - createLicensedRouteHandler(async (context, request, response) => { - const serverBasePath = basePath.serverBasePath; - if (path === '/api/security/v1/oidc') { - logger.warn( - `The "${serverBasePath}${path}" URL is deprecated and will stop working in the next major version, please use "${serverBasePath}/api/security/oidc/initiate_login" URL for Third-Party Initiated login instead.`, - { tags: ['deprecation'] } - ); - } + // 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. + { allowUnknowns: true } + ), + options: { authRequired: false }, + }; - return performOIDCLogin(request, response, { - flow: OIDCAuthenticationFlow.InitiatedBy3rdParty, - iss: request.body.iss, - loginHint: request.body.login_hint, - }); - }) - ); - } + /** + * 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( + { ...initiateLoginRouteParameters, validate: { body: initiateLoginRouteParameters.validate } }, + createLicensedRouteHandler(async (context, request, response) => { + return performOIDCLogin(request, response, { + flow: OIDCAuthenticationFlow.InitiatedBy3rdParty, + 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. * See more details at https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin */ router.get( - { - path: '/api/security/oidc/initiate_login', - validate: { - query: 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. - { allowUnknowns: true } - ), - }, - options: { authRequired: false }, - }, + { ...initiateLoginRouteParameters, validate: { query: initiateLoginRouteParameters.validate } }, createLicensedRouteHandler(async (context, request, response) => { return performOIDCLogin(request, response, { flow: OIDCAuthenticationFlow.InitiatedBy3rdParty,