Skip to content

Commit 962d36c

Browse files
authored
Merge pull request #793 from OpenSignLabs/feat_sso
2 parents be93e6a + d071986 commit 962d36c

File tree

14 files changed

+792
-163
lines changed

14 files changed

+792
-163
lines changed

apps/OpenSign/src/App.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import PlaceHolderSign from "./pages/PlaceHolderSign";
1616
import PdfRequestFiles from "./pages/PdfRequestFiles";
1717
import LazyPage from "./primitives/LazyPage";
1818
import { isEnableSubscription } from "./constant/const";
19+
import SSOVerify from "./pages/SSOVerify";
1920
const DebugPdf = lazy(() => import("./pages/DebugPdf"));
2021
const ForgetPassword = lazy(() => import("./pages/ForgetPassword"));
2122
const GuestLogin = lazy(() => import("./pages/GuestLogin"));
@@ -181,6 +182,7 @@ function App() {
181182
element={<PdfRequestFiles />}
182183
/>
183184
</Route>
185+
<Route path="/sso" element={<SSOVerify />} />
184186
<Route path="*" element={<PageNotFound />} />
185187
</Routes>
186188
</BrowserRouter>

apps/OpenSign/src/components/Header.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ const Header = ({ showSidebar }) => {
4444

4545
const closeDropdown = () => {
4646
setIsOpen(false);
47-
Parse.User.logOut();
47+
if (Parse?.User?.current()) {
48+
Parse.User.logOut();
49+
}
4850
let appdata = localStorage.getItem("userSettings");
4951
let applogo = localStorage.getItem("appLogo");
5052
let appName = localStorage.getItem("appName");

apps/OpenSign/src/components/sidebar/Menu.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ const Menu = ({ item, isOpen, closeSidebar }) => {
1010
? `/${item.pageType}/${item.objectId}`
1111
: `/${item.objectId}`
1212
}
13-
className="mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 cursor-pointer focus:text-[#0056b3] focus:bg-[#eef1f5]"
13+
className={({ isActive }) =>
14+
`${
15+
isActive ? "text-[#0056b3] bg-[#eef1f5]" : ""
16+
} mx-auto flex items-center hover:bg-[#eef1f5] p-3 lg:p-4 cursor-pointer`
17+
}
1418
onClick={closeSidebar}
1519
tabIndex={isOpen ? 0 : -1}
1620
role="menuitem"

apps/OpenSign/src/constant/Utils.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@ export const isMobile = window.innerWidth < 767;
1212
export const textInputWidget = "text input";
1313
export const textWidget = "text";
1414
export const radioButtonWidget = "radio button";
15-
export const openInNewTab = (url) => {
16-
window.open(url, "_blank", "noopener,noreferrer");
15+
export const openInNewTab = (url, target) => {
16+
if (target) {
17+
window.open(url, target, "noopener,noreferrer");
18+
} else {
19+
window.open(url, "_blank", "noopener,noreferrer");
20+
}
1721
};
1822

1923
export async function fetchSubscription(

apps/OpenSign/src/pages/Login.js

Lines changed: 137 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Alert from "../primitives/Alert";
1919
import { appInfo } from "../constant/appinfo";
2020
import { fetchAppInfo } from "../redux/reducers/infoReducer";
2121
import { showTenant } from "../redux/reducers/ShowTenant";
22-
import { fetchSubscription, getAppLogo } from "../constant/Utils";
22+
import { fetchSubscription, getAppLogo, openInNewTab } from "../constant/Utils";
2323
function Login() {
2424
const navigate = useNavigate();
2525
const location = useLocation();
@@ -45,6 +45,7 @@ function Login() {
4545
});
4646
const [isModal, setIsModal] = useState(false);
4747
const [image, setImage] = useState();
48+
const [isLoginSSO, setIsLoginSSO] = useState(false);
4849

4950
useEffect(() => {
5051
if (localStorage.getItem("accesstoken")) {
@@ -1016,8 +1017,9 @@ function Login() {
10161017

10171018
const handleCloseModal = () => {
10181019
setIsModal(false);
1019-
Parse.User.logOut();
1020-
1020+
if (Parse?.User?.current()) {
1021+
Parse.User.logOut();
1022+
}
10211023
let appdata = localStorage.getItem("userSettings");
10221024
let applogo = localStorage.getItem("appLogo");
10231025
let appName = localStorage.getItem("appName");
@@ -1040,6 +1042,24 @@ function Login() {
10401042
localStorage.setItem("baseUrl", baseUrl);
10411043
localStorage.setItem("parseAppId", appid);
10421044
};
1045+
1046+
// `handleSignInWithSSO` is trigger when user click sign in with sso and open sso authorize endpoint
1047+
const handleSignInWithSSO = () => {
1048+
if (state?.email) {
1049+
setIsLoginSSO(true);
1050+
const encodedEmail = encodeURIComponent(state.email);
1051+
const clientUrl = window.location.origin;
1052+
const domain = state.email.split("@")?.pop();
1053+
const ssoApiUrl =
1054+
process.env.SSO_API_URL || "https://sso.opensignlabs.com/api";
1055+
openInNewTab(
1056+
`${ssoApiUrl}/oauth/authorize?response_type=code&provider=saml&tenant=${domain}&product=OpenSign&redirect_uri=${clientUrl}/sso&state=${encodedEmail}`,
1057+
"_self"
1058+
);
1059+
} else {
1060+
alert("Please provide email.");
1061+
}
1062+
};
10431063
return (
10441064
<div className="bg-white">
10451065
<Title title={"Login Page"} />
@@ -1087,136 +1107,131 @@ function Login() {
10871107
</div>
10881108
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-2">
10891109
<div>
1090-
<div>
1091-
<form onSubmit={handleSubmit} aria-label="Login Form">
1092-
<h1 className="text-[30px] mt-6">Welcome Back!</h1>
1093-
<fieldset>
1094-
<legend className="text-[12px] text-[#878787]">
1095-
Login to your account
1096-
</legend>
1097-
<div className="px-6 py-4 outline outline-1 outline-slate-300/50 my-2 rounded shadow-md">
1098-
<label className="block text-xs" htmlFor="email">
1099-
Username
1100-
</label>
1101-
<input
1102-
id="email"
1103-
type="text"
1104-
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs"
1105-
name="email"
1106-
value={state.email}
1107-
onChange={handleChange}
1108-
required
1109-
/>
1110-
<hr className="my-2 border-none" />
1111-
<label className="block text-xs" htmlFor="password">
1112-
Password
1113-
</label>
1114-
<div className="relative">
1115-
<input
1116-
id="password"
1117-
type={state.passwordVisible ? "text" : "password"}
1118-
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs"
1119-
name="password"
1120-
value={state.password}
1121-
onChange={handleChange}
1122-
required
1123-
/>
1124-
<span
1125-
className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer ${
1126-
state.passwordVisible
1127-
? "text-[#007bff]"
1128-
: "text-black"
1129-
}`}
1130-
onClick={togglePasswordVisibility}
1131-
>
1132-
{state.passwordVisible ? (
1133-
<i className="fa fa-eye-slash text-xs pb-1" /> // Close eye icon
1134-
) : (
1135-
<i className="fa fa-eye text-xs pb-1 " /> // Open eye icon
1136-
)}
1137-
</span>
1138-
</div>
1139-
<div className="relative mt-1">
1140-
<NavLink
1141-
to="/forgetpassword"
1142-
className="text-[13px] text-[#002864] hover:underline underline-offset-1 focus:outline-none cursor-pointer ml-1"
1143-
>
1144-
Forgot Password?
1145-
</NavLink>
1146-
</div>
1110+
<form onSubmit={handleSubmit} aria-label="Login Form">
1111+
<h1 className="text-[30px] mt-6">Welcome Back!</h1>
1112+
<fieldset>
1113+
<legend className="text-[12px] text-[#878787]">
1114+
Login to your account
1115+
</legend>
1116+
<div className="px-6 py-4 outline outline-1 outline-slate-300/50 my-2 rounded shadow-md">
1117+
<label className="block text-xs" htmlFor="email">
1118+
Email
1119+
</label>
1120+
<input
1121+
id="email"
1122+
type="text"
1123+
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs"
1124+
name="email"
1125+
value={state.email}
1126+
onChange={handleChange}
1127+
required
1128+
/>
1129+
<hr className="my-2 border-none" />
1130+
{isLoginSSO && (
1131+
<>
1132+
<label className="block text-xs" htmlFor="password">
1133+
Password
1134+
</label>
1135+
<div className="relative">
1136+
<input
1137+
id="password"
1138+
type={
1139+
state.passwordVisible ? "text" : "password"
1140+
}
1141+
className="px-3 py-2 w-full border-[1px] border-gray-300 rounded text-xs"
1142+
name="password"
1143+
value={state.password}
1144+
onChange={handleChange}
1145+
required
1146+
/>
1147+
<span
1148+
className={`absolute top-[50%] right-[10px] -translate-y-[50%] cursor-pointer ${
1149+
state.passwordVisible
1150+
? "text-[#007bff]"
1151+
: "text-black"
1152+
}`}
1153+
onClick={togglePasswordVisibility}
1154+
>
1155+
{state.passwordVisible ? (
1156+
<i className="fa fa-eye-slash text-xs pb-1" /> // Close eye icon
1157+
) : (
1158+
<i className="fa fa-eye text-xs pb-1 " /> // Open eye icon
1159+
)}
1160+
</span>
1161+
</div>
1162+
</>
1163+
)}
1164+
<div className="relative mt-1">
1165+
<NavLink
1166+
to="/forgetpassword"
1167+
className="text-[13px] text-[#002864] hover:underline underline-offset-1 focus:outline-none cursor-pointer ml-1"
1168+
>
1169+
Forgot Password?
1170+
</NavLink>
11471171
</div>
1148-
</fieldset>
1149-
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2">
1150-
<button
1151-
type="submit"
1152-
className="rounded-sm bg-[#3ac9d6] text-white w-full py-3 shadow outline-none uppercase focus:ring-2 focus:ring-blue-600"
1153-
disabled={state.loading}
1154-
>
1155-
{state.loading ? "Loading..." : "Login"}
1156-
</button>
1157-
<NavLink
1158-
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
1159-
to={
1160-
location.search
1161-
? "/signup" + location.search
1162-
: "/signup"
1163-
}
1164-
style={width < 768 ? { textAlign: "center" } : {}}
1165-
>
1166-
Create Account
1167-
</NavLink>
11681172
</div>
1169-
</form>
1170-
<br />
1171-
{(appInfo.fbAppId || appInfo.googleClietId) && (
1172-
<div className="text-sm flex justify-center items-center">
1173-
<hr className="border-[1px] border-gray-300 w-full" />
1174-
<span className="px-2 text-gray-500 cursor-default">
1175-
OR
1176-
</span>
1177-
<hr className="border-[1px] border-gray-300 w-full" />
1178-
</div>
1179-
)}
1180-
<br />
1181-
<div
1182-
style={{
1183-
textAlign: "center",
1184-
display: "flex",
1185-
alignItems: "center",
1186-
justifyContent: "center"
1187-
}}
1188-
>
1189-
{/* {appInfo.fbAppId && appInfo.fbAppId !== "" ? (
1173+
</fieldset>
1174+
<div className="flex flex-col md:flex-row justify-between items-stretch gap-8 text-center text-xs font-bold mt-2">
1175+
<button
1176+
type="submit"
1177+
className="rounded-sm bg-[#3ac9d6] text-white w-full py-3 shadow outline-none uppercase focus:ring-2 focus:ring-blue-600"
1178+
disabled={state.loading}
1179+
>
1180+
{state.loading ? "Loading..." : "Login"}
1181+
</button>
1182+
<NavLink
1183+
className="rounded-sm cursor-pointer bg-white border-[1px] border-[#15b4e9] text-[#15b4e9] w-full py-3 shadow uppercase"
1184+
to={
1185+
location.search
1186+
? "/signup" + location.search
1187+
: "/signup"
1188+
}
1189+
style={width < 768 ? { textAlign: "center" } : {}}
1190+
>
1191+
Create Account
1192+
</NavLink>
1193+
</div>
1194+
</form>
1195+
<br />
1196+
{appInfo.googleClietId && (
1197+
<div className="text-sm flex justify-center items-center">
1198+
<hr className="border-[1px] border-gray-300 w-full" />
1199+
<span className="px-2 text-gray-500 cursor-default">
1200+
OR
1201+
</span>
1202+
<hr className="border-[1px] border-gray-300 w-full" />
1203+
</div>
1204+
)}
1205+
<br />
1206+
<div className="flex flex-col justify-center items-center gap-y-3">
1207+
{/* {appInfo?.fbAppId && (
11901208
<LoginFacebook
11911209
FBCred={appInfo.fbAppId}
11921210
thirdpartyLoginfn={thirdpartyLoginfn}
11931211
thirdpartyLoader={state.thirdpartyLoader}
11941212
setThirdpartyLoader={setThirdpartyLoader}
11951213
/>
1196-
) : null} */}
1197-
</div>
1198-
<div style={{ margin: "10px 0" }}></div>
1199-
<div
1200-
style={{
1201-
textAlign: "center",
1202-
display: "flex",
1203-
alignItems: "center",
1204-
justifyContent: "center"
1205-
}}
1206-
>
1207-
{appInfo.googleClietId && appInfo.googleClietId !== "" ? (
1208-
<GoogleSignInBtn
1209-
GoogleCred={appInfo.googleClietId}
1210-
thirdpartyLoginfn={thirdpartyLoginfn}
1211-
thirdpartyLoader={state.thirdpartyLoader}
1212-
setThirdpartyLoader={setThirdpartyLoader}
1213-
/>
1214-
) : null}
1215-
</div>
1214+
)} */}
1215+
{appInfo?.googleClietId && (
1216+
<GoogleSignInBtn
1217+
GoogleCred={appInfo.googleClietId}
1218+
thirdpartyLoginfn={thirdpartyLoginfn}
1219+
thirdpartyLoader={state.thirdpartyLoader}
1220+
setThirdpartyLoader={setThirdpartyLoader}
1221+
/>
1222+
)}
1223+
{isEnableSubscription && (
1224+
<div
1225+
className="cursor-pointer border-[1px] border-gray-300 rounded px-[40px] py-2 font-semibold text-sm hover:border-[#d2e3fc] hover:bg-[#ecf3feb7]"
1226+
onClick={() => handleSignInWithSSO()}
1227+
>
1228+
Sign in with SSO
1229+
</div>
1230+
)}
12161231
</div>
12171232
</div>
12181233
{width >= 768 && (
1219-
<div className="self-center">
1234+
<div className="place-self-center">
12201235
<div className="mx-auto md:w-[300px] lg:w-[400px] xl:w-[500px]">
12211236
<img
12221237
src={login_img}

0 commit comments

Comments
 (0)