github.com/minio/console@v1.4.1/web-app/src/screens/LoginPage/LoginCallback.tsx (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import React, { Fragment, useEffect, useState } from "react"; 18 import styled from "styled-components"; 19 import { useNavigate } from "react-router-dom"; 20 import api from "../../common/api"; 21 import { baseUrl } from "../../history"; 22 import { Box, Button, LoginWrapper, WarnIcon } from "mds"; 23 import { getLogoVar } from "../../config"; 24 import get from "lodash/get"; 25 26 const CallBackContainer = styled.div(({ theme }) => ({ 27 "& .errorDescription": { 28 fontStyle: "italic", 29 transition: "all .2s ease-in-out", 30 padding: "0 15px", 31 marginTop: 5, 32 overflow: "auto", 33 }, 34 "& .errorLabel": { 35 color: get(theme, "fontColor", "#000"), 36 fontSize: 18, 37 fontWeight: "bold", 38 marginLeft: 5, 39 }, 40 "& .simpleError": { 41 marginTop: 5, 42 padding: "2px 5px", 43 fontSize: 16, 44 color: get(theme, "fontColor", "#000"), 45 }, 46 "& .messageIcon": { 47 color: get(theme, "signalColors.danger", "#C72C48"), 48 display: "flex", 49 "& svg": { 50 width: 32, 51 height: 32, 52 }, 53 }, 54 "& .errorTitle": { 55 display: "flex", 56 alignItems: "center", 57 borderBottom: 15, 58 }, 59 })); 60 61 const LoginCallback = () => { 62 const navigate = useNavigate(); 63 64 const [error, setError] = useState<string>(""); 65 const [errorDescription, setErrorDescription] = useState<string>(""); 66 const [loading, setLoading] = useState<boolean>(true); 67 68 useEffect(() => { 69 if (loading) { 70 const queryString = window.location.search; 71 const urlParams = new URLSearchParams(queryString); 72 const code = urlParams.get("code"); 73 const state = urlParams.get("state"); 74 const error = urlParams.get("error"); 75 const errorDescription = urlParams.get("errorDescription"); 76 if (error || errorDescription) { 77 setError(error || ""); 78 setErrorDescription(errorDescription || ""); 79 setLoading(false); 80 } else { 81 api 82 .invoke("POST", "/api/v1/login/oauth2/auth", { code, state }) 83 .then(() => { 84 // We push to history the new URL. 85 let targetPath = "/"; 86 if ( 87 localStorage.getItem("redirect-path") && 88 localStorage.getItem("redirect-path") !== "" 89 ) { 90 targetPath = `${localStorage.getItem("redirect-path")}`; 91 localStorage.setItem("redirect-path", ""); 92 } 93 if (state) { 94 localStorage.setItem("auth-state", state); 95 } 96 setLoading(false); 97 navigate(targetPath); 98 }) 99 .catch((error) => { 100 setError(error.errorMessage); 101 setErrorDescription(error.detailedError); 102 setLoading(false); 103 }); 104 } 105 } 106 }, [loading, navigate]); 107 return error !== "" || errorDescription !== "" ? ( 108 <Fragment> 109 <LoginWrapper 110 logoProps={{ applicationName: "console", subVariant: getLogoVar() }} 111 form={ 112 <CallBackContainer> 113 <div className={"errorTitle"}> 114 <span className={"messageIcon"}> 115 <WarnIcon /> 116 </span> 117 <span className={"errorLabel"}>Error from IDP</span> 118 </div> 119 <div className={"simpleError"}>{error}</div> 120 <Box className={"errorDescription"}>{errorDescription}</Box> 121 <Button 122 id={"back-to-login"} 123 onClick={() => { 124 window.location.href = `${baseUrl}login`; 125 }} 126 type="submit" 127 variant="callAction" 128 fullWidth 129 > 130 Back to Login 131 </Button> 132 </CallBackContainer> 133 } 134 promoHeader={ 135 <span style={{ fontSize: 28 }}>High-Performance Object Store</span> 136 } 137 promoInfo={ 138 <span style={{ fontSize: 14, lineHeight: 1 }}> 139 MinIO is a cloud-native object store built to run on any 140 infrastructure - public, private or edge clouds. Primary use cases 141 include data lakes, databases, AI/ML, SaaS applications and fast 142 backup & recovery. MinIO is dual licensed under GNU AGPL v3 and 143 commercial license. To learn more, visit{" "} 144 <a href={"https://min.io/?ref=con"} target="_blank" rel="noopener"> 145 www.min.io 146 </a> 147 . 148 </span> 149 } 150 backgroundAnimation={false} 151 /> 152 </Fragment> 153 ) : null; 154 }; 155 156 export default LoginCallback;