From 6d55c727f198170d28a2083db8e05382eedaf65a Mon Sep 17 00:00:00 2001 From: SachinTedwa Date: Sat, 28 Dec 2024 03:29:18 +0530 Subject: [PATCH 1/2] Add example with Nextjs15 --- with-nextjs15(backend integration)/.gitignore | 41 ++++++++++++ with-nextjs15(backend integration)/README.md | 36 ++++++++++ with-nextjs15(backend integration)/bun.lockb | Bin 0 -> 186744 bytes .../eslint.config.mjs | 16 +++++ .../next.config.ts | 14 ++++ .../package.json | 28 ++++++++ .../postcss.config.mjs | 8 +++ .../public/file.svg | 1 + .../public/globe.svg | 1 + .../public/next.svg | 1 + .../public/vercel.svg | 1 + .../public/window.svg | 1 + .../src/app/(main)/(auth)/check_api/page.tsx | 14 ++++ .../src/app/(main)/(auth)/login/page.tsx | 16 +++++ .../src/app/(main)/(auth)/profile/page.tsx | 19 ++++++ .../src/app/(main)/page.tsx | 27 ++++++++ .../src/app/api/auth/logout/route.ts | 16 +++++ .../src/app/api/auth/session/route.ts | 23 +++++++ .../src/app/favicon.ico | Bin 0 -> 25931 bytes .../src/app/globals.css | 0 .../src/app/layout.tsx | 31 +++++++++ .../src/components/ClientProviders.tsx | 44 ++++++++++++ .../src/components/Dashboard/Navbar/nav.tsx | 63 ++++++++++++++++++ .../src/lib/authorizer.ts | 22 ++++++ .../src/lib/config/authorizer-config.ts | 7 ++ .../src/middleware.ts | 36 ++++++++++ .../tailwind.config.ts | 18 +++++ .../tsconfig.json | 27 ++++++++ 28 files changed, 511 insertions(+) create mode 100644 with-nextjs15(backend integration)/.gitignore create mode 100644 with-nextjs15(backend integration)/README.md create mode 100644 with-nextjs15(backend integration)/bun.lockb create mode 100644 with-nextjs15(backend integration)/eslint.config.mjs create mode 100644 with-nextjs15(backend integration)/next.config.ts create mode 100644 with-nextjs15(backend integration)/package.json create mode 100644 with-nextjs15(backend integration)/postcss.config.mjs create mode 100644 with-nextjs15(backend integration)/public/file.svg create mode 100644 with-nextjs15(backend integration)/public/globe.svg create mode 100644 with-nextjs15(backend integration)/public/next.svg create mode 100644 with-nextjs15(backend integration)/public/vercel.svg create mode 100644 with-nextjs15(backend integration)/public/window.svg create mode 100644 with-nextjs15(backend integration)/src/app/(main)/(auth)/check_api/page.tsx create mode 100644 with-nextjs15(backend integration)/src/app/(main)/(auth)/login/page.tsx create mode 100644 with-nextjs15(backend integration)/src/app/(main)/(auth)/profile/page.tsx create mode 100644 with-nextjs15(backend integration)/src/app/(main)/page.tsx create mode 100644 with-nextjs15(backend integration)/src/app/api/auth/logout/route.ts create mode 100644 with-nextjs15(backend integration)/src/app/api/auth/session/route.ts create mode 100644 with-nextjs15(backend integration)/src/app/favicon.ico create mode 100644 with-nextjs15(backend integration)/src/app/globals.css create mode 100644 with-nextjs15(backend integration)/src/app/layout.tsx create mode 100644 with-nextjs15(backend integration)/src/components/ClientProviders.tsx create mode 100644 with-nextjs15(backend integration)/src/components/Dashboard/Navbar/nav.tsx create mode 100644 with-nextjs15(backend integration)/src/lib/authorizer.ts create mode 100644 with-nextjs15(backend integration)/src/lib/config/authorizer-config.ts create mode 100644 with-nextjs15(backend integration)/src/middleware.ts create mode 100644 with-nextjs15(backend integration)/tailwind.config.ts create mode 100644 with-nextjs15(backend integration)/tsconfig.json diff --git a/with-nextjs15(backend integration)/.gitignore b/with-nextjs15(backend integration)/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/with-nextjs15(backend integration)/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/with-nextjs15(backend integration)/README.md b/with-nextjs15(backend integration)/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/with-nextjs15(backend integration)/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/with-nextjs15(backend integration)/bun.lockb b/with-nextjs15(backend integration)/bun.lockb new file mode 100644 index 0000000000000000000000000000000000000000..ca0b42ec65ac20122d95a7520cb825702afefee5 GIT binary patch literal 186744 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 XC`#^Ilhh%yE)`vMlzi&{>3{zNun>0o literal 0 HcmV?d00001 diff --git a/with-nextjs15(backend integration)/eslint.config.mjs b/with-nextjs15(backend integration)/eslint.config.mjs new file mode 100644 index 0000000..c85fb67 --- /dev/null +++ b/with-nextjs15(backend integration)/eslint.config.mjs @@ -0,0 +1,16 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), +]; + +export default eslintConfig; diff --git a/with-nextjs15(backend integration)/next.config.ts b/with-nextjs15(backend integration)/next.config.ts new file mode 100644 index 0000000..d33429e --- /dev/null +++ b/with-nextjs15(backend integration)/next.config.ts @@ -0,0 +1,14 @@ +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + async rewrites() { + return [ + { + source: '/api/:path*', // Matches any path starting with /api/ + destination: 'http://localhost:3001/:path*', // Proxy to your backend + }, + ]; + }, +}; + +export default nextConfig; diff --git a/with-nextjs15(backend integration)/package.json b/with-nextjs15(backend integration)/package.json new file mode 100644 index 0000000..9864f71 --- /dev/null +++ b/with-nextjs15(backend integration)/package.json @@ -0,0 +1,28 @@ +{ + "name": "authorizer_nextjs15", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@authorizerdev/authorizer-react": "^1.3.3", + "next": "15.1.2", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "typescript": "^5", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "eslint": "^9", + "eslint-config-next": "15.1.2", + "@eslint/eslintrc": "^3" + } +} diff --git a/with-nextjs15(backend integration)/postcss.config.mjs b/with-nextjs15(backend integration)/postcss.config.mjs new file mode 100644 index 0000000..1a69fd2 --- /dev/null +++ b/with-nextjs15(backend integration)/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + }, +}; + +export default config; diff --git a/with-nextjs15(backend integration)/public/file.svg b/with-nextjs15(backend integration)/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/with-nextjs15(backend integration)/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/with-nextjs15(backend integration)/public/globe.svg b/with-nextjs15(backend integration)/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/with-nextjs15(backend integration)/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/with-nextjs15(backend integration)/public/next.svg b/with-nextjs15(backend integration)/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/with-nextjs15(backend integration)/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/with-nextjs15(backend integration)/public/vercel.svg b/with-nextjs15(backend integration)/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/with-nextjs15(backend integration)/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/with-nextjs15(backend integration)/public/window.svg b/with-nextjs15(backend integration)/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/with-nextjs15(backend integration)/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/app/(main)/(auth)/check_api/page.tsx b/with-nextjs15(backend integration)/src/app/(main)/(auth)/check_api/page.tsx new file mode 100644 index 0000000..fb45151 --- /dev/null +++ b/with-nextjs15(backend integration)/src/app/(main)/(auth)/check_api/page.tsx @@ -0,0 +1,14 @@ +import { validateUser } from "@/lib/authorizer" + + +// const fetchUserData = async () => { +// return await validateUser(); +// }; + + +export default async function Check_api() { + const result = await validateUser(); + console.log("result", result); + return result ?
{JSON.stringify(result, null, 2)}
: null; + +} \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/app/(main)/(auth)/login/page.tsx b/with-nextjs15(backend integration)/src/app/(main)/(auth)/login/page.tsx new file mode 100644 index 0000000..d80f286 --- /dev/null +++ b/with-nextjs15(backend integration)/src/app/(main)/(auth)/login/page.tsx @@ -0,0 +1,16 @@ +'use client'; + +import { useEffect } from 'react'; +import { Authorizer, useAuthorizer } from '@authorizerdev/authorizer-react'; +import { useRouter } from 'next/navigation'; + +export default function Login() { + const { token } = useAuthorizer(); + const router = useRouter(); + useEffect(() => { + if (token) { + router.push('/'); + } + }, [token]); + return ; +} \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/app/(main)/(auth)/profile/page.tsx b/with-nextjs15(backend integration)/src/app/(main)/(auth)/profile/page.tsx new file mode 100644 index 0000000..671424a --- /dev/null +++ b/with-nextjs15(backend integration)/src/app/(main)/(auth)/profile/page.tsx @@ -0,0 +1,19 @@ +import { Authorizer } from '@authorizerdev/authorizer-js'; +import authorizerConfig from '../../../../lib/config/authorizer-config'; +import { cookies } from 'next/headers'; + +const getUserData = async () => { + const nextCookies = cookies(); + const tokenCookie = (await nextCookies).get('authorizer-client-next'); + const token = tokenCookie ? tokenCookie.value : null; + const authorizerRef = new Authorizer(authorizerConfig); + + return authorizerRef.getProfile({ + Authorization: `Bearer ${token}`, + }); +}; + +export default async function Profile() { + const user = await getUserData(); + return user ?
{JSON.stringify(user, null, 2)}
: null; +} \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/app/(main)/page.tsx b/with-nextjs15(backend integration)/src/app/(main)/page.tsx new file mode 100644 index 0000000..adbb0a9 --- /dev/null +++ b/with-nextjs15(backend integration)/src/app/(main)/page.tsx @@ -0,0 +1,27 @@ + +import Link from 'next/link'; + +const HomePage = () => { + return ( +
+
+
+

+ Authorizer Homepage!!! +

+
+

+ Authorizer is a simple, secure, and scalable authentication and + authorization service that allows you to add authentication to your + applications and APIs in just a few minutes. +

+ + {/* */} + +
+ +
+ ); +}; + +export default HomePage; \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/app/api/auth/logout/route.ts b/with-nextjs15(backend integration)/src/app/api/auth/logout/route.ts new file mode 100644 index 0000000..b83f4c7 --- /dev/null +++ b/with-nextjs15(backend integration)/src/app/api/auth/logout/route.ts @@ -0,0 +1,16 @@ +import type { AuthToken } from '@authorizerdev/authorizer-js'; +import { cookies } from 'next/headers'; +import { NextRequest, NextResponse } from 'next/server'; + +export const POST = async (req: NextRequest, res: Response) => { + (await cookies()).set('authorizer-client-next', '', { + secure: true, + expires: -1, + httpOnly: true, + path: '/', + }); + return NextResponse.json( + { message: 'Logged out successfully' }, + { status: 200 }, + ); +}; \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/app/api/auth/session/route.ts b/with-nextjs15(backend integration)/src/app/api/auth/session/route.ts new file mode 100644 index 0000000..0b15128 --- /dev/null +++ b/with-nextjs15(backend integration)/src/app/api/auth/session/route.ts @@ -0,0 +1,23 @@ +import type { AuthToken } from '@authorizerdev/authorizer-js'; +import { NextRequest, NextResponse } from 'next/server'; +import { cookies } from 'next/headers'; + +export const POST = async (req: NextRequest, res: Response) => { + const data = (await req.json()) as AuthToken | null; + const accessToken = data?.access_token; + const expiresAt = data?.expires_in; + + if (!accessToken || !expiresAt) { + return NextResponse.json({ message: 'Unauthorized' }, { status: 401 }); + } else { + (await cookies()).set('authorizer-client-next', `${accessToken}`, { + secure: true, + httpOnly: true, + path: '/', + }); + return NextResponse.json( + { message: 'Session created successfully' }, + { status: 200 }, + ); + } +}; \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/app/favicon.ico b/with-nextjs15(backend integration)/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 zcmeHv30#a{`}aL_*G&7qml|y<+KVaDM2m#dVr!KsA!#An?kSQM(q<_dDNCpjEux83 zLb9Z^XxbDl(w>%i@8hT6>)&Gu{h#Oeyszu?xtw#Zb1mO{pgX9699l+Qppw7jXaYf~-84xW z)w4x8?=youko|}Vr~(D$UXIbiXABHh`p1?nn8Po~fxRJv}|0e(BPs|G`(TT%kKVJAdg5*Z|x0leQq0 zkdUBvb#>9F()jo|T~kx@OM8$9wzs~t2l;K=woNssA3l6|sx2r3+kdfVW@e^8e*E}v zA1y5{bRi+3Z`uD3{F7LgFJDdvm;nJilkzDku>BwXH(8ItVCXk*-lSJnR?-2UN%hJ){&rlvg`CDTj z)Bzo!3v7Ou#83zEDEFcKt(f1E0~=rqeEbTnMvWR#{+9pg%7G8y>u1OVRUSoox-ovF z2Ydma(;=YuBY(eI|04{hXzZD6_f(v~H;C~y5=DhAC{MMS>2fm~1H_t2$56pc$NH8( z5bH|<)71dV-_oCHIrzrT`2s-5w_+2CM0$95I6X8p^r!gHp+j_gd;9O<1~CEQQGS8) zS9Qh3#p&JM-G8rHekNmKVewU;pJRcTAog68KYo^dRo}(M>36U4Us zfgYWSiHZL3;lpWT=zNAW>Dh#mB!_@Lg%$ms8N-;aPqMn+C2HqZgz&9~Eu z4|Kp<`$q)Uw1R?y(~S>ePdonHxpV1#eSP1B;Ogo+-Pk}6#0GsZZ5!||ev2MGdh}_m z{DeR7?0-1^zVs&`AV6Vt;r3`I`OI_wgs*w=eO%_#7Kepl{B@xiyCANc(l zzIyd4y|c6PXWq9-|KM8(zIk8LPk(>a)zyFWjhT!$HJ$qX1vo@d25W<fvZQ2zUz5WRc(UnFMKHwe1| zWmlB1qdbiA(C0jmnV<}GfbKtmcu^2*P^O?MBLZKt|As~ge8&AAO~2K@zbXelK|4T<{|y4`raF{=72kC2Kn(L4YyenWgrPiv z@^mr$t{#X5VuIMeL!7Ab6_kG$&#&5p*Z{+?5U|TZ`B!7llpVmp@skYz&n^8QfPJzL z0G6K_OJM9x+Wu2gfN45phANGt{7=C>i34CV{Xqlx(fWpeAoj^N0Biu`w+MVcCUyU* zDZuzO0>4Z6fbu^T_arWW5n!E45vX8N=bxTVeFoep_G#VmNlQzAI_KTIc{6>c+04vr zx@W}zE5JNSU>!THJ{J=cqjz+4{L4A{Ob9$ZJ*S1?Ggg3klFp!+Y1@K+pK1DqI|_gq z5ZDXVpge8-cs!o|;K73#YXZ3AShj50wBvuq3NTOZ`M&qtjj#GOFfgExjg8Gn8>Vq5 z`85n+9|!iLCZF5$HJ$Iu($dm?8~-ofu}tEc+-pyke=3!im#6pk_Wo8IA|fJwD&~~F zc16osQ)EBo58U7XDuMexaPRjU@h8tXe%S{fA0NH3vGJFhuyyO!Uyl2^&EOpX{9As0 zWj+P>{@}jxH)8|r;2HdupP!vie{sJ28b&bo!8`D^x}TE$%zXNb^X1p@0PJ86`dZyj z%ce7*{^oo+6%&~I!8hQy-vQ7E)0t0ybH4l%KltWOo~8cO`T=157JqL(oq_rC%ea&4 z2NcTJe-HgFjNg-gZ$6!Y`SMHrlj}Etf7?r!zQTPPSv}{so2e>Fjs1{gzk~LGeesX%r(Lh6rbhSo_n)@@G-FTQy93;l#E)hgP@d_SGvyCp0~o(Y;Ee8{ zdVUDbHm5`2taPUOY^MAGOw*>=s7=Gst=D+p+2yON!0%Hk` zz5mAhyT4lS*T3LS^WSxUy86q&GnoHxzQ6vm8)VS}_zuqG?+3td68_x;etQAdu@sc6 zQJ&5|4(I?~3d-QOAODHpZ=hlSg(lBZ!JZWCtHHSj`0Wh93-Uk)_S%zsJ~aD>{`A0~ z9{AG(e|q3g5B%wYKRxiL2Y$8(4w6bzchKuloQW#e&S3n+P- z8!ds-%f;TJ1>)v)##>gd{PdS2Oc3VaR`fr=`O8QIO(6(N!A?pr5C#6fc~Ge@N%Vvu zaoAX2&(a6eWy_q&UwOhU)|P3J0Qc%OdhzW=F4D|pt0E4osw;%<%Dn58hAWD^XnZD= z>9~H(3bmLtxpF?a7su6J7M*x1By7YSUbxGi)Ot0P77`}P3{)&5Un{KD?`-e?r21!4vTTnN(4Y6Lin?UkSM z`MXCTC1@4A4~mvz%Rh2&EwY))LeoT=*`tMoqcEXI>TZU9WTP#l?uFv+@Dn~b(>xh2 z;>B?;Tz2SR&KVb>vGiBSB`@U7VIWFSo=LDSb9F{GF^DbmWAfpms8Sx9OX4CnBJca3 zlj9(x!dIjN?OG1X4l*imJNvRCk}F%!?SOfiOq5y^mZW)jFL@a|r-@d#f7 z2gmU8L3IZq0ynIws=}~m^#@&C%J6QFo~Mo4V`>v7MI-_!EBMMtb%_M&kvAaN)@ZVw z+`toz&WG#HkWDjnZE!6nk{e-oFdL^$YnbOCN}JC&{$#$O27@|Tn-skXr)2ml2~O!5 zX+gYoxhoc7qoU?C^3~&!U?kRFtnSEecWuH0B0OvLodgUAi}8p1 zrO6RSXHH}DMc$&|?D004DiOVMHV8kXCP@7NKB zgaZq^^O<7PoKEp72kby@W0Z!Y*Ay{&vfg#C&gG@YVR9g?FEocMUi1gSN$+V+ayF45{a zuDZDTN}mS|;BO%gEf}pjBfN2-gIrU#G5~cucA;dokXW89%>AyXJJI z9X4UlIWA|ZYHgbI z5?oFk@A=Ik7lrEQPDH!H+b`7_Y~aDb_qa=B2^Y&Ow41cU=4WDd40dp5(QS-WMN-=Y z9g;6_-JdNU;|6cPwf$ak*aJIcwL@1n$#l~zi{c{EW?T;DaW*E8DYq?Umtz{nJ&w-M zEMyTDrC&9K$d|kZe2#ws6)L=7K+{ zQw{XnV6UC$6-rW0emqm8wJoeZK)wJIcV?dST}Z;G0Arq{dVDu0&4kd%N!3F1*;*pW zR&qUiFzK=@44#QGw7k1`3t_d8&*kBV->O##t|tonFc2YWrL7_eqg+=+k;!F-`^b8> z#KWCE8%u4k@EprxqiV$VmmtiWxDLgnGu$Vs<8rppV5EajBXL4nyyZM$SWVm!wnCj-B!Wjqj5-5dNXukI2$$|Bu3Lrw}z65Lc=1G z^-#WuQOj$hwNGG?*CM_TO8Bg-1+qc>J7k5c51U8g?ZU5n?HYor;~JIjoWH-G>AoUP ztrWWLbRNqIjW#RT*WqZgPJXU7C)VaW5}MiijYbABmzoru6EmQ*N8cVK7a3|aOB#O& zBl8JY2WKfmj;h#Q!pN%9o@VNLv{OUL?rixHwOZuvX7{IJ{(EdPpuVFoQqIOa7giLVkBOKL@^smUA!tZ1CKRK}#SSM)iQHk)*R~?M!qkCruaS!#oIL1c z?J;U~&FfH#*98^G?i}pA{ z9Jg36t4=%6mhY(quYq*vSxptes9qy|7xSlH?G=S@>u>Ebe;|LVhs~@+06N<4CViBk zUiY$thvX;>Tby6z9Y1edAMQaiH zm^r3v#$Q#2T=X>bsY#D%s!bhs^M9PMAcHbCc0FMHV{u-dwlL;a1eJ63v5U*?Q_8JO zT#50!RD619#j_Uf))0ooADz~*9&lN!bBDRUgE>Vud-i5ck%vT=r^yD*^?Mp@Q^v+V zG#-?gKlr}Eeqifb{|So?HM&g91P8|av8hQoCmQXkd?7wIJwb z_^v8bbg`SAn{I*4bH$u(RZ6*xUhuA~hc=8czK8SHEKTzSxgbwi~9(OqJB&gwb^l4+m`k*Q;_?>Y-APi1{k zAHQ)P)G)f|AyjSgcCFps)Fh6Bca*Xznq36!pV6Az&m{O8$wGFD? zY&O*3*J0;_EqM#jh6^gMQKpXV?#1?>$ml1xvh8nSN>-?H=V;nJIwB07YX$e6vLxH( zqYwQ>qxwR(i4f)DLd)-$P>T-no_c!LsN@)8`e;W@)-Hj0>nJ-}Kla4-ZdPJzI&Mce zv)V_j;(3ERN3_@I$N<^|4Lf`B;8n+bX@bHbcZTopEmDI*Jfl)-pFDvo6svPRoo@(x z);_{lY<;);XzT`dBFpRmGrr}z5u1=pC^S-{ce6iXQlLGcItwJ^mZx{m$&DA_oEZ)B{_bYPq-HA zcH8WGoBG(aBU_j)vEy+_71T34@4dmSg!|M8Vf92Zj6WH7Q7t#OHQqWgFE3ARt+%!T z?oLovLVlnf?2c7pTc)~cc^($_8nyKwsN`RA-23ed3sdj(ys%pjjM+9JrctL;dy8a( z@en&CQmnV(()bu|Y%G1-4a(6x{aLytn$T-;(&{QIJB9vMox11U-1HpD@d(QkaJdEb zG{)+6Dos_L+O3NpWo^=gR?evp|CqEG?L&Ut#D*KLaRFOgOEK(Kq1@!EGcTfo+%A&I z=dLbB+d$u{sh?u)xP{PF8L%;YPPW53+@{>5W=Jt#wQpN;0_HYdw1{ksf_XhO4#2F= zyPx6Lx2<92L-;L5PD`zn6zwIH`Jk($?Qw({erA$^bC;q33hv!d!>%wRhj# zal^hk+WGNg;rJtb-EB(?czvOM=H7dl=vblBwAv>}%1@{}mnpUznfq1cE^sgsL0*4I zJ##!*B?=vI_OEVis5o+_IwMIRrpQyT_Sq~ZU%oY7c5JMIADzpD!Upz9h@iWg_>>~j zOLS;wp^i$-E?4<_cp?RiS%Rd?i;f*mOz=~(&3lo<=@(nR!_Rqiprh@weZlL!t#NCc zO!QTcInq|%#>OVgobj{~ixEUec`E25zJ~*DofsQdzIa@5^nOXj2T;8O`l--(QyU^$t?TGY^7#&FQ+2SS3B#qK*k3`ye?8jUYSajE5iBbJls75CCc(m3dk{t?- zopcER9{Z?TC)mk~gpi^kbbu>b-+a{m#8-y2^p$ka4n60w;Sc2}HMf<8JUvhCL0B&Btk)T`ctE$*qNW8L$`7!r^9T+>=<=2qaq-;ll2{`{Rg zc5a0ZUI$oG&j-qVOuKa=*v4aY#IsoM+1|c4Z)<}lEDvy;5huB@1RJPquU2U*U-;gu z=En2m+qjBzR#DEJDO`WU)hdd{Vj%^0V*KoyZ|5lzV87&g_j~NCjwv0uQVqXOb*QrQ zy|Qn`hxx(58c70$E;L(X0uZZ72M1!6oeg)(cdKO ze0gDaTz+ohR-#d)NbAH4x{I(21yjwvBQfmpLu$)|m{XolbgF!pmsqJ#D}(ylp6uC> z{bqtcI#hT#HW=wl7>p!38sKsJ`r8}lt-q%Keqy%u(xk=yiIJiUw6|5IvkS+#?JTBl z8H5(Q?l#wzazujH!8o>1xtn8#_w+397*_cy8!pQGP%K(Ga3pAjsaTbbXJlQF_+m+-UpUUent@xM zg%jqLUExj~o^vQ3Gl*>wh=_gOr2*|U64_iXb+-111aH}$TjeajM+I20xw(((>fej-@CIz4S1pi$(#}P7`4({6QS2CaQS4NPENDp>sAqD z$bH4KGzXGffkJ7R>V>)>tC)uax{UsN*dbeNC*v}#8Y#OWYwL4t$ePR?VTyIs!wea+ z5Urmc)X|^`MG~*dS6pGSbU+gPJoq*^a=_>$n4|P^w$sMBBy@f*Z^Jg6?n5?oId6f{ z$LW4M|4m502z0t7g<#Bx%X;9<=)smFolV&(V^(7Cv2-sxbxopQ!)*#ZRhTBpx1)Fc zNm1T%bONzv6@#|dz(w02AH8OXe>kQ#1FMCzO}2J_mST)+ExmBr9cva-@?;wnmWMOk z{3_~EX_xadgJGv&H@zK_8{(x84`}+c?oSBX*Ge3VdfTt&F}yCpFP?CpW+BE^cWY0^ zb&uBN!Ja3UzYHK-CTyA5=L zEMW{l3Usky#ly=7px648W31UNV@K)&Ub&zP1c7%)`{);I4b0Q<)B}3;NMG2JH=X$U zfIW4)4n9ZM`-yRj67I)YSLDK)qfUJ_ij}a#aZN~9EXrh8eZY2&=uY%2N0UFF7<~%M zsB8=erOWZ>Ct_#^tHZ|*q`H;A)5;ycw*IcmVxi8_0Xk}aJA^ath+E;xg!x+As(M#0=)3!NJR6H&9+zd#iP(m0PIW8$ z1Y^VX`>jm`W!=WpF*{ioM?C9`yOR>@0q=u7o>BP-eSHqCgMDj!2anwH?s%i2p+Q7D zzszIf5XJpE)IG4;d_(La-xenmF(tgAxK`Y4sQ}BSJEPs6N_U2vI{8=0C_F?@7<(G; zo$~G=8p+076G;`}>{MQ>t>7cm=zGtfbdDXm6||jUU|?X?CaE?(<6bKDYKeHlz}DA8 zXT={X=yp_R;HfJ9h%?eWvQ!dRgz&Su*JfNt!Wu>|XfU&68iRikRrHRW|ZxzRR^`eIGt zIeiDgVS>IeExKVRWW8-=A=yA`}`)ZkWBrZD`hpWIxBGkh&f#ijr449~m`j6{4jiJ*C!oVA8ZC?$1RM#K(_b zL9TW)kN*Y4%^-qPpMP7d4)o?Nk#>aoYHT(*g)qmRUb?**F@pnNiy6Fv9rEiUqD(^O zzyS?nBrX63BTRYduaG(0VVG2yJRe%o&rVrLjbxTaAFTd8s;<<@Qs>u(<193R8>}2_ zuwp{7;H2a*X7_jryzriZXMg?bTuegABb^87@SsKkr2)0Gyiax8KQWstw^v#ix45EVrcEhr>!NMhprl$InQMzjSFH54x5k9qHc`@9uKQzvL4ihcq{^B zPrVR=o_ic%Y>6&rMN)hTZsI7I<3&`#(nl+3y3ys9A~&^=4?PL&nd8)`OfG#n zwAMN$1&>K++c{^|7<4P=2y(B{jJsQ0a#U;HTo4ZmWZYvI{+s;Td{Yzem%0*k#)vjpB zia;J&>}ICate44SFYY3vEelqStQWFihx%^vQ@Do(sOy7yR2@WNv7Y9I^yL=nZr3mb zXKV5t@=?-Sk|b{XMhA7ZGB@2hqsx}4xwCW!in#C zI@}scZlr3-NFJ@NFaJlhyfcw{k^vvtGl`N9xSo**rDW4S}i zM9{fMPWo%4wYDG~BZ18BD+}h|GQKc-g^{++3MY>}W_uq7jGHx{mwE9fZiPCoxN$+7 zrODGGJrOkcPQUB(FD5aoS4g~7#6NR^ma7-!>mHuJfY5kTe6PpNNKC9GGRiu^L31uG z$7v`*JknQHsYB!Tm_W{a32TM099djW%5e+j0Ve_ct}IM>XLF1Ap+YvcrLV=|CKo6S zb+9Nl3_YdKP6%Cxy@6TxZ>;4&nTneadr z_ES90ydCev)LV!dN=#(*f}|ZORFdvkYBni^aLbUk>BajeWIOcmHP#8S)*2U~QKI%S zyrLmtPqb&TphJ;>yAxri#;{uyk`JJqODDw%(Z=2`1uc}br^V%>j!gS)D*q*f_-qf8&D;W1dJgQMlaH5er zN2U<%Smb7==vE}dDI8K7cKz!vs^73o9f>2sgiTzWcwY|BMYHH5%Vn7#kiw&eItCqa zIkR2~Q}>X=Ar8W|^Ms41Fm8o6IB2_j60eOeBB1Br!boW7JnoeX6Gs)?7rW0^5psc- zjS16yb>dFn>KPOF;imD}e!enuIniFzv}n$m2#gCCv4jM#ArwlzZ$7@9&XkFxZ4n!V zj3dyiwW4Ki2QG{@i>yuZXQizw_OkZI^-3otXC{!(lUpJF33gI60ak;Uqitp74|B6I zgg{b=Iz}WkhCGj1M=hu4#Aw173YxIVbISaoc z-nLZC*6Tgivd5V`K%GxhBsp@SUU60-rfc$=wb>zdJzXS&-5(NRRodFk;Kxk!S(O(a0e7oY=E( zAyS;Ow?6Q&XA+cnkCb{28_1N8H#?J!*$MmIwLq^*T_9-z^&UE@A(z9oGYtFy6EZef LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/with-nextjs15(backend integration)/src/app/globals.css b/with-nextjs15(backend integration)/src/app/globals.css new file mode 100644 index 0000000..e69de29 diff --git a/with-nextjs15(backend integration)/src/app/layout.tsx b/with-nextjs15(backend integration)/src/app/layout.tsx new file mode 100644 index 0000000..69a4975 --- /dev/null +++ b/with-nextjs15(backend integration)/src/app/layout.tsx @@ -0,0 +1,31 @@ +import type { Metadata } from 'next'; +// import { Open_Sans } from 'next/font/google'; +import './globals.css'; +import { AuthProvider } from '@/components/ClientProviders'; +import Navbar from '@/components/Dashboard/Navbar/nav'; + +// const openSans = Open_Sans({ subsets: ['latin'] }); + +export const metadata: Metadata = { + title: 'Authorizer!', + description: + 'Authorizer is a simple, secure, and scalable authentication and authorization service that allows you to add authentication to your applications and APIs in just a few minutes.', +}; + +export default async function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + + return ( + + + + {/* Pass token as a prop */} + {children} + + + + ); +} \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/components/ClientProviders.tsx b/with-nextjs15(backend integration)/src/components/ClientProviders.tsx new file mode 100644 index 0000000..0364a67 --- /dev/null +++ b/with-nextjs15(backend integration)/src/components/ClientProviders.tsx @@ -0,0 +1,44 @@ +'use client'; + +import config from '@/lib/config/authorizer-config'; +import type { AuthToken } from '@authorizerdev/authorizer-js'; +import { AuthorizerProvider } from '@authorizerdev/authorizer-react'; +import { useRouter } from 'next/navigation'; +import { ReactNode, useEffect } from 'react'; + + +const onStateChangeCallback = async ({ + token, +}: { + token: AuthToken | null; +}) => { + if (!token) return; + + await fetch('/api/auth/session', { + method: 'POST', + body: JSON.stringify(token), + cache: 'no-store', + }); +}; + +export const AuthProvider = ({ children }: { children: ReactNode }) => { + const router = useRouter(); + +// useEffect(() => { +// const hasJoinToken = sessionStorage.getItem('join'); +// if (hasJoinToken) { +// const inviteUrl = '/join?token=' + hasJoinToken; +// router.push(inviteUrl); +// } +// }, []); + + return ( + + {children} + + ); +}; + diff --git a/with-nextjs15(backend integration)/src/components/Dashboard/Navbar/nav.tsx b/with-nextjs15(backend integration)/src/components/Dashboard/Navbar/nav.tsx new file mode 100644 index 0000000..eb3f87c --- /dev/null +++ b/with-nextjs15(backend integration)/src/components/Dashboard/Navbar/nav.tsx @@ -0,0 +1,63 @@ +'use client' + +import { useAuthorizer } from '@authorizerdev/authorizer-react'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; + + + +export default function Nav() { + const { user, setUser, setToken, authorizerRef } = useAuthorizer(); + const router = useRouter(); + const onLogout = async () => { + setUser(null); + setToken(null); + await authorizerRef.logout(); + await fetch('/api/auth/logout', { + method: 'POST', + }); + router.push('/'); + }; + + const checkApi = async () => {}; + return ( + + ); +} \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/lib/authorizer.ts b/with-nextjs15(backend integration)/src/lib/authorizer.ts new file mode 100644 index 0000000..6200ea0 --- /dev/null +++ b/with-nextjs15(backend integration)/src/lib/authorizer.ts @@ -0,0 +1,22 @@ +import { cookies } from 'next/headers'; + +export const generateAuthHeaders = async () => { + const nextCookies = await cookies(); + const token = nextCookies.get('authorizer-client-next')?.value; + const headers = new Headers(); + headers.append('Content-Type', 'application/json'); + headers.append('Authorization', `Bearer ${token}`); + return headers; +}; + +export const validateUser = async () => { + const headers = await generateAuthHeaders(); + console.log(headers); + const response = await fetch('http://localhost:3001/health', { + headers, + }); + + if (response.ok) return response.json(); + return false; +}; + diff --git a/with-nextjs15(backend integration)/src/lib/config/authorizer-config.ts b/with-nextjs15(backend integration)/src/lib/config/authorizer-config.ts new file mode 100644 index 0000000..2809d18 --- /dev/null +++ b/with-nextjs15(backend integration)/src/lib/config/authorizer-config.ts @@ -0,0 +1,7 @@ +const config = { + authorizerURL: 'http://localhost:8080', + redirectURL: 'http://localhost:3000', + clientID: '882720ca-81cc-4925-9d33-41035d6c758f', + }; + + export default config; \ No newline at end of file diff --git a/with-nextjs15(backend integration)/src/middleware.ts b/with-nextjs15(backend integration)/src/middleware.ts new file mode 100644 index 0000000..25cf51c --- /dev/null +++ b/with-nextjs15(backend integration)/src/middleware.ts @@ -0,0 +1,36 @@ +// src/middleware.ts +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; + +export function middleware(request: NextRequest) { + const token = request.cookies.get('authorizer-client-next'); + console.log('Token:', token); + + // Define protected routes + const protectedRoutes = ['/profile']; + const isProtectedRoute = protectedRoutes.some(route => + request.nextUrl.pathname.startsWith(route) + ); + + // If no token exists for protected routes, redirect to login + if (isProtectedRoute && !token) { + return NextResponse.redirect(new URL('/login', request.url)); + } + + // If logged in and trying to access login, redirect to home + if (request.nextUrl.pathname === '/login' && token) { + return NextResponse.redirect(new URL('/', request.url)); + } + + return NextResponse.next(); +} + +export const config = { + matcher: [ + // Skip Next.js internals and all static files, unless found in search params + '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', + // Always run for API routes + '/(api|trpc)(.*)', + ], + } + \ No newline at end of file diff --git a/with-nextjs15(backend integration)/tailwind.config.ts b/with-nextjs15(backend integration)/tailwind.config.ts new file mode 100644 index 0000000..109807b --- /dev/null +++ b/with-nextjs15(backend integration)/tailwind.config.ts @@ -0,0 +1,18 @@ +import type { Config } from "tailwindcss"; + +export default { + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + background: "var(--background)", + foreground: "var(--foreground)", + }, + }, + }, + plugins: [], +} satisfies Config; diff --git a/with-nextjs15(backend integration)/tsconfig.json b/with-nextjs15(backend integration)/tsconfig.json new file mode 100644 index 0000000..c133409 --- /dev/null +++ b/with-nextjs15(backend integration)/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} From efc89de7ca16259a30ba1896910a5b1d711ca8d7 Mon Sep 17 00:00:00 2001 From: SachinTedwa Date: Sat, 28 Dec 2024 03:31:38 +0530 Subject: [PATCH 2/2] Add example with golang_server --- with-golang/.env | 1 + with-golang/go.mod | 36 ++++++++++++ with-golang/go.sum | 85 ++++++++++++++++++++++++++++ with-golang/main.go | 133 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 with-golang/.env create mode 100644 with-golang/go.mod create mode 100644 with-golang/go.sum create mode 100644 with-golang/main.go diff --git a/with-golang/.env b/with-golang/.env new file mode 100644 index 0000000..df09d75 --- /dev/null +++ b/with-golang/.env @@ -0,0 +1 @@ +PORT=3001 diff --git a/with-golang/go.mod b/with-golang/go.mod new file mode 100644 index 0000000..48ccc01 --- /dev/null +++ b/with-golang/go.mod @@ -0,0 +1,36 @@ +module gin + +go 1.23.2 + +require ( + github.com/authorizerdev/authorizer-go v0.0.0-20240402105736-0eeef41a29a2 // indirect + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/cors v1.7.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.10.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/with-golang/go.sum b/with-golang/go.sum new file mode 100644 index 0000000..6f19df0 --- /dev/null +++ b/with-golang/go.sum @@ -0,0 +1,85 @@ +github.com/authorizerdev/authorizer-go v0.0.0-20240402105736-0eeef41a29a2 h1:Fb7QvIRVgUY4bzVheAgffz+Qa43t4ujQTMNApjyTfo8= +github.com/authorizerdev/authorizer-go v0.0.0-20240402105736-0eeef41a29a2/go.mod h1:JS47FPlPYXUoppQmyiyxk8pWwxYvw2Hf63Q7jFZzz1k= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= +github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/with-golang/main.go b/with-golang/main.go new file mode 100644 index 0000000..98d42b0 --- /dev/null +++ b/with-golang/main.go @@ -0,0 +1,133 @@ +package main + +import ( + "log" + "net/http" + "strings" + "github.com/authorizerdev/authorizer-go" + "github.com/gin-gonic/gin" + "github.com/gin-contrib/cors" + "github.com/joho/godotenv" // For loading .env files + "os" +) + +// HealthCheckHandler handles health check requests +func HealthCheckHandler(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "status": "UP", + "message": "Service is running smoothly", + }) +} + +// User struct to represent user data +type User struct { + ID int `json:"id"` + Name string `json:"name"` + Email string `json:"email"` +} + +var users = []User{ + {ID: 1, Name: "Alice", Email: "alice@example.com"}, + {ID: 2, Name: "Bob", Email: "bob@example.com"}, +} + +// GetUsersHandler returns the list of users +func GetUsersHandler(c *gin.Context) { + c.JSON(http.StatusOK, users) +} + +// AddUserHandler adds a new user +func AddUserHandler(c *gin.Context) { + var newUser User + if err := c.ShouldBindJSON(&newUser); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + newUser.ID = len(users) + 1 + users = append(users, newUser) + c.JSON(http.StatusCreated, newUser) +} + +func AuthorizeMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + // Optional: add conditions here for open routes that don't require authentication + + authHeader := c.Request.Header.Get("Authorization") + tokenSplit := strings.Split(authHeader, " ") + log.Println(tokenSplit[1]) + + // Replace with your Authorizer credentials + clientID := "882720ca-81cc-4925-9d33-41035d6c758f" + authorizerURL := "http://localhost:8080" + redirectURL := "" + + defaultHeaders := map[string]string{} + authorizerClient, err := authorizer.NewAuthorizerClient(clientID, authorizerURL, redirectURL, defaultHeaders) + if err != nil { + log.Println(`authorizerClient have problem`) + // Unauthorized response if client initialization fails + c.AbortWithStatusJSON(http.StatusUnauthorized, "unauthorized") + return + } + + if len(tokenSplit) < 2 || tokenSplit[1] == "" { + log.Println(`token have problem`) + // Unauthorized response for invalid token format + c.AbortWithStatusJSON(http.StatusUnauthorized, "unauthorized") + return + } + + // Validate the token + res, err := authorizerClient.ValidateJWTToken(&authorizer.ValidateJWTTokenInput{ + TokenType: authorizer.TokenTypeAccessToken, + Token: tokenSplit[1], + }) + if err != nil || !res.IsValid { + log.Println(`validation have problem`) + // Unauthorized response for invalid token + c.AbortWithStatusJSON(http.StatusUnauthorized, "unauthorized cant aboe to find") + return + } + + // Proceed with the request if the token is valid + c.Next() + } +} + + +// Main function to set up and run the server +func main() { + // Load environment variables + if err := godotenv.Load(); err != nil { + log.Println("No .env file found") + } + + port := os.Getenv("PORT") + if port == "" { + port = "8080" // Default port if not specified + } + + r := gin.Default() + r.Use(cors.New(cors.Config{ + AllowOrigins: []string{"http://localhost:3000"}, + AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, + AllowHeaders: []string{"Origin", "Content-Type", "Accept", "Authorization"}, + ExposeHeaders: []string{"Content-Length"}, + AllowCredentials: true, + })) + + r.Use(cors.Default()) + r.Use(AuthorizeMiddleware()) + + + // Define routes + r.GET("/health", HealthCheckHandler) + r.GET("/users", GetUsersHandler) + r.POST("/users", AddUserHandler) + + // Start the server + log.Printf("Starting server on port %s", port) + if err := r.Run(":" + port); err != nil { + log.Fatalf("Could not start server: %v", err) + } +}