WIP: SAML login
parent
40e915b5f1
commit
4dd0e0a95e
|
@ -21,6 +21,9 @@ JWT_SECRET='secret'
|
|||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
|
||||
# Enable SAML login
|
||||
SAML_LOGIN_URL=
|
||||
|
||||
# @see: https://github.com/calendso/calendso/issues/263
|
||||
# Required for Vercel hosting - set NEXTAUTH_URL to equal your BASE_URL
|
||||
# NEXTAUTH_URL='http://localhost:3000'
|
||||
|
|
|
@ -46,6 +46,9 @@ export enum ErrorCode {
|
|||
export const identityProviderNameMap: { [key in IdentityProvider]: string } = {
|
||||
[IdentityProvider.CAL]: "Cal",
|
||||
[IdentityProvider.GOOGLE]: "Google",
|
||||
[IdentityProvider.SAML]: "SAML",
|
||||
};
|
||||
|
||||
export const isGoogleLoginEnabled = process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET;
|
||||
|
||||
export const isSAMLLoginEnabled = process.env.SAML_LOGIN_URL;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"db-migrate": "yarn prisma migrate dev",
|
||||
"db-seed": "yarn ts-node scripts/seed.ts",
|
||||
"db-nuke": "docker-compose down --volumes --remove-orphans",
|
||||
"dx": "cross-env BASE_URL=http://localhost:3000 JWT_SECRET=secret DATABASE_URL=postgresql://postgres:@localhost:5450/calendso run-s db-up db-migrate db-seed dev",
|
||||
"dx": "cross-env BASE_URL=http://localhost:3000 SAML_LOGIN_URL=http://localhost:5000 JWT_SECRET=secret DATABASE_URL=postgresql://postgres:@localhost:5450/calendso run-s db-up db-migrate db-seed dev",
|
||||
"test": "jest",
|
||||
"test-playwright": "jest --config jest.playwright.config.js",
|
||||
"test-codegen": "yarn playwright codegen http://localhost:3000",
|
||||
|
|
|
@ -2,7 +2,7 @@ import NextAuth from "next-auth";
|
|||
import Providers, { AppProviders } from "next-auth/providers";
|
||||
import { authenticator } from "otplib";
|
||||
|
||||
import { ErrorCode, isGoogleLoginEnabled, Session, verifyPassword } from "@lib/auth";
|
||||
import { ErrorCode, isGoogleLoginEnabled, isSAMLLoginEnabled, Session, verifyPassword } from "@lib/auth";
|
||||
import { symmetricDecrypt } from "@lib/crypto";
|
||||
import prisma from "@lib/prisma";
|
||||
import slugify from "@lib/slugify";
|
||||
|
@ -91,6 +91,29 @@ if (isGoogleLoginEnabled) {
|
|||
);
|
||||
}
|
||||
|
||||
if (isSAMLLoginEnabled) {
|
||||
providers.push({
|
||||
id: "boxyhq",
|
||||
name: "BoxyHQ",
|
||||
type: "oauth",
|
||||
version: "2.0",
|
||||
params: {
|
||||
grant_type: "authorization_code",
|
||||
},
|
||||
accessTokenUrl: `${process.env.SAML_LOGIN_URL}/oauth/token`,
|
||||
authorizationUrl: `${process.env.SAML_LOGIN_URL}/oauth/authorize?response_type=code&provider=saml`,
|
||||
profileUrl: `${process.env.SAML_LOGIN_URL}/oauth/userinfo`,
|
||||
profile: (profile) => {
|
||||
return {
|
||||
...profile,
|
||||
name: `${profile.firstName} ${profile.lastName}`,
|
||||
};
|
||||
},
|
||||
clientId: "tenant=boxyhq.com&product=demo",
|
||||
clientSecret: "dummy",
|
||||
});
|
||||
}
|
||||
|
||||
export default NextAuth({
|
||||
session: {
|
||||
jwt: true,
|
||||
|
|
|
@ -3,14 +3,14 @@ import Link from "next/link";
|
|||
import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
|
||||
import { ErrorCode, getSession, isGoogleLoginEnabled } from "@lib/auth";
|
||||
import { ErrorCode, getSession, isGoogleLoginEnabled, isSAMLLoginEnabled } from "@lib/auth";
|
||||
import { useLocale } from "@lib/hooks/useLocale";
|
||||
|
||||
import AddToHomescreen from "@components/AddToHomescreen";
|
||||
import Loader from "@components/Loader";
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
|
||||
export default function Login({ csrfToken, isGoogleLoginEnabled }) {
|
||||
export default function Login({ csrfToken, isGoogleLoginEnabled, isSAMLLoginEnabled }) {
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
const [email, setEmail] = useState("");
|
||||
|
@ -180,6 +180,13 @@ export default function Login({ csrfToken, isGoogleLoginEnabled }) {
|
|||
Sign in with Google
|
||||
</button>
|
||||
)}
|
||||
{isSAMLLoginEnabled && (
|
||||
<button
|
||||
onClick={async () => await signIn("boxyhq")}
|
||||
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-sm shadow-sm text-sm font-medium text-black bg-secondary-50 hover:bg-secondary-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black">
|
||||
{t("signin_with_saml")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-4 text-neutral-600 text-center text-sm">
|
||||
{t("dont_have_an_account")} {/* replace this with your account creation flow */}
|
||||
|
@ -207,5 +214,6 @@ Login.getInitialProps = async (context) => {
|
|||
return {
|
||||
csrfToken: await getCsrfToken(context),
|
||||
isGoogleLoginEnabled,
|
||||
isSAMLLoginEnabled,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import { signIn } from "next-auth/client";
|
|||
import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
|
||||
import { getSession, isGoogleLoginEnabled } from "@lib/auth";
|
||||
import { getSession, isGoogleLoginEnabled, isSAMLLoginEnabled } from "@lib/auth";
|
||||
import { useLocale } from "@lib/hooks/useLocale";
|
||||
import prisma from "@lib/prisma";
|
||||
|
||||
|
@ -136,6 +136,13 @@ export default function Signup(props) {
|
|||
{t("signin_with_google")}
|
||||
</button>
|
||||
)}
|
||||
{props.isSAMLLoginEnabled && (
|
||||
<button
|
||||
onClick={async () => await signIn("boxyhq")}
|
||||
className="w-full mt-6 flex justify-center py-2 px-4 border border-transparent rounded-sm shadow-sm text-sm font-medium text-black bg-secondary-50 hover:bg-secondary-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black">
|
||||
{t("signin_with_saml")}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -187,5 +194,5 @@ export async function getServerSideProps(ctx) {
|
|||
};
|
||||
}
|
||||
|
||||
return { props: { isGoogleLoginEnabled, email: verificationRequest.identifier } };
|
||||
return { props: { isGoogleLoginEnabled, isSAMLLoginEnabled, email: verificationRequest.identifier } };
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
-- add the new value to the existing type
|
||||
ALTER TYPE "IdentityProvider" ADD VALUE 'SAML';
|
|
@ -66,6 +66,7 @@ enum UserPlan {
|
|||
enum IdentityProvider {
|
||||
CAL
|
||||
GOOGLE
|
||||
SAML
|
||||
}
|
||||
|
||||
model User {
|
||||
|
|
|
@ -516,6 +516,7 @@
|
|||
"settings": "Settings",
|
||||
"google_account": "Your account was created using Google.",
|
||||
"signin_with_google": "Sign in with Google",
|
||||
"signin_with_saml": "Sign in with SAML",
|
||||
"next_step": "Skip step",
|
||||
"prev_step": "Prev step",
|
||||
"installed": "Installed",
|
||||
|
|
Loading…
Reference in New Issue