diff --git a/models/login_details.go b/models/login_details.go
index 51d99c652..ad162ca06 100644
--- a/models/login_details.go
+++ b/models/login_details.go
@@ -41,9 +41,6 @@ type LoginDetails struct {
// animated login
AnimatedLogin bool `json:"animatedLogin,omitempty"`
- // is direct p v
- IsDirectPV bool `json:"isDirectPV,omitempty"`
-
// is k8 s
IsK8S bool `json:"isK8S,omitempty"`
diff --git a/portal-ui/src/ProtectedRoutes.tsx b/portal-ui/src/ProtectedRoutes.tsx
index ac2eb7cf4..3b500c514 100644
--- a/portal-ui/src/ProtectedRoutes.tsx
+++ b/portal-ui/src/ProtectedRoutes.tsx
@@ -64,7 +64,7 @@ const ProtectedRoute = ({ Component }: ProtectedRouteProps) => {
dispatch(saveSessionResponse(res));
dispatch(userLogged(true));
setSessionLoading(false);
- dispatch(globalSetDistributedSetup(res.distributedMode || false));
+ dispatch(globalSetDistributedSetup(res?.distributedMode || false));
if (res.customStyles && res.customStyles !== "") {
const overrideColorVariants = getOverrideColorVariants(
diff --git a/portal-ui/src/api/consoleApi.ts b/portal-ui/src/api/consoleApi.ts
index 04d586941..390bd9db7 100644
--- a/portal-ui/src/api/consoleApi.ts
+++ b/portal-ui/src/api/consoleApi.ts
@@ -466,7 +466,6 @@ export interface LoginDetails {
| "service-account"
| "redirect-service-account";
redirectRules?: RedirectRule[];
- isDirectPV?: boolean;
isK8S?: boolean;
animatedLogin?: boolean;
}
diff --git a/portal-ui/src/screens/LoginPage/LoginPage.tsx b/portal-ui/src/screens/LoginPage/LoginPage.tsx
index fbca5dca1..215413de5 100644
--- a/portal-ui/src/screens/LoginPage/LoginPage.tsx
+++ b/portal-ui/src/screens/LoginPage/LoginPage.tsx
@@ -16,13 +16,9 @@
import React, { Fragment, useEffect } from "react";
import { useNavigate } from "react-router-dom";
-import { Button, Loader, LoginWrapper, RefreshIcon } from "mds";
-import { Theme } from "@mui/material/styles";
-import createStyles from "@mui/styles/createStyles";
-import makeStyles from "@mui/styles/makeStyles";
+import { Box, Button, Loader, LoginWrapper, RefreshIcon } from "mds";
import { loginStrategyType, redirectRule } from "./types";
import MainError from "../Console/Common/MainError/MainError";
-import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
import { AppState, useAppDispatch } from "../../store";
import { useSelector } from "react-redux";
import { getFetchConfigurationAsync, getVersionAsync } from "./loginThunks";
@@ -31,205 +27,6 @@ import StrategyForm from "./StrategyForm";
import { redirectRules } from "../../utils/sortFunctions";
import { getLogoVar } from "../../config";
-const useStyles = makeStyles((theme: Theme) =>
- createStyles({
- root: {
- position: "absolute",
- top: 0,
- left: 0,
- width: "100%",
- height: "100%",
- overflow: "auto",
- },
- form: {
- width: "100%", // Fix IE 11 issue.
- },
- submit: {
- margin: "30px 0px 8px",
- height: 40,
- width: "100%",
- boxShadow: "none",
- padding: "16px 30px",
- },
- loginSsoText: {
- fontWeight: "700",
- marginBottom: "15px",
- },
- ssoSelect: {
- width: "100%",
- fontSize: "13px",
- fontWeight: "700",
- color: "grey",
- },
- ssoMenuItem: {
- fontSize: "15px",
- fontWeight: "700",
- color: theme.palette.primary.light,
- "&.MuiMenuItem-divider:last-of-type": {
- borderBottom: "none",
- },
- "&.Mui-focusVisible": {
- backgroundColor: theme.palette.grey["100"],
- },
- },
- ssoLoginIcon: {
- height: "13px",
- marginRight: "25px",
- },
- ssoSubmit: {
- marginTop: "15px",
- "&:first-of-type": {
- marginTop: 0,
- },
- },
- separator: {
- marginLeft: 4,
- marginRight: 4,
- },
- linkHolder: {
- marginTop: 20,
- font: "normal normal normal 14px/16px Inter",
- },
- miniLinks: {
- margin: "auto",
- textAlign: "center",
- color: "#B2DEF5",
- "& a": {
- color: "#B2DEF5",
- textDecoration: "none",
- },
- "& .min-icon": {
- width: 10,
- color: "#B2DEF5",
- },
- },
- miniLogo: {
- marginTop: 8,
- "& .min-icon": {
- height: 12,
- paddingTop: 2,
- marginRight: 2,
- },
- },
- loginPage: {
- height: "100%",
- margin: "auto",
- },
- buttonRetry: {
- display: "flex",
- justifyContent: "center",
- },
- loginContainer: {
- flexDirection: "column",
- maxWidth: 400,
- margin: "auto",
- "& .right-items": {
- backgroundColor: "white",
- padding: 40,
- },
- "& .consoleTextBanner": {
- fontWeight: 300,
- fontSize: "calc(3vw + 3vh + 1.5vmin)",
- lineHeight: 1.15,
- color: theme.palette.primary.main,
- flex: 1,
- height: "100%",
- display: "flex",
- justifyContent: "flex-start",
- margin: "auto",
-
- "& .logoLine": {
- display: "flex",
- alignItems: "center",
- fontSize: 18,
- },
- "& .left-items": {
- marginTop: 100,
- background:
- "transparent linear-gradient(180deg, #FBFAFA 0%, #E4E4E4 100%) 0% 0% no-repeat padding-box",
- padding: 40,
- },
- "& .left-logo": {
- "& .min-icon": {
- color: theme.palette.primary.main,
- width: 108,
- },
- marginBottom: 10,
- },
- "& .text-line1": {
- font: " 100 44px 'Inter'",
- },
- "& .text-line2": {
- fontSize: 80,
- fontWeight: 100,
- textTransform: "uppercase",
- },
- "& .text-line3": {
- fontSize: 14,
- fontWeight: "bold",
- },
- "& .logo-console": {
- display: "flex",
- alignItems: "center",
-
- "@media (max-width: 900px)": {
- marginTop: 20,
- flexFlow: "column",
-
- "& svg": {
- width: "50%",
- },
- },
- },
- },
- },
- "@media (max-width: 900px)": {
- loginContainer: {
- display: "flex",
- flexFlow: "column",
-
- "& .consoleTextBanner": {
- margin: 0,
- flex: 2,
-
- "& .left-items": {
- alignItems: "center",
- textAlign: "center",
- },
-
- "& .logoLine": {
- justifyContent: "center",
- },
- },
- },
- },
- loginStrategyMessage: {
- textAlign: "center",
- },
- loadingLoginStrategy: {
- textAlign: "center",
- width: 40,
- height: 40,
- },
- submitContainer: {
- textAlign: "right",
- marginTop: 30,
- },
- linearPredef: {
- height: 10,
- },
- retryButton: {
- alignSelf: "flex-end",
- },
- iconLogo: {
- "& .min-icon": {
- width: "100%",
- },
- },
- ...spacingUtils,
- })
-);
-
export interface LoginStrategyPayload {
accessKey: string;
secretKey: string;
@@ -251,7 +48,6 @@ export const getTargetPath = () => {
const Login = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
- const classes = useStyles();
const loginStrategy = useSelector(
(state: AppState) => state.login.loginStrategy
@@ -308,19 +104,32 @@ const Login = () => {
}
default:
loginComponent = (
-
+
{loadingFetchConfiguration ? (
-
+
) : (
-
-
+
+
An error has occurred
The backend cannot be reached.
-
-
+
+
)}
-
+
);
}
@@ -351,11 +160,18 @@ const Login = () => {
logoProps={{ applicationName: "console", subVariant: getLogoVar() }}
form={loginComponent}
formFooter={
-
+
Documentation
- |
+ |
{
>
GitHub
- |
+ |
{
>
Support
- |
+ |
{
>
Download
-
+
}
promoHeader={
High-Performance Object Store
diff --git a/portal-ui/src/screens/LoginPage/StrategyForm.tsx b/portal-ui/src/screens/LoginPage/StrategyForm.tsx
index e57122300..f37fbbe98 100644
--- a/portal-ui/src/screens/LoginPage/StrategyForm.tsx
+++ b/portal-ui/src/screens/LoginPage/StrategyForm.tsx
@@ -14,72 +14,47 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see
.
-import Grid from "@mui/material/Grid";
-import React from "react";
+import React, { Fragment, useState } from "react";
import {
+ Box,
Button,
+ DropdownSelector,
+ Grid,
+ InputBox,
LockFilledIcon,
LogoutIcon,
PasswordKeyIcon,
+ Select,
UserFilledIcon,
} from "mds";
-import { setAccessKey, setSecretKey, setSTS, setUseSTS } from "./loginSlice";
import {
- InputAdornment,
- LinearProgress,
- MenuItem,
- Select,
- SelectChangeEvent,
-} from "@mui/material";
+ setAccessKey,
+ setDisplayEmbeddedIDPForms,
+ setSecretKey,
+ setSTS,
+ setUseSTS,
+} from "./loginSlice";
+import { LinearProgress } from "@mui/material";
import { AppState, useAppDispatch } from "../../store";
import { useSelector } from "react-redux";
-import { LoginField } from "./LoginField";
-import makeStyles from "@mui/styles/makeStyles";
-import { Theme } from "@mui/material/styles";
-import createStyles from "@mui/styles/createStyles";
-import { spacingUtils } from "../Console/Common/FormComponents/common/styleLibrary";
import { doLoginAsync } from "./loginThunks";
import { IStrategyForm } from "./types";
-const useStyles = makeStyles((theme: Theme) =>
- createStyles({
- root: {
- position: "absolute",
- top: 0,
- left: 0,
- width: "100%",
- height: "100%",
- overflow: "auto",
- },
- form: {
- width: "100%", // Fix IE 11 issue.
- },
- submit: {
- margin: "30px 0px 8px",
- height: 40,
- width: "100%",
- boxShadow: "none",
- padding: "16px 30px",
- },
- submitContainer: {
- textAlign: "right",
- marginTop: 30,
- },
- linearPredef: {
- height: 10,
- },
- ...spacingUtils,
- })
-);
-
const StrategyForm = ({ redirectRules }: IStrategyForm) => {
const dispatch = useAppDispatch();
- const classes = useStyles();
+
+ const [ssoOptionsOpen, ssoOptionsSetOpen] = useState
(false);
+ const [anchorEl, setAnchorEl] = React.useState<
+ (EventTarget & HTMLButtonElement) | null
+ >(null);
const accessKey = useSelector((state: AppState) => state.login.accessKey);
const secretKey = useSelector((state: AppState) => state.login.secretKey);
const sts = useSelector((state: AppState) => state.login.sts);
const useSTS = useSelector((state: AppState) => state.login.useSTS);
+ const displaySSOForm = useSelector(
+ (state: AppState) => state.login.ssoEmbeddedIDPDisplay
+ );
const loginSending = useSelector(
(state: AppState) => state.login.loginSending
@@ -90,177 +65,207 @@ const StrategyForm = ({ redirectRules }: IStrategyForm) => {
dispatch(doLoginAsync());
};
- let ssoOptions: React.ReactNode = null;
+ let selectOptions = [
+ {
+ label: useSTS ? "Use Credentials" : "Use STS",
+ value: useSTS ? "use-sts-cred" : "use-sts",
+ },
+ ];
+ let ssoOptions: any[] = [];
if (redirectRules.length > 0) {
- ssoOptions = redirectRules.map((r, idx) => (
-
- ));
+ ssoOptions = redirectRules.map((r) => ({
+ label: `${r.displayName}${r.serviceType ? ` - ${r.serviceType}` : ""}`,
+ value: r.redirect,
+ icon: ,
+ }));
+
+ selectOptions = [
+ { label: "Use Credentials", value: "use-sts-cred" },
+ { label: "Use STS", value: "use-sts" },
+ ];
}
- const extraActionSelector = (e: SelectChangeEvent) => {
- const value = e.target.value;
-
+ const extraActionSelector = (value: string) => {
if (value) {
- console.log(value);
- if (value.includes("use-sts")) {
- console.log("si");
- dispatch(setUseSTS(!useSTS));
+ if (redirectRules.length > 0) {
+ let stsState = true;
+
+ if (value === "use-sts-cred") {
+ stsState = false;
+ }
+
+ dispatch(setUseSTS(stsState));
+ dispatch(setDisplayEmbeddedIDPForms(true));
return;
}
- window.location.href = e.target.value as string;
+ if (value.includes("use-sts")) {
+ dispatch(setUseSTS(!useSTS));
+ return;
+ }
}
};
+ const submitSSOInitRequest = (value: string) => {
+ window.location.href = value;
+ };
+
return (
-
diff --git a/portal-ui/src/screens/LoginPage/loginSlice.ts b/portal-ui/src/screens/LoginPage/loginSlice.ts
index 2671b1f9b..6fae78278 100644
--- a/portal-ui/src/screens/LoginPage/loginSlice.ts
+++ b/portal-ui/src/screens/LoginPage/loginSlice.ts
@@ -28,18 +28,14 @@ export interface LoginState {
sts: string;
useSTS: boolean;
backgroundAnimation: boolean;
-
loginStrategy: ILoginDetails;
-
loginSending: boolean;
loadingFetchConfiguration: boolean;
-
latestMinIOVersion: string;
loadingVersion: boolean;
- isDirectPV: boolean;
isK8S: boolean;
-
navigateTo: string;
+ ssoEmbeddedIDPDisplay: boolean;
}
const initialState: LoginState = {
@@ -55,11 +51,10 @@ const initialState: LoginState = {
loadingFetchConfiguration: true,
latestMinIOVersion: "",
loadingVersion: true,
- isDirectPV: false,
isK8S: false,
backgroundAnimation: false,
-
navigateTo: "",
+ ssoEmbeddedIDPDisplay: false,
};
export const loginSlice = createSlice({
@@ -81,6 +76,9 @@ export const loginSlice = createSlice({
setNavigateTo: (state, action: PayloadAction) => {
state.navigateTo = action.payload;
},
+ setDisplayEmbeddedIDPForms: (state, action: PayloadAction) => {
+ state.ssoEmbeddedIDPDisplay = action.payload;
+ },
resetForm: (state) => initialState,
},
extraReducers: (builder) => {
@@ -107,7 +105,6 @@ export const loginSlice = createSlice({
state.loadingFetchConfiguration = false;
if (action.payload) {
state.loginStrategy = action.payload;
- state.isDirectPV = !!action.payload.isDirectPV;
state.isK8S = !!action.payload.isK8S;
state.backgroundAnimation = !!action.payload.animatedLogin;
}
@@ -131,6 +128,7 @@ export const {
setUseSTS,
setSTS,
setNavigateTo,
+ setDisplayEmbeddedIDPForms,
resetForm,
} = loginSlice.actions;
diff --git a/portal-ui/src/screens/LoginPage/types.ts b/portal-ui/src/screens/LoginPage/types.ts
index d5932c02a..03c42a51f 100644
--- a/portal-ui/src/screens/LoginPage/types.ts
+++ b/portal-ui/src/screens/LoginPage/types.ts
@@ -17,7 +17,6 @@
export interface ILoginDetails {
loginStrategy: loginStrategyType;
redirectRules: redirectRule[];
- isDirectPV?: boolean;
isK8S?: boolean;
animatedLogin?: boolean;
}
diff --git a/portal-ui/tests/permissions-1/test-fix-ui-crash-for-policy.ts b/portal-ui/tests/permissions-1/test-fix-ui-crash-for-policy.ts
index 86c4eab13..38d2f69d2 100644
--- a/portal-ui/tests/permissions-1/test-fix-ui-crash-for-policy.ts
+++ b/portal-ui/tests/permissions-1/test-fix-ui-crash-for-policy.ts
@@ -37,7 +37,7 @@ insAllowedSeckey = "poluicrashfix1234";*/
const loginUrl = `${testDomainUrl}/login`;
const bucketsScreenUrl = `${testDomainUrl}/buckets`;
-const loginSubmitBtn = Selector("form button");
+const loginSubmitBtn = Selector("button").withAttribute("id", "do-login");
export const bucketsSidebarEl = Selector(".MuiPaper-root")
.find("ul")
diff --git a/portal-ui/tests/permissions-2/inspect.ts b/portal-ui/tests/permissions-2/inspect.ts
index 9883593f7..b2a5c972f 100644
--- a/portal-ui/tests/permissions-2/inspect.ts
+++ b/portal-ui/tests/permissions-2/inspect.ts
@@ -46,7 +46,7 @@ insNotAllowedSeckey = "minio123";
const loginUrl = `${testDomainUrl}/login`;
const inspectScreenUrl = `${testDomainUrl}${IAM_PAGES.SUPPORT_INSPECT}`;
-const loginSubmitBtn = Selector("form button");
+const loginSubmitBtn = Selector("button").withAttribute("id", "do-login");
export const inspectEl = Selector(".MuiPaper-root")
.find("ul")
diff --git a/portal-ui/tests/permissions-7/resourceTesting.ts b/portal-ui/tests/permissions-7/resourceTesting.ts
index 6353d3259..1bedb2c55 100644
--- a/portal-ui/tests/permissions-7/resourceTesting.ts
+++ b/portal-ui/tests/permissions-7/resourceTesting.ts
@@ -63,16 +63,20 @@ test
.useRole(roles.conditions2)
.navigateTo(`http://localhost:9090/browser`)
.click(test1BucketBrowseButton)
+ .wait(1500)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText("firstlevel")
)
+ .wait(1500)
.expect(file.exists)
.notOk()
+ .wait(1500)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText(
"secondlevel"
)
)
+ .wait(1500)
.expect(file.exists)
.notOk();
}
@@ -113,19 +117,25 @@ test
.useRole(roles.conditions1)
.navigateTo(`http://localhost:9090/browser`)
.click(test1BucketBrowseButton)
+ .wait(1500)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText("firstlevel")
)
+ .wait(1500)
.expect(file.exists)
.ok()
+ .wait(1500)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText("secondlevel")
)
+ .wait(1500)
.expect(file.exists)
.ok()
+ .wait(1500)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText("thirdlevel")
)
+ .wait(1500)
.expect(file.exists)
.ok();
})
diff --git a/portal-ui/tests/utils/roles.ts b/portal-ui/tests/utils/roles.ts
index 01d7c84a7..392071e6b 100644
--- a/portal-ui/tests/utils/roles.ts
+++ b/portal-ui/tests/utils/roles.ts
@@ -7,7 +7,7 @@ const unixTimestamp = data.trim();
const loginUrl = "http://localhost:9090/login";
// diagnostics/watch/trace need to run in port 9090 (through the server) to work
const loginUrlServer = "http://localhost:9090/login";
-const submitButton = Selector("form button");
+const submitButton = Selector("button").withAttribute("id", "do-login");
export const admin = Role(
loginUrl,
diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go
index c68fcb4a1..5f77661af 100644
--- a/restapi/embedded_spec.go
+++ b/restapi/embedded_spec.go
@@ -7029,9 +7029,6 @@ func init() {
"animatedLogin": {
"type": "boolean"
},
- "isDirectPV": {
- "type": "boolean"
- },
"isK8S": {
"type": "boolean"
},
@@ -16163,9 +16160,6 @@ func init() {
"animatedLogin": {
"type": "boolean"
},
- "isDirectPV": {
- "type": "boolean"
- },
"isK8S": {
"type": "boolean"
},
diff --git a/restapi/user_login.go b/restapi/user_login.go
index a10946d03..96bfcbf7c 100644
--- a/restapi/user_login.go
+++ b/restapi/user_login.go
@@ -24,6 +24,8 @@ import (
"net/http"
"strings"
+ "github.com/go-openapi/errors"
+
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/console/models"
@@ -89,6 +91,7 @@ func login(credentials ConsoleCredentialsI, sessionFeatures *auth.SessionFeature
if err != nil {
return nil, err
}
+
// if we made it here, the consoleCredentials work, generate a jwt with claims
token, err := auth.NewEncryptedTokenForClient(&tokens, credentials.GetAccountAccessKey(), sessionFeatures)
if err != nil {
@@ -133,6 +136,13 @@ func getLoginResponse(params authApi.LoginParams) (*models.LoginResponse, *model
ConsoleCredentials: creds,
AccountAccessKey: lr.AccessKey,
}
+
+ credsVerificate, _ := creds.Get()
+
+ if credsVerificate.SessionToken == "" || credsVerificate.SecretAccessKey == "" || credsVerificate.AccessKeyID == "" {
+ return nil, ErrorWithContext(ctx, errors.New(401, "Invalid STS Params"))
+ }
+
} else {
// prepare console credentials
consoleCreds, err = getConsoleCredentials(lr.AccessKey, lr.SecretKey)
diff --git a/swagger.yml b/swagger.yml
index b047b4027..87f1e7266 100644
--- a/swagger.yml
+++ b/swagger.yml
@@ -4351,8 +4351,6 @@ definitions:
type: array
items:
$ref: "#/definitions/redirectRule"
- isDirectPV:
- type: boolean
isK8S:
type: boolean
animatedLogin: