diff --git a/common/index.ts b/common/index.ts
index b5e6a475d..1a0eb3ff5 100644
--- a/common/index.ts
+++ b/common/index.ts
@@ -34,6 +34,7 @@ export const OPENID_AUTH_LOGIN_WITH_FRAGMENT = '/auth/openid/captureUrlFragment'
export const SAML_AUTH_LOGIN = '/auth/saml/login';
export const SAML_AUTH_LOGIN_WITH_FRAGMENT = '/auth/saml/captureUrlFragment';
export const ANONYMOUS_AUTH_LOGIN = '/auth/anonymous';
+export const AUTH_TYPE_PARAM = 'auth_type';
export const OPENID_AUTH_LOGOUT = '/auth/openid/logout';
export const SAML_AUTH_LOGOUT = '/auth/saml/logout';
diff --git a/public/apps/login/login-page.tsx b/public/apps/login/login-page.tsx
index a22a36dc7..1e5f43dd8 100644
--- a/public/apps/login/login-page.tsx
+++ b/public/apps/login/login-page.tsx
@@ -231,14 +231,14 @@ export function LoginPage(props: LoginPageDeps) {
);
- if (authOpts.length > 1) {
- if (props.config.auth.anonymous_auth_enabled) {
- const anonymousConfig = props.config.ui[AuthType.ANONYMOUS].login;
- formBody.push(
- renderLoginButton(AuthType.ANONYMOUS, ANONYMOUS_AUTH_LOGIN, anonymousConfig)
- );
- }
+ if (props.config.auth.anonymous_auth_enabled) {
+ const anonymousConfig = props.config.ui[AuthType.ANONYMOUS].login;
+ formBody.push(
+ renderLoginButton(AuthType.ANONYMOUS, ANONYMOUS_AUTH_LOGIN, anonymousConfig)
+ );
+ }
+ if (authOpts.length > 1) {
formBody.push();
formBody.push();
formBody.push();
diff --git a/public/apps/login/test/__snapshots__/login-page.test.tsx.snap b/public/apps/login/test/__snapshots__/login-page.test.tsx.snap
index b8a1e1182..de432dcca 100644
--- a/public/apps/login/test/__snapshots__/login-page.test.tsx.snap
+++ b/public/apps/login/test/__snapshots__/login-page.test.tsx.snap
@@ -153,6 +153,419 @@ exports[`Login page renders renders with config value for multiauth 1`] = `
`;
+exports[`Login page renders renders with config value for multiauth with anonymous auth enabled 1`] = `
+
+
+
+
+ Title1
+
+
+
+ SubTitle1
+
+
+
+
+
+ }
+ value=""
+ />
+
+
+
+ }
+ type="password"
+ value=""
+ />
+
+
+
+ Log in
+
+
+
+
+
+
+
+
+
+
+ Button1
+
+
+
+
+ Button2
+
+
+
+
+`;
+
+exports[`Login page renders renders with config value with anonymous auth enabled: string 1`] = `
+
+
+
+
+ Title1
+
+
+
+ SubTitle1
+
+
+
+
+
+ }
+ value=""
+ />
+
+
+
+ }
+ type="password"
+ value=""
+ />
+
+
+
+ Log in
+
+
+
+
+
+
+
+`;
+
+exports[`Login page renders renders with config value with anonymous auth enabled: string array 1`] = `
+
+
+
+
+ Title1
+
+
+
+ SubTitle1
+
+
+
+
+
+ }
+ value=""
+ />
+
+
+
+ }
+ type="password"
+ value=""
+ />
+
+
+
+ Log in
+
+
+
+
+
+
+
+`;
+
exports[`Login page renders renders with config value: string 1`] = `
{
expect(component).toMatchSnapshot();
});
+ it('renders with config value with anonymous auth enabled: string array', () => {
+ const config: ClientConfigType = {
+ ui: configUI,
+ auth: {
+ type: [AuthType.BASIC],
+ logout_url: API_AUTH_LOGOUT,
+ anonymous_auth_enabled: true,
+ },
+ };
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+
it('renders with config value: string', () => {
const config: ClientConfigType = {
ui: configUI,
@@ -166,12 +190,42 @@ describe('Login page', () => {
expect(component).toMatchSnapshot();
});
+ it('renders with config value with anonymous auth enabled: string', () => {
+ const config: ClientConfigType = {
+ ui: configUI,
+ auth: {
+ type: AuthType.BASIC,
+ logout_url: API_AUTH_LOGOUT,
+ anonymous_auth_enabled: true,
+ },
+ };
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+
it('renders with config value for multiauth', () => {
const config: ClientConfigType = {
ui: configUI,
auth: {
- type: [AuthType.BASIC, 'openid', AuthType.SAML],
+ type: [AuthType.BASIC, AuthType.OPEN_ID, AuthType.SAML],
+ logout_url: API_AUTH_LOGOUT,
+ },
+ };
+ const component = shallow(
+
+ );
+ expect(component).toMatchSnapshot();
+ });
+
+ it('renders with config value for multiauth with anonymous auth enabled', () => {
+ const config: ClientConfigType = {
+ ui: configUI,
+ auth: {
+ type: [AuthType.BASIC, AuthType.OPEN_ID, AuthType.SAML],
logout_url: API_AUTH_LOGOUT,
+ anonymous_auth_enabled: true,
},
};
const component = shallow(
diff --git a/server/auth/types/basic/basic_auth.ts b/server/auth/types/basic/basic_auth.ts
index f21f86827..a9cfedb6c 100644
--- a/server/auth/types/basic/basic_auth.ts
+++ b/server/auth/types/basic/basic_auth.ts
@@ -28,9 +28,14 @@ import { SecurityPluginConfigType } from '../../..';
import { SecuritySessionCookie } from '../../../session/security_cookie';
import { BasicAuthRoutes } from './routes';
import { AuthenticationType } from '../authentication_type';
-import { LOGIN_PAGE_URI, ANONYMOUS_AUTH_LOGIN } from '../../../../common';
import { composeNextUrlQueryParam } from '../../../utils/next_url';
-import { AUTH_HEADER_NAME, AuthType, OPENDISTRO_SECURITY_ANONYMOUS } from '../../../../common';
+import {
+ LOGIN_PAGE_URI,
+ ANONYMOUS_AUTH_LOGIN,
+ AUTH_HEADER_NAME,
+ AuthType,
+ OPENDISTRO_SECURITY_ANONYMOUS,
+} from '../../../../common';
export class BasicAuthentication extends AuthenticationType {
public readonly type: string = AuthType.BASIC;
diff --git a/server/auth/types/multiple/multi_auth.ts b/server/auth/types/multiple/multi_auth.ts
index b190d9d03..b00b3d154 100644
--- a/server/auth/types/multiple/multi_auth.ts
+++ b/server/auth/types/multiple/multi_auth.ts
@@ -25,7 +25,7 @@ import {
import { OpenSearchDashboardsResponse } from '../../../../../../src/core/server/http/router';
import { SecurityPluginConfigType } from '../../..';
import { AuthenticationType } from '../authentication_type';
-import { ANONYMOUS_AUTH_LOGIN, AuthType, LOGIN_PAGE_URI } from '../../../../common';
+import { AuthType, LOGIN_PAGE_URI } from '../../../../common';
import { composeNextUrlQueryParam } from '../../../utils/next_url';
import { MultiAuthRoutes } from './routes';
import { SecuritySessionCookie } from '../../../session/security_cookie';
@@ -166,14 +166,6 @@ export class MultipleAuthentication extends AuthenticationType {
this.coreSetup.http.basePath.serverBasePath
);
- if (this.config.auth.anonymous_auth_enabled) {
- const redirectLocation = `${this.coreSetup.http.basePath.serverBasePath}${ANONYMOUS_AUTH_LOGIN}?${nextUrlParam}`;
- return response.redirected({
- headers: {
- location: `${redirectLocation}`,
- },
- });
- }
return response.redirected({
headers: {
location: `${this.coreSetup.http.basePath.serverBasePath}${LOGIN_PAGE_URI}?${nextUrlParam}`,
diff --git a/server/auth/types/saml/routes.ts b/server/auth/types/saml/routes.ts
index 87605d65e..d14d0711b 100644
--- a/server/auth/types/saml/routes.ts
+++ b/server/auth/types/saml/routes.ts
@@ -131,11 +131,12 @@ export class SamlAuthRoutes {
}
try {
- const credentials = await this.securityClient.authToken(
+ const credentials = await this.securityClient.authToken({
requestId,
- request.body.SAMLResponse,
- undefined
- );
+ samlResponse: request.body.SAMLResponse,
+ acsEndpoint: undefined,
+ authRequestType: AuthType.SAML,
+ });
const user = await this.securityClient.authenticateWithHeader(
request,
'authorization',
@@ -208,11 +209,12 @@ export class SamlAuthRoutes {
async (context, request, response) => {
const acsEndpoint = `${this.coreSetup.http.basePath.serverBasePath}/_opendistro/_security/saml/acs/idpinitiated`;
try {
- const credentials = await this.securityClient.authToken(
- undefined,
- request.body.SAMLResponse,
- acsEndpoint
- );
+ const credentials = await this.securityClient.authToken({
+ requestId: undefined,
+ samlResponse: request.body.SAMLResponse,
+ acsEndpoint,
+ authRequestType: AuthType.SAML,
+ });
const user = await this.securityClient.authenticateWithHeader(
request,
'authorization',
diff --git a/server/backend/opensearch_security_client.ts b/server/backend/opensearch_security_client.ts
index 71a65d205..6f2d3439f 100755
--- a/server/backend/opensearch_security_client.ts
+++ b/server/backend/opensearch_security_client.ts
@@ -16,6 +16,7 @@
import { ILegacyClusterClient, OpenSearchDashboardsRequest } from '../../../../src/core/server';
import { User } from '../auth/user';
import { TenancyConfigSettings } from '../../public/apps/configuration/panels/tenancy-config/types';
+import { AUTH_TYPE_PARAM, AuthType } from '../../common';
export class SecurityClient {
constructor(private readonly esClient: ILegacyClusterClient) {}
@@ -182,7 +183,9 @@ export class SecurityClient {
public async getSamlHeader(request: OpenSearchDashboardsRequest) {
try {
// response is expected to be an error
- await this.esClient.asScoped(request).callAsCurrentUser('opensearch_security.authinfo');
+ await this.esClient.asScoped(request).callAsCurrentUser('opensearch_security.authinfo', {
+ [AUTH_TYPE_PARAM]: AuthType.SAML,
+ });
} catch (error: any) {
// the error looks like
// wwwAuthenticateDirective:
@@ -217,11 +220,12 @@ export class SecurityClient {
throw new Error(`Invalid SAML configuration.`);
}
- public async authToken(
- requestId: string | undefined,
- samlResponse: any,
- acsEndpoint: any | undefined = undefined
- ) {
+ public async authToken({
+ requestId,
+ samlResponse,
+ acsEndpoint = undefined,
+ authRequestType,
+ }: AuthTokenParams) {
const body = {
RequestId: requestId,
SAMLResponse: samlResponse,
@@ -230,6 +234,7 @@ export class SecurityClient {
try {
return await this.esClient.asScoped().callAsCurrentUser('opensearch_security.authtoken', {
body,
+ [AUTH_TYPE_PARAM]: authRequestType,
});
} catch (error: any) {
console.log(error);
@@ -237,3 +242,10 @@ export class SecurityClient {
}
}
}
+
+interface AuthTokenParams {
+ requestId?: string;
+ samlResponse: any;
+ acsEndpoint?: any;
+ authRequestType?: string;
+}
diff --git a/test/constant.ts b/test/constant.ts
index d4ab9e3ae..5dcb387e2 100644
--- a/test/constant.ts
+++ b/test/constant.ts
@@ -13,14 +13,9 @@
* permissions and limitations under the License.
*/
-import { version, opensearchDashboards } from '../package.json';
-
export const OPENSEARCH_DASHBOARDS_SERVER_USER: string = 'kibanaserver';
export const OPENSEARCH_DASHBOARDS_SERVER_PASSWORD: string = 'kibanaserver';
-export const ELASTICSEARCH_VERSION: string = opensearchDashboards.version;
-export const SECURITY_ES_PLUGIN_VERSION: string = version;
-
export const ADMIN_USER: string = 'admin';
export const ADMIN_PASSWORD: string = process.env.ADMIN_PASSWORD || 'admin';
const ADMIN_USER_PASS: string = `${ADMIN_USER}:${ADMIN_PASSWORD}`;
diff --git a/test/jest_integration/basic_auth.test.ts b/test/jest_integration/basic_auth.test.ts
index b4bbd3e55..cdb4a39d0 100644
--- a/test/jest_integration/basic_auth.test.ts
+++ b/test/jest_integration/basic_auth.test.ts
@@ -132,7 +132,6 @@ describe('start OpenSearch Dashboards server', () => {
});
it('call authinfo API as admin', async () => {
- const testUserCredentials = Buffer.from(ADMIN_CREDENTIALS);
const response = await osdTestServer.request
.get(root, '/api/v1/auth/authinfo')
.set(AUTHORIZATION_HEADER_NAME, ADMIN_CREDENTIALS);
@@ -142,7 +141,7 @@ describe('start OpenSearch Dashboards server', () => {
it('call authinfo API without credentials', async () => {
const response = await osdTestServer.request
.get(root, '/api/v1/auth/authinfo')
- .unset('Authorization');
+ .unset(AUTHORIZATION_HEADER_NAME);
expect(response.status).toEqual(401);
});
@@ -209,7 +208,9 @@ describe('start OpenSearch Dashboards server', () => {
});
it('enforce authentication on api/status route', async () => {
- const response = await osdTestServer.request.get(root, '/api/status');
+ const response = await osdTestServer.request
+ .get(root, '/api/status')
+ .unset(AUTHORIZATION_HEADER_NAME);
expect(response.status).toEqual(401);
});