Skip to content

Commit 091d004

Browse files
Repumbapsrok1
andauthored
Improve auth frontend (#726)
Co-authored-by: Paweł Srokosz <pawel.srokosz@cert.pl>
1 parent 610066d commit 091d004

File tree

6 files changed

+204
-196
lines changed

6 files changed

+204
-196
lines changed

mwdb/web/src/App.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import ProfileAPIKeys from "./components/Profile/Views/ProfileAPIKeys";
3838
import ProfileResetPassword from "./components/Profile/Views/ProfileResetPassword";
3939
import ProfileOAuth from "./components/Profile/Views/ProfileOAuth";
4040

41-
import { OAuthLogin, OAuthAuthorize } from "./components/OAuth";
41+
import { OAuthAuthorize } from "./components/OAuth";
4242

4343
import SettingsOverview from "./components/Settings/Views/SettingsOverview";
4444
import UsersPendingList from "./components/Settings/Views/UsersPendingList";
@@ -100,20 +100,12 @@ function SampleRouteFallback() {
100100
}
101101

102102
function AppRoutes() {
103-
const {
104-
config: { is_registration_enabled: isRegistrationEnabled },
105-
} = useContext(ConfigContext);
106103
return (
107104
<Routes>
108105
<Route path="login" element={<UserLogin />} />
109-
{isRegistrationEnabled ? (
110-
<Route path="register" element={<UserRegister />} />
111-
) : (
112-
[]
113-
)}
106+
<Route path="register" element={<UserRegister />} />
114107
<Route path="recover_password" element={<UserPasswordRecover />} />
115108
<Route path="setpasswd/:token" element={<UserSetPassword />} />
116-
<Route path="oauth/login" element={<OAuthLogin />} />
117109
<Route path="oauth/callback" element={<OAuthAuthorize />} />
118110
<Route element={<RequiresAuth />}>
119111
<Route path="/" element={<RecentSamples />} />

mwdb/web/src/components/Navigation.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -91,25 +91,6 @@ export default function Navigation() {
9191
const remotePath = useRemotePath();
9292
const navItems = config.isReady ? (
9393
<Extendable ident="navbar">
94-
{!auth.isAuthenticated &&
95-
config.config["is_registration_enabled"] ? (
96-
<li className="nav-item">
97-
<Link className="nav-link" to={"/register"}>
98-
Register user
99-
</Link>
100-
</li>
101-
) : (
102-
[]
103-
)}
104-
{!auth.isAuthenticated && config.config["is_oidc_enabled"] ? (
105-
<li className="nav-item">
106-
<Link className="nav-link" to={"/oauth/login"}>
107-
OAuth authentication
108-
</Link>
109-
</li>
110-
) : (
111-
[]
112-
)}
11394
{auth.isAuthenticated ? (
11495
<Extendable ident="navbarAuthenticated">
11596
<li className="nav-item">

mwdb/web/src/components/OAuth.js

Lines changed: 68 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,87 @@
11
import React, { useContext, useEffect, useState } from "react";
2-
import { Link, useSearchParams, useNavigate } from "react-router-dom";
2+
import { useSearchParams, useNavigate } from "react-router-dom";
33

4-
import { APIContext } from "@mwdb-web/commons/api/context";
4+
import api from "@mwdb-web/commons/api";
55
import { AuthContext } from "@mwdb-web/commons/auth";
6-
import { View, getErrorMessage } from "@mwdb-web/commons/ui";
7-
import { ConfirmationModal, ShowIf } from "@mwdb-web/commons/ui";
6+
import { getErrorMessage } from "@mwdb-web/commons/ui";
87

9-
export function OAuthLogin() {
10-
const api = useContext(APIContext);
11-
const [error, setError] = useState();
12-
const [providers, setProviders] = useState([]);
13-
const [chosenProvider, setChosenProvider] = useState();
14-
const [isRedirectModalOpen, setRedirectModalOpen] = useState(false);
15-
const [isRegisterModalOpen, setRegisterModalOpen] = useState(false);
16-
17-
async function getProviders() {
18-
try {
19-
const response = await api.oauthGetProviders();
20-
setProviders(response.data["providers"]);
21-
} catch (e) {
22-
setError(e);
23-
}
8+
async function authenticate(provider, action, errorFunction) {
9+
try {
10+
const response = await api.oauthAuthenticate(provider);
11+
const expirationTime = Date.now() + 5 * 60 * 1000;
12+
sessionStorage.setItem(
13+
`openid_${response.data["state"]}`,
14+
JSON.stringify({
15+
provider: provider,
16+
nonce: response.data["nonce"],
17+
action: action,
18+
expiration: expirationTime,
19+
})
20+
);
21+
window.location = response.data["authorization_url"];
22+
} catch (e) {
23+
errorFunction(e);
2424
}
25+
}
2526

26-
async function authenticate(provider, action) {
27-
try {
28-
const response = await api.oauthAuthenticate(provider);
29-
const expirationTime = Date.now() + 5 * 60 * 1000;
30-
sessionStorage.setItem(
31-
`openid_${response.data["state"]}`,
32-
JSON.stringify({
33-
provider: provider,
34-
nonce: response.data["nonce"],
35-
action: action,
36-
expiration: expirationTime,
37-
})
38-
);
39-
window.location = response.data["authorization_url"];
40-
} catch (e) {
41-
setError(e);
42-
}
43-
}
27+
export function ProviderButton({ provider, color }) {
28+
// todo: correct error handling
29+
const [, setError] = useState();
30+
const chosenProvider = provider;
4431

45-
useEffect(() => {
46-
getProviders();
47-
// eslint-disable-next-line react-hooks/exhaustive-deps
48-
}, []);
32+
return (
33+
<button
34+
onClick={(e) => {
35+
e.preventDefault();
36+
authenticate(chosenProvider, "authorize", setError);
37+
}}
38+
className="form-control btn btn-primary mb-1"
39+
style={{
40+
backgroundColor: color,
41+
borderStyle: "none",
42+
}}
43+
>
44+
Log in with {provider}
45+
</button>
46+
);
47+
}
48+
49+
export function ProvidersSelectList({ providersList }) {
50+
// todo: correct error handling
51+
const [, setError] = useState();
52+
const availableProviders = providersList;
53+
const [chosenProvider, setChosenProvider] = useState();
4954

5055
return (
51-
<View error={error}>
52-
<h2>External authentication</h2>
53-
<p>
54-
Select below the identity provider associated with your mwdb
55-
account. By clicking on the identity provider below you will be
56-
redirected to its authentication page. <br />
57-
If you don't have an account associated with any of these
58-
providers you can do this in the profile details. <br />
59-
Alternatively, you can register a new account through an
60-
external identity provider by{" "}
61-
<Link
62-
to="#"
63-
onClick={(ev) => {
64-
ev.preventDefault();
65-
setRegisterModalOpen(true);
66-
}}
67-
>
68-
clicking here
69-
</Link>
70-
.
71-
</p>
72-
<ShowIf condition={providers.length}>
73-
{providers.map((provider) => (
74-
<div className="d-flex justify-content-center">
75-
<div className="col-6 text-center">
76-
<Link
77-
to="#"
78-
className="card btn-outline-secondary text-decoration-none"
79-
onClick={(ev) => {
80-
ev.preventDefault();
81-
setChosenProvider(provider);
82-
setRedirectModalOpen(true);
83-
}}
84-
>
85-
<div className="card-body">
86-
<h5>{provider}</h5>
87-
</div>
88-
</Link>
89-
</div>
90-
</div>
91-
))}
92-
</ShowIf>
93-
<ConfirmationModal
94-
isOpen={isRedirectModalOpen}
95-
onRequestClose={() => {
96-
setRedirectModalOpen(false);
97-
setChosenProvider("");
98-
}}
99-
onConfirm={(e) => {
100-
e.preventDefault();
101-
authenticate(chosenProvider, "authorize");
56+
<form>
57+
<select
58+
className="custom-select"
59+
onChange={(e) => {
60+
setChosenProvider(e.target.value);
10261
}}
103-
message={`Are you sure you want to redirect to ${chosenProvider} provider`}
104-
buttonStyle="btn-danger"
105-
/>
106-
<ConfirmationModal
107-
isOpen={isRegisterModalOpen}
108-
onRequestClose={() => setRegisterModalOpen(false)}
109-
message="Choose OpenID Provider to register user"
110-
onConfirm={(e) => {
62+
>
63+
<option value="" hidden>
64+
Select provider...
65+
</option>
66+
{availableProviders.map((provider) => (
67+
<option value={provider}>{provider}</option>
68+
))}
69+
</select>
70+
<button
71+
className="form-control btn btn-primary mt-1"
72+
style={{ backgroundColor: "#3c5799" }}
73+
onClick={(e) => {
11174
e.preventDefault();
112-
authenticate(chosenProvider, "register");
75+
authenticate(chosenProvider, "authorize", setError);
11376
}}
114-
buttonStyle="btn-info"
115-
confirmText="Submit"
11677
>
117-
<form onSubmit={(e) => {}}>
118-
<div>
119-
<select
120-
className="custom-select"
121-
value={chosenProvider}
122-
onChange={(ev) =>
123-
setChosenProvider(ev.target.value)
124-
}
125-
>
126-
<option value="" hidden>
127-
Select provider...
128-
</option>
129-
{providers.map((provider) => (
130-
<option value={provider}>{provider}</option>
131-
))}
132-
</select>
133-
</div>
134-
</form>
135-
</ConfirmationModal>
136-
</View>
78+
Log in with selected provider
79+
</button>
80+
</form>
13781
);
13882
}
13983

14084
export function OAuthAuthorize() {
141-
const api = useContext(APIContext);
14285
const auth = useContext(AuthContext);
14386
const navigate = useNavigate();
14487
// Current query set in URI path
@@ -189,7 +132,7 @@ export function OAuthAuthorize() {
189132
replace: true,
190133
});
191134
else {
192-
navigate("/oauth/login", {
135+
navigate("/login", {
193136
state: {
194137
error: getErrorMessage(e),
195138
},

0 commit comments

Comments
 (0)