Did the dangerous thing

This commit is contained in:
Fergal Moran
2023-08-20 01:27:55 +01:00
parent fefe7adc5b
commit 92891361ae
4 changed files with 82 additions and 62 deletions

View File

@@ -4,6 +4,14 @@ import type LiveShowModel from "./live-show";
import type MixModel from "./mix"; import type MixModel from "./mix";
import type UserModel from "./user"; import type UserModel from "./user";
import type ShowStatus from "./show-status"; import type ShowStatus from "./show-status";
import type TokenPayload from "./token-payload";
export type { LiveShowModel, UserModel, ChatModel, MixModel, AuthTokenModel }; export type {
LiveShowModel,
UserModel,
ChatModel,
MixModel,
AuthTokenModel,
TokenPayload,
};
export { ShowStatus }; export { ShowStatus };

View File

@@ -0,0 +1,9 @@
type TokenPayload = {
name: string;
email: string;
displayName: string;
profileImage: string;
slug: string;
};
export default TokenPayload;

View File

@@ -1,29 +1,28 @@
import { type AuthTokenModel } from "@/lib/models"; import NextAuth, { type AuthOptions } from "next-auth";
import type { Session, AuthOptions } from "next-auth"; import GoogleProvider from "next-auth/providers/google";
import AuthService from "../api/auth-service";
import jwt_decode, { type JwtPayload } from "jwt-decode";
import CredentialsProvider from "next-auth/providers/credentials"; import CredentialsProvider from "next-auth/providers/credentials";
import ProfileService from "../api/profile-service"; import jwt_decode, { type JwtPayload } from "jwt-decode";
import { type JWT } from "next-auth/jwt";
import logger from "@/lib/logger"; import logger from "@/lib/logger";
import AuthService from "../api/auth-service";
import { TokenPayload } from "@/lib/models";
export const authOptions: AuthOptions = { export const authOptions: AuthOptions = {
secret: process.env.NEXTAUTH_SECRET,
debug: process.env.NODE_ENV === "development",
session: { session: {
maxAge: 30 * 24 * 60 * 60, //30 days maxAge: 30 * 24 * 60 * 60, //30 days
updateAge: 24 * 60 * 60, // 24 hours updateAge: 24 * 60 * 60, // 24 hours
}, },
pages: { pages: {
signIn: "/auth/login", signIn: "/auth/login",
newUser: "/auth/register",
signOut: "/",
}, },
providers: [ providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
}),
CredentialsProvider({ CredentialsProvider({
name: "Email and Password", name: "Email and Password",
credentials: { credentials: {
username: { userName: {
label: "Username", label: "Username",
type: "text", type: "text",
placeholder: "Username or email address", placeholder: "Username or email address",
@@ -38,47 +37,35 @@ export const authOptions: AuthOptions = {
logger.info({ authorize: "Authorizing" }); logger.info({ authorize: "Authorizing" });
try { try {
if (!credentials) { if (!credentials) {
return null; return false;
} }
const token = await new AuthService().getAuthToken( const token = await new AuthService().getAuthToken(
credentials.username, credentials.userName,
credentials.password, credentials.password,
); );
if (!token) { if (!token) {
return null; return null;
} }
const decodedToken = jwt_decode<JwtPayload & TokenPayload>(
const decodedToken = jwt_decode<JwtPayload & AuthTokenModel>(
token.access_token, token.access_token,
); );
if (decodedToken && decodedToken.sub) { if (decodedToken) {
// const session: Session = { const profile = {
// id: decodedToken.sub as string, id: decodedToken.sub,
// accessToken: token.access_token, name: decodedToken.name,
// expires: `${token.expires_in}`, displayName: decodedToken.displayName,
// user: {
// id: decodedToken.id,
// email: decodedToken.email,
// username: decodedToken.name,
// name: decodedToken.displayName,
// slug: decodedToken.slug,
// profileImage: decodedToken.profileImage,
// accessToken: token.access_token,
// },
// };
const r = {
id: decodedToken.id,
email: decodedToken.email, email: decodedToken.email,
username: decodedToken.name,
name: decodedToken.displayName,
slug: decodedToken.slug,
profileImage: decodedToken.profileImage, profileImage: decodedToken.profileImage,
slug: decodedToken.slug,
accessToken: token.access_token, accessToken: token.access_token,
accessTokenExpires: token.expires_in,
}; };
logger.debug("config", "authorize_returns", r);
return Promise.resolve(r); return profile;
} else {
return false;
} }
} catch (err) { } catch (err) {
logger.error(`Error authorizing: ${err}`); logger.error(`Error authorizing: ${err}`);
@@ -88,23 +75,40 @@ export const authOptions: AuthOptions = {
}), }),
], ],
callbacks: { callbacks: {
async session({ session, token }: { session: Session; token: JWT }) { async signIn({ account, profile }) {
const profile = await new ProfileService( if (account && account.provider === "google") {
session.accessToken, return false;
).getProfile();
if (!profile) {
return Promise.resolve(session);
} }
session.user.profile = profile; return true;
logger.debug("config", "callback_session_Returns", session); },
async session({ session, token }) {
session.user.accessToken = token.accessToken as string;
session.user.displayName = token.displayName as string;
session.user.profileImage = token.profileImage as string;
session.user.slug = token.slug as string;
if (session.user.accessToken) {
const authService = new AuthService(session.user.accessToken);
const profile = await authService.getUser();
session.user.profile = profile;
}
// session.user.refreshToken = token.refreshToken;
// session.user.accessTokenExpires = token.accessTokenExpires;
return session; return session;
}, },
jwt: async ({ user, token }): Promise<JWT> => { jwt: async ({ token, user, account }) => {
if (user) { if (account && user) {
token.user = user; return {
...token,
accessToken: user.accessToken,
displayName: user.displayName,
profileImage: user.profileImage,
slug: user.slug,
};
} }
logger.debug("config", "callback_jwt_Returns", token); return token;
return Promise.resolve(token);
}, },
}, },
}; };
export default NextAuth(authOptions);

View File

@@ -1,23 +1,22 @@
import { type UserModel } from "@lib/data/models";
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
import NextAuth, { type DefaultSession } from "next-auth"; import NextAuth from "next-auth";
import type { UserModel } from "@/lib/models";
declare module "next-auth" { declare module "next-auth" {
/** /**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/ */
interface Session { interface Session {
id: string; user: User;
accessToken: string;
user: User & DefaultSession["user"];
} }
interface User { interface User {
username: string; accessToken: string;
slug: string; accessTokenExpires: number;
email: string; email: string;
name: string | null; displayName: string;
profileImage: string | null; profileImage: string;
profile?: UserModel; name: string;
slug: string;
profile: UserModel | undefined;
} }
} }