Skip to content

Commit 88c6210

Browse files
authored
Merge pull request #107 from nileshdev0707/feature/auth_flow
Added authentication flow
2 parents 333bd65 + b05abad commit 88c6210

File tree

14 files changed

+552
-234
lines changed

14 files changed

+552
-234
lines changed

package.json

Lines changed: 57 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,59 @@
11
{
2-
"name": "jiffyscan",
3-
"version": "0.1.0",
4-
"private": true,
5-
"scripts": {
6-
"dev": "next dev",
7-
"build": "next build",
8-
"start": "next start",
9-
"lint": "next lint",
10-
"format": "prettier --check --ignore-path .gitignore .",
11-
"format:fix": "prettier --write --ignore-path .gitignore ."
12-
},
13-
"dependencies": {
14-
"@emotion/react": "^11.10.6",
15-
"@emotion/styled": "^11.10.6",
16-
"@mui/icons-material": "^5.11.11",
17-
"@mui/material": "^5.11.14",
18-
"@types/memory-cache": "^0.2.2",
19-
"@types/node": "18.15.3",
20-
"@types/react": "18.0.28",
21-
"@types/react-dom": "18.0.11",
22-
"@vercel/analytics": "^0.1.11",
23-
"axios": "^1.3.4",
24-
"chart.js": "^4.2.1",
25-
"ethers": "^5.7.2",
26-
"lodash": "^4.17.21",
27-
"memory-cache": "^0.2.0",
28-
"moment": "^2.29.4",
29-
"moment-timezone": "^0.5.42",
30-
"next": "13.2.4",
31-
"react": "18.2.0",
32-
"react-chartjs-2": "^5.2.0",
33-
"react-dom": "18.2.0",
34-
"react-ga4": "^2.1.0",
35-
"react-google-login": "^5.2.2",
36-
"react-indiana-drag-scroll": "^2.2.0",
37-
"react-loading-skeleton-2": "^1.0.1-1",
38-
"react-modern-drawer": "^1.2.0",
39-
"react-simple-toasts": "^3.2.5",
40-
"react-toastify": "^9.1.2",
41-
"typescript": "4.9.5"
42-
},
43-
"devDependencies": {
44-
"@headlessui/react": "^1.7.13",
45-
"@heroicons/react": "^2.0.16",
46-
"@types/lodash": "^4.14.192",
47-
"autoprefixer": "^10.4.14",
48-
"eslint": "^8.36.0",
49-
"eslint-config-next": "13.2.4",
50-
"postcss": "^8.4.21",
51-
"prettier": "^2.8.6",
52-
"sass": "^1.59.3",
53-
"tailwindcss": "^3.2.7"
54-
}
2+
"name": "jiffyscan",
3+
"version": "0.1.0",
4+
"private": true,
5+
"scripts": {
6+
"dev": "next dev",
7+
"build": "next build",
8+
"start": "next start",
9+
"lint": "next lint",
10+
"format": "prettier --check --ignore-path .gitignore .",
11+
"format:fix": "prettier --write --ignore-path .gitignore ."
12+
},
13+
"dependencies": {
14+
"@aws-sdk/client-cognito-identity-provider": "^3.398.0",
15+
"@emotion/react": "^11.10.6",
16+
"@emotion/styled": "^11.10.6",
17+
"@mui/icons-material": "^5.11.11",
18+
"@mui/material": "^5.11.14",
19+
"@types/memory-cache": "^0.2.2",
20+
"@types/node": "18.15.3",
21+
"@types/react": "18.0.28",
22+
"@types/react-dom": "18.0.11",
23+
"@vercel/analytics": "^0.1.11",
24+
"aws-amplify": "^5.3.10",
25+
"aws-sdk": "^2.1446.0",
26+
"axios": "^1.3.4",
27+
"chart.js": "^4.2.1",
28+
"ethers": "^5.7.2",
29+
"lodash": "^4.17.21",
30+
"memory-cache": "^0.2.0",
31+
"moment": "^2.29.4",
32+
"moment-timezone": "^0.5.42",
33+
"next": "13.2.4",
34+
"next-auth": "^4.23.1",
35+
"react": "18.2.0",
36+
"react-chartjs-2": "^5.2.0",
37+
"react-dom": "18.2.0",
38+
"react-ga4": "^2.1.0",
39+
"react-google-login": "^5.2.2",
40+
"react-indiana-drag-scroll": "^2.2.0",
41+
"react-loading-skeleton-2": "^1.0.1-1",
42+
"react-modern-drawer": "^1.2.0",
43+
"react-simple-toasts": "^3.2.5",
44+
"react-toastify": "^9.1.2",
45+
"typescript": "4.9.5"
46+
},
47+
"devDependencies": {
48+
"@headlessui/react": "^1.7.13",
49+
"@heroicons/react": "^2.0.16",
50+
"@types/lodash": "^4.14.192",
51+
"autoprefixer": "^10.4.14",
52+
"eslint": "^8.36.0",
53+
"eslint-config-next": "13.2.4",
54+
"postcss": "^8.4.21",
55+
"prettier": "^2.8.6",
56+
"sass": "^1.59.3",
57+
"tailwindcss": "^3.2.7"
58+
}
5559
}

public/images/google.svg

Lines changed: 13 additions & 0 deletions
Loading

src/components/common/Spinner.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import React from 'react';
22

3-
const Spinner = () => {
3+
const Spinner = ({width = '3rem', height = '3rem'}) => {
4+
const spinnerStyle: React.CSSProperties = {
5+
width,
6+
height,
7+
};
48
return (
5-
<div className="h-[177px] bg-white flex items-center justify-center">
6-
<div></div>
7-
<div
8-
className="w-12 h-12 rounded-full animate-spin
9+
<div
10+
style={spinnerStyle}
11+
className="w-12 h-12 rounded-full animate-spin
912
border-2 border-solid border-blue-500 border-t-transparent shadow-md"
10-
></div>
11-
</div>
13+
></div>
1214
);
1315
};
1416

src/components/global/recent_metrics/RecentMetrics.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ function RecentMetrics({
8383

8484
<div>
8585
{loading ? (
86+
<div className="h-[177px] bg-white flex items-center justify-center">
8687
<Spinner />
88+
</div>
8789
) : (
8890
<div className="w-full">
8991
<ScrollContainer>

src/lib/auth.tsx

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import {Provider} from "next-auth/providers";
2+
import CredentialsProvider from 'next-auth/providers/credentials'
3+
import authorize from "@/lib/authorize";
4+
import jwt from "@/lib/jwtAuthCallBack";
5+
import manageSession from "@/lib/sessionCallBack";
6+
7+
const NEXTAUTH_URL = process.env.NEXTAUTH_URL;
8+
const COGNITO_REGION = process.env.NEXT_PUBLIC_COGNITO_REGION;
9+
const COGNITO_DOMAIN = process.env.COGNITO_DOMAIN;
10+
const COGNITO_CLIENT_ID = process.env.COGNITO_CLIENT_ID;
11+
const COGNITO_USER_POOL_ID = process.env.NEXT_PUBLIC_COGNITO_USER_POOL_ID;
12+
const COGNITO_CLIENT_SECRET = process.env.COGNITO_CLIENT_SECRET;
13+
console.log("Process env:", process.env)
14+
type User = {
15+
id: string;
16+
accessToken: string | undefined;
17+
idToken: string | undefined;
18+
refreshToken: string | undefined;
19+
user: {
20+
email: string;
21+
// Other properties
22+
};
23+
};
24+
25+
function getProvider(provider: string): Provider {
26+
return {
27+
id: `cognito_${provider.toLowerCase()}`,
28+
name: `Cognito${provider}`,
29+
type: "oauth",
30+
checks: 'nonce',
31+
clientId: COGNITO_CLIENT_ID,
32+
clientSecret: COGNITO_CLIENT_SECRET,
33+
wellKnown: `https://cognito-idp.${COGNITO_REGION}.amazonaws.com/${COGNITO_USER_POOL_ID}/.well-known/openid-configuration`,
34+
authorization: {
35+
url: `${COGNITO_DOMAIN}/oauth2/authorize`,
36+
params: {
37+
response_type: "code",
38+
client_id: COGNITO_CLIENT_ID,
39+
identity_provider: provider,
40+
redirect_uri: `${NEXTAUTH_URL}/api/auth/callback/cognito_${provider.toLowerCase()}`
41+
}
42+
},
43+
idToken: true,
44+
// Token endpoint configuration
45+
token: {
46+
url: `${COGNITO_DOMAIN}/oauth2/token`,
47+
params: {
48+
grant_type: "authorization_code",
49+
client_id: COGNITO_CLIENT_ID,
50+
client_secret: COGNITO_CLIENT_SECRET,
51+
redirect_uri: `${NEXTAUTH_URL}/api/auth/callback/cognito_${provider.toLowerCase()}`
52+
}
53+
},
54+
// userInfo endpoint configuration
55+
userinfo: {
56+
url: `${COGNITO_DOMAIN}/oauth2/userInfo`,
57+
},
58+
// Profile to return after successful auth.
59+
// You can do some transformation on your profile object here.
60+
profile: function (profile) {
61+
console.log("Profile:", profile)
62+
return {
63+
id: profile.sub,
64+
...profile
65+
}
66+
}
67+
}
68+
}
69+
70+
export const authOptions = {
71+
providers: [
72+
...["Google"].map((provider) => getProvider(provider)),
73+
CredentialsProvider({
74+
type: "credentials",
75+
id: 'Credentials_signIn',
76+
name: 'Credentials_signIn',
77+
credentials: {
78+
username: {label: 'Username', type: 'text'},
79+
// email: {label: 'Email', type: 'text'},
80+
password: {label: 'Password', type: 'password'},
81+
},
82+
83+
authorize: async (credentials) => {
84+
// Use AWS SDK to authenticate against Cognito
85+
return await authorize(credentials) as User | null
86+
}
87+
}),
88+
],
89+
callbacks: {
90+
async signIn() {
91+
// Return true to allow sign in and false to block sign in.
92+
return true;
93+
},
94+
async redirect({baseUrl}: any) {
95+
// Return the url to redirect to after successful sign in.
96+
return baseUrl;
97+
},
98+
jwt: jwt,
99+
// async jwt({token, account, profile, user}: any) {
100+
// return await jwt({token, account, profile, user})
101+
// },
102+
session: manageSession,
103+
// return session; // Make sure to return the modified session
104+
}
105+
};
106+
107+

src/lib/authorize.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {CognitoIdentityProvider} from "@aws-sdk/client-cognito-identity-provider";
2+
3+
const COGNITO_REGION = process.env.NEXT_PUBLIC_COGNITO_REGION;
4+
const LOGIN_REGISTER_COGNITO_CLIENT_ID = process.env.NEXT_PUBLIC_LOGIN_REGISTER_COGNITO_CLIENT_ID;
5+
const COGNITO_USER_POOL_ID = process.env.NEXT_PUBLIC_COGNITO_USER_POOL_ID;
6+
export default async function authorize(credentials: any) {
7+
const cognito = new CognitoIdentityProvider({region: COGNITO_REGION});
8+
const signInParams = {
9+
AuthFlow: 'USER_PASSWORD_AUTH',
10+
ClientId: LOGIN_REGISTER_COGNITO_CLIENT_ID,
11+
UserPoolId: COGNITO_USER_POOL_ID,
12+
AuthParameters: {
13+
USERNAME: credentials.email,
14+
PASSWORD: credentials.password,
15+
},
16+
};
17+
console.log("signInParams", signInParams)
18+
// return;
19+
try {
20+
const signInResponse = await cognito.initiateAuth(signInParams);
21+
console.log("signInResponse:", signInResponse);
22+
// Process signInResponse and return a user object if successful
23+
if (signInResponse.AuthenticationResult) {
24+
return {
25+
accessToken: signInResponse.AuthenticationResult.AccessToken,
26+
idToken: signInResponse.AuthenticationResult.IdToken,
27+
refreshToken: signInResponse.AuthenticationResult.RefreshToken,
28+
user: {
29+
email: credentials.email,
30+
}
31+
}
32+
} else {
33+
console.log('Error signing in:', signInResponse, signInParams);
34+
throw new Error('Failed to authenticate')
35+
}
36+
} catch (error: any) {
37+
console.log('Error : ddd', error);
38+
throw new Error(error.message)
39+
}
40+
}

src/lib/jwtAuthCallBack.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default async function jwt({token, account, user,}: any) {
2+
return {...token, ...user, ...account};
3+
}

src/lib/sessionCallBack.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {DefaultSession, Session} from "next-auth";
2+
import {JWT} from "next-auth/jwt";
3+
4+
export default async function manageSession(params: {
5+
session: Session;
6+
token: JWT;
7+
user: any; // Replace with the appropriate user type
8+
newSession: any; // Replace with the appropriate session type
9+
trigger: "update";
10+
}): Promise<Session | DefaultSession> {
11+
// Your session handling logic here
12+
params.session.user = {
13+
...params.session.user, // Use just session.user
14+
...params.token, // Merge properties from token into user
15+
};
16+
return params.session// Make sure to return the modified session
17+
};

src/pages/_app.tsx

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from 'react';
2-
import type { ReactElement, ReactNode } from 'react';
3-
import type { NextPage } from 'next';
4-
import type { AppProps } from 'next/app';
5-
import { ConfigProvider } from '../context/config';
6-
import { Analytics } from '@vercel/analytics/react';
2+
import type {ReactElement, ReactNode} from 'react';
3+
import type {GetServerSideProps, NextPage} from 'next';
4+
import type {AppProps} from 'next/app';
5+
import {ConfigProvider} from '@/context/config';
6+
import {Analytics} from '@vercel/analytics/react';
77
import '../styles/main.sass';
88

99
export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
@@ -15,18 +15,28 @@ type AppPropsWithLayout = AppProps & {
1515
};
1616

1717
import ReactGA from 'react-ga4';
18+
import {getSession, SessionProvider} from "next-auth/react";
1819

1920
const TRACKING_ID = 'G-8HQ9S4Z1YF';
2021
ReactGA.initialize(TRACKING_ID);
21-
22-
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
22+
export const getServerSideProps: GetServerSideProps<{}> = async (ctx) => {
23+
const session = await getSession(ctx);
24+
return {
25+
props: {
26+
session,
27+
},
28+
};
29+
}
30+
export default function MyApp({Component, pageProps}: AppPropsWithLayout) {
2331
// Use the layout defined at the page level, if available
2432
const getLayout = Component.getLayout ?? ((page) => page);
2533

2634
return (
2735
<div>
28-
<ConfigProvider>{getLayout(<Component {...pageProps} />)}</ConfigProvider>
29-
<Analytics />
36+
<SessionProvider session={pageProps.session}>
37+
<ConfigProvider>{getLayout(<Component {...pageProps} />)}</ConfigProvider>
38+
<Analytics/>
39+
</SessionProvider>
3040
</div>
3141
);
3242
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import NextAuth from 'next-auth'
2+
import {authOptions} from "@/lib/auth";
3+
export default NextAuth(authOptions)
4+
// export { handler as GET, handler as POST }

0 commit comments

Comments
 (0)