mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: middleware support for oauth
This commit is contained in:
parent
52f2235942
commit
5ca1ba75e1
15 changed files with 212 additions and 43 deletions
70
apps/web/app/auth/cookies.ts
Normal file
70
apps/web/app/auth/cookies.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { LEARNHOUSE_TOP_DOMAIN } from '@services/config/config'
|
||||
|
||||
const cookiePrefix = '__LRN-'
|
||||
const cookieDomain =
|
||||
LEARNHOUSE_TOP_DOMAIN == `.${LEARNHOUSE_TOP_DOMAIN}`
|
||||
const cookieSecure = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? true : true
|
||||
const cookieSameSite = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? 'lax' : 'None'
|
||||
|
||||
export const cookiesOptions = {
|
||||
sessionToken: {
|
||||
name: `__Secure-next-auth.session-token`,
|
||||
options: {
|
||||
domain: cookieDomain,
|
||||
httpOnly: true,
|
||||
sameSite: cookieSameSite,
|
||||
path: '/',
|
||||
secure: cookieSecure,
|
||||
},
|
||||
},
|
||||
callbackUrl: {
|
||||
name: `__Secure-next-auth.callback-url`,
|
||||
options: {
|
||||
domain: cookieDomain,
|
||||
httpOnly: true,
|
||||
sameSite: cookieSameSite,
|
||||
path: '/',
|
||||
secure: cookieSecure,
|
||||
},
|
||||
},
|
||||
csrfToken: {
|
||||
name: `__Host-next-auth.csrf-token`,
|
||||
options: {
|
||||
domain: cookieDomain,
|
||||
httpOnly: true,
|
||||
sameSite: cookieSameSite,
|
||||
path: '/',
|
||||
secure: cookieSecure,
|
||||
},
|
||||
},
|
||||
pkceCodeVerifier: {
|
||||
name: `${cookiePrefix}next-auth.pkce.code_verifier`,
|
||||
options: {
|
||||
domain: cookieDomain,
|
||||
httpOnly: true,
|
||||
sameSite: cookieSameSite,
|
||||
path: '/',
|
||||
secure: cookieSecure,
|
||||
},
|
||||
},
|
||||
state: {
|
||||
name: `${cookiePrefix}next-auth.state`,
|
||||
options: {
|
||||
domain: cookieDomain,
|
||||
httpOnly: true,
|
||||
sameSite: cookieSameSite,
|
||||
path: '/',
|
||||
secure: cookieSecure,
|
||||
},
|
||||
},
|
||||
nonce: {
|
||||
name: `${cookiePrefix}next-auth.nonce`,
|
||||
options: {
|
||||
domain: cookieDomain,
|
||||
httpOnly: true,
|
||||
sameSite: cookieSameSite,
|
||||
path: '/',
|
||||
secure: cookieSecure,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4,11 +4,16 @@ import {
|
|||
loginAndGetToken,
|
||||
loginWithOAuthToken,
|
||||
} from '@services/auth/auth'
|
||||
import { LEARNHOUSE_TOP_DOMAIN, getUriWithOrg } from '@services/config/config'
|
||||
import { getResponseMetadata } from '@services/utils/ts/requests'
|
||||
import CredentialsProvider from 'next-auth/providers/credentials'
|
||||
import GoogleProvider from 'next-auth/providers/google'
|
||||
import { cookiesOptions } from './cookies'
|
||||
|
||||
const isDevEnv = LEARNHOUSE_TOP_DOMAIN == 'localhost' ? true : false
|
||||
|
||||
export const nextAuthOptions = {
|
||||
debug: true,
|
||||
providers: [
|
||||
CredentialsProvider({
|
||||
// The name to display on the sign in form (e.g. 'Sign in with...')
|
||||
|
|
@ -41,6 +46,24 @@ export const nextAuthOptions = {
|
|||
clientSecret: process.env.LEARNHOUSE_GOOGLE_CLIENT_SECRET || '',
|
||||
}),
|
||||
],
|
||||
pages: {
|
||||
signIn: getUriWithOrg('auth', '/'),
|
||||
verifyRequest: getUriWithOrg('auth', '/'),
|
||||
error: getUriWithOrg('auth', '/'), // Error code passed in query string as ?error=
|
||||
},
|
||||
cookies: {
|
||||
sessionToken: {
|
||||
name: `${!isDevEnv ? '__Secure-' : ''}next-auth.session-token`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
// When working on localhost, the cookie domain must be omitted entirely (https://stackoverflow.com/a/1188145)
|
||||
domain: `.${LEARNHOUSE_TOP_DOMAIN}`,
|
||||
secure: !isDevEnv,
|
||||
},
|
||||
},
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, user, account }: any) {
|
||||
// First sign in with Credentials provider
|
||||
|
|
|
|||
|
|
@ -57,16 +57,16 @@ const LoginClient = (props: LoginClientProps) => {
|
|||
redirect: false,
|
||||
email: values.email,
|
||||
password: values.password,
|
||||
callbackUrl: '/'
|
||||
callbackUrl: '/redirect_from_auth'
|
||||
});
|
||||
if (res && res.error) {
|
||||
setError("Wrong Email or password");
|
||||
setIsSubmitting(false);
|
||||
}else {
|
||||
} else {
|
||||
await signIn('credentials', {
|
||||
email: values.email,
|
||||
password: values.password,
|
||||
callbackUrl: '/'
|
||||
callbackUrl: '/redirect_from_auth'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
@ -177,7 +177,7 @@ const LoginClient = (props: LoginClientProps) => {
|
|||
</div>
|
||||
</FormLayout>
|
||||
<div className='flex h-0.5 rounded-2xl bg-slate-100 mt-5 mb-5 mx-10'></div>
|
||||
<button onClick={() => signIn('google')} className="flex justify-center py-3 text-md w-full bg-white text-slate-600 space-x-3 font-semibold text-center p-2 rounded-md shadow hover:cursor-pointer">
|
||||
<button onClick={() => signIn('google', { callbackUrl: '/redirect_from_auth' })} className="flex justify-center py-3 text-md w-full bg-white text-slate-600 space-x-3 font-semibold text-center p-2 rounded-md shadow hover:cursor-pointer">
|
||||
<img src="https://fonts.gstatic.com/s/i/productlogos/googleg/v6/24px.svg" alt="" />
|
||||
<span>Sign in with Google</span>
|
||||
</button>
|
||||
|
|
@ -3,14 +3,14 @@ import LoginClient from './login'
|
|||
import { Metadata } from 'next'
|
||||
|
||||
type MetadataProps = {
|
||||
params: { orgslug: string; courseid: string }
|
||||
params: { orgslug: string }
|
||||
searchParams: { [key: string]: string | string[] | undefined }
|
||||
}
|
||||
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: MetadataProps): Promise<Metadata> {
|
||||
const orgslug = params.orgslug
|
||||
export async function generateMetadata(params: MetadataProps): Promise<Metadata> {
|
||||
const orgslug = params.searchParams.orgslug
|
||||
|
||||
//const orgslug = params.orgslug
|
||||
// Get Org context information
|
||||
const org = await getOrganizationContextInfo(orgslug, {
|
||||
revalidate: 0,
|
||||
|
|
@ -22,8 +22,8 @@ export async function generateMetadata({
|
|||
}
|
||||
}
|
||||
|
||||
const Login = async (params: any) => {
|
||||
const orgslug = params.params.orgslug
|
||||
const Login = async (params: MetadataProps) => {
|
||||
const orgslug = params.searchParams.orgslug
|
||||
const org = await getOrganizationContextInfo(orgslug, {
|
||||
revalidate: 0,
|
||||
tags: ['organizations'],
|
||||
|
|
@ -17,7 +17,7 @@ export default function Error({
|
|||
|
||||
return (
|
||||
<div>
|
||||
<ErrorUI></ErrorUI>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue