Skip to content

Commit 53b6963

Browse files
authored
azure auth (#817)
* azure auth * images
1 parent 3c546f2 commit 53b6963

File tree

10 files changed

+98
-18
lines changed

10 files changed

+98
-18
lines changed

frontend/app/sign-in/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ export default async function SignInPage(props: {
1616
if (url.pathname === "/" || url.pathname === "") {
1717
callbackUrl = "/onboarding";
1818
}
19-
} catch {}
19+
} catch { }
2020
}
2121

2222
return (
2323
<SignIn
2424
enableCredentials={isFeatureEnabled(Feature.EMAIL_AUTH)}
2525
enableGithub={isFeatureEnabled(Feature.GITHUB_AUTH)}
2626
enableGoogle={isFeatureEnabled(Feature.GOOGLE_AUTH)}
27+
enableAzure={isFeatureEnabled(Feature.AZURE_AUTH)}
2728
callbackUrl={callbackUrl}
2829
/>
2930
);

frontend/app/sign-up/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ export default async function SignUpPage(props: {
1616
if (url.pathname === "/" || url.pathname === "") {
1717
callbackUrl = "/onboarding";
1818
}
19-
} catch {}
19+
} catch { }
2020
}
2121

2222
return (
2323
<SignUp
2424
enableCredentials={isFeatureEnabled(Feature.EMAIL_AUTH)}
2525
enableGithub={isFeatureEnabled(Feature.GITHUB_AUTH)}
2626
enableGoogle={isFeatureEnabled(Feature.GOOGLE_AUTH)}
27+
enableAzure={isFeatureEnabled(Feature.AZURE_AUTH)}
2728
callbackUrl={callbackUrl}
2829
/>
2930
);

frontend/assets/logo/microsoft.svg

Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"use client";
2+
3+
import Image from "next/image";
4+
5+
import azure from "@/assets/logo/microsoft.svg";
6+
import { Button, type ButtonProps } from "@/components/ui/button";
7+
import { IconSpinner } from "@/components/ui/icons";
8+
import { cn } from "@/lib/utils";
9+
10+
interface AzureButtonProps extends ButtonProps {
11+
text?: string;
12+
isLoading?: boolean;
13+
isDisabled?: boolean;
14+
}
15+
16+
export function AzureButton({
17+
text = "Continue with Microsoft",
18+
className,
19+
onClick,
20+
isLoading,
21+
isDisabled,
22+
...props
23+
}: AzureButtonProps) {
24+
return (
25+
<Button
26+
variant="light"
27+
onClick={onClick}
28+
disabled={isDisabled || isLoading}
29+
className={cn("text-[16px] py-6 px-4 pr-6 w-full", className)}
30+
{...props}
31+
>
32+
<div className="h-5 w-5">
33+
{isLoading ? (
34+
<IconSpinner className="animate-spin" />
35+
) : (
36+
<Image src={azure} alt="Azure Icon" width={20} height={20} />
37+
)}
38+
</div>
39+
<div className="ml-2">{text}</div>
40+
</Button>
41+
);
42+
}

frontend/components/auth/github-button.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ import { cn } from "@/lib/utils";
66

77
interface GitHubSignInButtonProps extends ButtonProps {
88
text?: string;
9-
callbackUrl: string;
109
isLoading?: boolean;
1110
isDisabled?: boolean;
1211
}
1312

1413
export function GitHubButton({
1514
text = "Continue with GitHub",
16-
callbackUrl,
1715
className,
1816
onClick,
1917
isLoading,

frontend/components/auth/google-button.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@ import { cn } from "@/lib/utils";
1010

1111
interface GoogleButtonProps extends ButtonProps {
1212
text?: string;
13-
callbackUrl: string;
1413
isLoading?: boolean;
1514
isDisabled?: boolean;
1615
}
1716

1817
export function GoogleButton({
1918
text = "Continue with Google",
20-
callbackUrl,
2119
className,
2220
onClick,
2321
isLoading,

frontend/components/auth/sign-in.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { signIn } from "next-auth/react";
77
import React, { useState } from "react";
88

99
import logo from "@/assets/logo/logo.svg";
10+
import { AzureButton } from "@/components/auth/azure-button";
1011
import { EmailSignInButton } from "@/components/auth/email-sign-in";
1112
import { GitHubButton } from "@/components/auth/github-button";
1213
import { GoogleButton } from "@/components/auth/google-button";
@@ -16,14 +17,15 @@ interface SignInProps {
1617
callbackUrl: string;
1718
enableGoogle?: boolean;
1819
enableGithub?: boolean;
20+
enableAzure?: boolean;
1921
enableCredentials?: boolean;
2022
}
2123

22-
type Provider = "github" | "google";
24+
type Provider = "github" | "google" | "azure-ad";
2325

2426
const defaultErrorMessage = `Failed to sign in. Please try again.`;
2527

26-
const SignIn = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }: SignInProps) => {
28+
const SignIn = ({ callbackUrl, enableGoogle, enableGithub, enableAzure, enableCredentials }: SignInProps) => {
2729
const searchParams = useSearchParams();
2830
const [error, setError] = useState(searchParams.get("error"));
2931
const [isLoading, setIsLoading] = useState<Provider | string>("");
@@ -58,7 +60,6 @@ const SignIn = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }:
5860
onClick={() => handleSignIn("google")}
5961
isLoading={isLoading === "google"}
6062
isDisabled={!!isLoading}
61-
callbackUrl={callbackUrl}
6263
/>
6364
)}
6465
{enableGithub && (
@@ -69,7 +70,16 @@ const SignIn = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }:
6970
className={cn({
7071
"w-full": enableCredentials,
7172
})}
72-
callbackUrl={callbackUrl}
73+
/>
74+
)}
75+
{enableAzure && (
76+
<AzureButton
77+
onClick={() => handleSignIn("azure-ad")}
78+
isLoading={isLoading === "azure-ad"}
79+
isDisabled={!!isLoading}
80+
className={cn({
81+
"w-full": enableCredentials,
82+
})}
7383
/>
7484
)}
7585
{error && <span className="text-destructive text-xs mt-4">{defaultErrorMessage}</span>}
@@ -85,11 +95,11 @@ const SignIn = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }:
8595
{!enableCredentials && (
8696
<div className="text-sm font-medium text-white/70">
8797
By continuing you agree to our{" "}
88-
<a href="https://docs.lmnr.ai/policies/privacy-policy" target="_blank" className="text-white">
98+
<a href="/policies/privacy" target="_blank" className="text-white">
8999
Privacy Policy
90100
</a>{" "}
91101
and{" "}
92-
<a href="https://docs.lmnr.ai/policies/terms-of-service" target="_blank" className="text-white">
102+
<a href="/policies/terms" target="_blank" className="text-white">
93103
Terms of Service
94104
</a>
95105
</div>

frontend/components/auth/sign-up.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { signIn } from "next-auth/react";
66
import React, { useState } from "react";
77

88
import logo from "@/assets/logo/logo.svg";
9+
import { AzureButton } from "@/components/auth/azure-button";
910
import { EmailSignInButton } from "@/components/auth/email-sign-in";
1011
import { GitHubButton } from "@/components/auth/github-button";
1112
import { GoogleButton } from "@/components/auth/google-button";
@@ -15,14 +16,15 @@ interface SignUpProps {
1516
callbackUrl: string;
1617
enableGoogle?: boolean;
1718
enableGithub?: boolean;
19+
enableAzure?: boolean;
1820
enableCredentials?: boolean;
1921
}
2022

21-
type Provider = "github" | "google";
23+
type Provider = "github" | "google" | "azure-ad";
2224

2325
const defaultErrorMessage = `Failed to sign in. Please try again.`;
2426

25-
const SignUp = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }: SignUpProps) => {
27+
const SignUp = ({ callbackUrl, enableGoogle, enableGithub, enableAzure, enableCredentials }: SignUpProps) => {
2628
const [error, setError] = useState("");
2729
const [isLoading, setIsLoading] = useState<Provider | string>("");
2830

@@ -56,7 +58,6 @@ const SignUp = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }:
5658
onClick={() => handleSignUp("google")}
5759
isLoading={isLoading === "google"}
5860
isDisabled={!!isLoading}
59-
callbackUrl={callbackUrl}
6061
/>
6162
)}
6263
{enableGithub && (
@@ -67,7 +68,16 @@ const SignUp = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }:
6768
className={cn({
6869
"w-full": enableCredentials,
6970
})}
70-
callbackUrl={callbackUrl}
71+
/>
72+
)}
73+
{enableAzure && (
74+
<AzureButton
75+
onClick={() => handleSignUp("azure-ad")}
76+
isLoading={isLoading === "azure-ad"}
77+
isDisabled={!!isLoading}
78+
className={cn({
79+
"w-full": enableCredentials,
80+
})}
7181
/>
7282
)}
7383
{error && <span className="text-destructive text-xs mt-4">{defaultErrorMessage}</span>}
@@ -83,11 +93,11 @@ const SignUp = ({ callbackUrl, enableGoogle, enableGithub, enableCredentials }:
8393
{!enableCredentials && (
8494
<div className="text-sm font-medium text-white/70">
8595
By continuing you agree to our{" "}
86-
<a href="https://docs.lmnr.ai/policies/privacy-policy" target="_blank" className="text-white">
96+
<a href="/policies/privacy" target="_blank" className="text-white">
8797
Privacy Policy
8898
</a>{" "}
8999
and{" "}
90-
<a href="https://docs.lmnr.ai/policies/terms-of-service" target="_blank" className="text-white">
100+
<a href="/policies/terms" target="_blank" className="text-white">
91101
Terms of Service
92102
</a>
93103
</div>

frontend/lib/auth.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import jwt from "jsonwebtoken";
22
import type { NextAuthOptions, User } from "next-auth";
3+
import AzureADProvider from "next-auth/providers/azure-ad";
34
import CredentialsProvider from "next-auth/providers/credentials";
45
import GithubProvider from "next-auth/providers/github";
56
import GoogleProvider from "next-auth/providers/google";
@@ -28,6 +29,15 @@ const getProviders = () => {
2829
clientSecret: process.env.AUTH_GOOGLE_SECRET!,
2930
}),
3031
},
32+
{
33+
feature: Feature.AZURE_AUTH,
34+
provider: () =>
35+
AzureADProvider({
36+
clientId: process.env.AUTH_AZURE_AD_CLIENT_ID!,
37+
clientSecret: process.env.AUTH_AZURE_AD_CLIENT_SECRET!,
38+
tenantId: process.env.AUTH_AZURE_AD_TENANT_ID!,
39+
}),
40+
},
3141
{
3242
feature: Feature.EMAIL_AUTH,
3343
provider: () =>

frontend/lib/features/features.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export const enum Feature {
22
SEND_EMAIL = "SEND_EMAIL",
33
GITHUB_AUTH = "GITHUB_AUTH",
44
GOOGLE_AUTH = "GOOGLE_AUTH",
5+
AZURE_AUTH = "AZURE_AUTH",
56
EMAIL_AUTH = "EMAIL_AUTH",
67
WORKSPACE = "WORKSPACE",
78
SUPABASE = "SUPABASE",
@@ -30,6 +31,10 @@ export const isFeatureEnabled = (feature: Feature) => {
3031
return !!process.env.AUTH_GITHUB_ID && !!process.env.AUTH_GITHUB_SECRET;
3132
}
3233

34+
if (feature === Feature.AZURE_AUTH) {
35+
return !!process.env.AUTH_AZURE_AD_CLIENT_ID && !!process.env.AUTH_AZURE_AD_CLIENT_SECRET && !!process.env.AUTH_AZURE_AD_TENANT_ID;
36+
}
37+
3338
if (feature === Feature.FULL_BUILD) {
3439
const environment = process.env.ENVIRONMENT;
3540
if (!environment) {
@@ -45,5 +50,9 @@ export const isFeatureEnabled = (feature: Feature) => {
4550
);
4651
}
4752

53+
if (feature === Feature.SEND_EMAIL) {
54+
return !!process.env.RESEND_API_KEY;
55+
}
56+
4857
return process.env.ENVIRONMENT === "PRODUCTION";
4958
};

0 commit comments

Comments
 (0)