forked from vercel/ai-chatbot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathauth.ts
126 lines (119 loc) · 4.67 KB
/
auth.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import AzureAd from "next-auth/providers/azure-ad"
import type { NextAuthConfig, Session } from 'next-auth';
export const config = {
theme: {
logo: 'https://next-auth.js.org/img/logo/logo-sm.png',
},
providers: [
Google({
authorization: {
params: {
access_type: 'offline',
prompt: 'consent',
scope: [
'openid',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/calendar',
// and more scope urls
].join(' '),
response: 'code',
},
},
}),
AzureAd({
clientId: process.env.AUTH_MICROSOFT_ENTRA_ID_ID,
clientSecret: process.env.AUTH_MICROSOFT_ENTRA_ID_SECRET,
tenantId: process.env.AUTH_MICROSOFT_ENTRA_ID_TENANT_ID,
authorization: {
params: {
scope: "openid profile email offline_access",
},
},
})
],
// basePath: '/api/auth',
callbacks: {
authorized({ request, auth }) {
return !!auth;
},
async jwt({ token, user, account }) {
// Initial sign in
if (account && user) {
return {
...token,
access_token: account.access_token,
issued_at: Date.now(),
expires_at: Date.now() + Number(account.expires_in) * 1000, // 3600 seconds
refresh_token: account.refresh_token,
sub: user.id,
};
} else if (Date.now() < Number(token.expires_at)) {
return token;
} else {
console.log('Access token expired getting new one');
try {
const response = await fetch('https://login.microsoftonline.com/0c4da9c5-40ea-4e7d-9c7a-e7308d4f8e38/oauth2/v2.0/token', {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: process.env.AUTH_MICROSOFT_ENTRA_ID_ID as string, // Type assertion
client_secret: process.env.AUTH_MICROSOFT_ENTRA_ID_SECRET as string, // Type assertion
grant_type: 'refresh_token',
refresh_token: token.refresh_token as string, // Type assertion
}),
method: 'POST',
});
// const response = await fetch('https://oauth2.googleapis.com/token', {
// headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
// body: new URLSearchParams({
// client_id: process.env.AUTH_GOOGLE_ID as string, // Type assertion
// client_secret: process.env.AUTH_GOOGLE_SECRET as string, // Type assertion
// grant_type: 'refresh_token',
// refresh_token: token.refresh_token as string, // Type assertion
// }),
// method: 'POST',
// });
const tokens = await response.json();
if (!response.ok) throw tokens;
return {
...token, // Keep the previous token properties
access_token: tokens.access_token,
expires_at: Date.now() + Number(tokens.expires_in) * 1000,
// Fall back to old refresh token, but note that
// many providers may only allow using a refresh token once.
refresh_token: tokens.refresh_token ?? token.refresh_token,
}; // updated inside our session-token cookie
} catch (error) {
console.error('Error refreshing access token', error);
// The error property will be used client-side to handle the refresh token error
return { ...token, error: 'RefreshAccessTokenError' as const };
}
}
},
async session({ session, token }) {
// This will be accessible in the client side using useSession hook
// So becareful what you return here. Don't return sensitive data.
// The auth() function should return jwt response but instead it returns
// the session object. This is a bug in next-auth.
// Follow this bug https://github.com/nextauthjs/next-auth/issues/9329
return {
...session,
accessToken: String(token.access_token),
refreshToken: String(token.refresh_token),
accessTokenIssuedAt: Number(token.issued_at),
accessTokenExpiresAt: Number(token.expires_at),
userId: String(token.sub),
} satisfies EnrichedSession;
},
},
} satisfies NextAuthConfig;
export interface EnrichedSession extends Session {
accessToken: string;
refreshToken: string;
accessTokenExpiresAt: number;
accessTokenIssuedAt: number;
userId: string;
}
export const { handlers, auth, signIn, signOut } = NextAuth(config);