forked from opensearch-project/OpenSearch-Dashboards
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #38 from elastic-analytics/priscilla_poc
Basic and OIDC Authentication POC, Refactor configuration
- Loading branch information
Showing
33 changed files
with
2,578 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
export const PLUGIN_ID = 'opensearchDashboardsSecurity'; | ||
export const PLUGIN_NAME = 'security-dashboards-plugin'; | ||
|
||
export const APP_ID_LOGIN = 'login'; | ||
|
||
export const API_PREFIX = '/api/v1'; | ||
export const CONFIGURATION_API_PREFIX = 'configuration'; | ||
export const API_ENDPOINT_AUTHINFO = API_PREFIX + '/auth/authinfo'; | ||
export const API_ENDPOINT_AUTHTYPE = API_PREFIX + '/auth/type'; | ||
export const LOGIN_PAGE_URI = '/app/' + APP_ID_LOGIN; | ||
export const API_AUTH_LOGIN = '/auth/login'; | ||
export const API_AUTH_LOGOUT = '/auth/logout'; | ||
export const ANONYMOUS_AUTH_LOGIN = '/auth/anonymous'; | ||
export const SAML_AUTH_LOGIN_WITH_FRAGMENT = '/auth/saml/captureUrlFragment?nextUrl=%2F'; | ||
|
||
export const OPENID_AUTH_LOGOUT = '/auth/openid/logout'; | ||
export const SAML_AUTH_LOGOUT = '/auth/saml/logout'; | ||
export const ANONYMOUS_AUTH_LOGOUT = '/auth/anonymous/logout'; | ||
|
||
export const AUTH_HEADER_NAME = 'authorization'; | ||
export const AUTH_GRANT_TYPE = 'authorization_code'; | ||
export const AUTH_RESPONSE_TYPE = 'code'; | ||
|
||
export enum AuthType { | ||
BASIC = 'basicauth', | ||
OIDC = 'oidc', | ||
JWT = 'jwt', | ||
SAML = 'saml', | ||
PROXY = 'proxy', | ||
ANONYMOUS = 'anonymous', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"id": "dashboardsSecurity", | ||
"version": "opensearchDashboards", | ||
"configPath": ["dashboards_security"], | ||
"requiredPlugins": ["navigation"], | ||
"server": true, | ||
"ui": true | ||
} |
25 changes: 25 additions & 0 deletions
25
src/plugins/dashboards_security/public/apps/login/_index.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
.login-wrapper { | ||
margin: 10% auto; | ||
width: 350px; | ||
padding: 1rem; | ||
position: relative; | ||
} | ||
|
||
.btn-login { | ||
width: 100%; | ||
} |
21 changes: 21 additions & 0 deletions
21
src/plugins/dashboards_security/public/apps/login/login-app.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import './_index.scss'; | ||
// @ts-ignore : Component not used | ||
import React, { Component } from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import { AppMountParameters, CoreStart } from '../../../../../core/public'; | ||
import { ClientConfigType } from '../../types'; | ||
import { LoginPage } from './login-page'; | ||
|
||
export function renderApp( | ||
coreStart: CoreStart, | ||
params: AppMountParameters, | ||
config: ClientConfigType | ||
) { | ||
ReactDOM.render(<LoginPage http={coreStart.http} config={config} />, params.element); | ||
return () => ReactDOM.unmountComponentAtNode(params.element); | ||
} |
184 changes: 184 additions & 0 deletions
184
src/plugins/dashboards_security/public/apps/login/login-page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
import React, { useState } from 'react'; | ||
import { | ||
EuiText, | ||
EuiFieldText, | ||
EuiIcon, | ||
EuiSpacer, | ||
EuiButton, | ||
EuiImage, | ||
EuiListGroup, | ||
EuiForm, | ||
EuiFormRow, | ||
} from '@elastic/eui'; | ||
import { AuthType } from 'src/plugins/dashboards_security/common'; | ||
import { ESMap } from 'typescript'; | ||
import { map } from 'bluebird'; | ||
import { CoreStart } from '../../../../../core/public'; | ||
import { ClientConfigType } from '../../types'; | ||
import defaultBrandImage from '../../assets/opensearch_logo_h.svg'; | ||
import { validateCurrentPassword } from '../../utils/auth_utils'; | ||
|
||
interface LoginButtonConfig { | ||
buttonname: string; | ||
showbrandimage: boolean; | ||
brandimage: string; | ||
buttonstyle: string; | ||
} | ||
|
||
interface LoginPageDeps { | ||
http: CoreStart['http']; | ||
config: ClientConfigType; | ||
} | ||
|
||
function redirect(serverBasePath: string) { | ||
// navigate to nextUrl | ||
const urlParams = new URLSearchParams(window.location.search); | ||
let nextUrl = urlParams.get('nextUrl'); | ||
if (!nextUrl || nextUrl.toLowerCase().includes('//')) { | ||
nextUrl = serverBasePath + '/'; | ||
} | ||
window.location.href = nextUrl + window.location.hash; | ||
} | ||
|
||
export function LoginPage(props: LoginPageDeps) { | ||
const [username, setUsername] = React.useState(''); | ||
const [password, setPassword] = React.useState(''); | ||
const [loginFailed, setloginFailed] = useState(false); | ||
const [loginError, setloginError] = useState(''); | ||
const [usernameValidationFailed, setUsernameValidationFailed] = useState(false); | ||
const [passwordValidationFailed, setPasswordValidationFailed] = useState(false); | ||
|
||
let errorLabel: any = null; | ||
if (loginFailed) { | ||
errorLabel = ( | ||
<EuiText id="error" color="danger" textAlign="center"> | ||
<b>{loginError}</b> | ||
</EuiText> | ||
); | ||
} | ||
|
||
// @ts-ignore : Parameter 'e' implicitly has an 'any' type. | ||
const handleSubmit = async (e) => { | ||
e.preventDefault(); | ||
|
||
// Clear errors | ||
setloginFailed(false); | ||
setUsernameValidationFailed(false); | ||
setPasswordValidationFailed(false); | ||
|
||
// Form validation | ||
if (username === '') { | ||
setUsernameValidationFailed(true); | ||
return; | ||
} | ||
|
||
if (password === '') { | ||
setPasswordValidationFailed(true); | ||
return; | ||
} | ||
try { | ||
await validateCurrentPassword(props.http, username, password); | ||
redirect(props.http.basePath.serverBasePath); | ||
} catch (error) { | ||
setloginFailed(true); | ||
setloginError('Invalid username or password. Please try again.'); | ||
return; | ||
} | ||
}; | ||
|
||
// TODO: Get brand image from server config | ||
return ( | ||
<EuiListGroup className="login-wrapper"> | ||
{props.config.ui.basicauth.login.showbrandimage && ( | ||
<EuiImage | ||
size="fullWidth" | ||
alt="" | ||
url={props.config.ui.basicauth.login.brandimage || defaultBrandImage} | ||
/> | ||
)} | ||
<EuiSpacer size="s" /> | ||
<EuiText size="m" textAlign="center"> | ||
{props.config.ui.basicauth.login.title || 'Please login to OpenSearch Dashboards'} | ||
</EuiText> | ||
<EuiSpacer size="s" /> | ||
<EuiText size="s" textAlign="center"> | ||
{props.config.ui.basicauth.login.subtitle || | ||
'If you have forgotten your username or password, please ask your system administrator'} | ||
</EuiText> | ||
<EuiSpacer size="s" /> | ||
<EuiForm component="form"> | ||
<EuiFormRow> | ||
<EuiFieldText | ||
data-test-subj="user-name" | ||
placeholder="Username" | ||
prepend={<EuiIcon type="user" />} | ||
onChange={(e) => setUsername(e.target.value)} | ||
value={username} | ||
/> | ||
</EuiFormRow> | ||
<EuiFormRow> | ||
<EuiFieldText | ||
data-test-subj="password" | ||
placeholder="Password" | ||
prepend={<EuiIcon type="lock" />} | ||
type="password" | ||
onChange={(e) => setPassword(e.target.value)} | ||
value={password} | ||
/> | ||
</EuiFormRow> | ||
<EuiFormRow> | ||
<EuiButton | ||
data-test-subj="submit" | ||
fill | ||
size="s" | ||
type="submit" | ||
className={props.config.ui.basicauth.login.buttonstyle || 'btn-login'} | ||
onClick={handleSubmit} | ||
> | ||
Log In | ||
</EuiButton> | ||
</EuiFormRow> | ||
</EuiForm> | ||
<EuiSpacer size="s" /> | ||
<EuiFormRow> | ||
<EuiButton | ||
data-test-subj="submit" | ||
size="s" | ||
type="prime" | ||
className={props.config.ui.openid.login.buttonstyle || 'btn-login'} | ||
href="/auth/oidc/okta/login" | ||
iconType={ | ||
props.config.ui.openid.login.showbrandimage | ||
? props.config.ui.openid.login.brandimage | ||
: '' | ||
} | ||
> | ||
Login with OKTA (OIDC) | ||
</EuiButton> | ||
</EuiFormRow> | ||
<EuiSpacer size="s" /> | ||
<EuiFormRow> | ||
<EuiButton | ||
data-test-subj="submit" | ||
size="s" | ||
type="prime" | ||
className={props.config.ui.openid.login.buttonstyle || 'btn-login'} | ||
href="/auth/oidc/google/login" | ||
iconType={ | ||
props.config.ui.openid.login.showbrandimage | ||
? props.config.ui.openid.login.brandimage | ||
: '' | ||
} | ||
> | ||
Login with Google (OIDC) | ||
</EuiButton> | ||
</EuiFormRow> | ||
{errorLabel} | ||
</EuiListGroup> | ||
); | ||
} |
38 changes: 38 additions & 0 deletions
38
src/plugins/dashboards_security/public/apps/logout/logout-app.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/* | ||
* Copyright OpenSearch Contributors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import { CoreStart } from 'opensearch-dashboards/public'; | ||
import { ClientConfigType } from '../../types'; | ||
import { LogoutPage } from './logout-page'; | ||
|
||
export async function setupLogoutButton(coreStart: CoreStart, config: ClientConfigType) { | ||
coreStart.chrome.navControls.registerRight({ | ||
order: 2000, | ||
mount: (element: HTMLElement) => { | ||
ReactDOM.render( | ||
<LogoutPage http={coreStart.http} logoutUrl={config.auth.logout_url} />, | ||
element | ||
); | ||
return () => ReactDOM.unmountComponentAtNode(element); | ||
}, | ||
}); | ||
} |
34 changes: 34 additions & 0 deletions
34
src/plugins/dashboards_security/public/apps/logout/logout-page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright OpenSearch Contributors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
/* | ||
* Copyright OpenSearch Contributors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
import React from 'react'; | ||
import { EuiButtonEmpty } from '@elastic/eui'; | ||
import { HttpStart } from 'opensearch-dashboards/public'; | ||
import { logout } from '../../utils/auth_utils'; | ||
|
||
export function LogoutPage(props: { http: HttpStart; logoutUrl?: string }) { | ||
return ( | ||
<div> | ||
<EuiButtonEmpty size="xs" onClick={() => logout(props.http, props.logoutUrl)}> | ||
Log out | ||
</EuiButtonEmpty> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.