Skip to content

Commit

Permalink
feat: Prevent multiple logins by validating device fingerprint
Browse files Browse the repository at this point in the history
  • Loading branch information
IkramBagban committed Dec 9, 2024
1 parent e77b112 commit cd7b4b8
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 2 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"studio": "prisma studio"
},
"dependencies": {
"@fingerprintjs/fingerprintjs": "^4.5.1",
"@hookform/resolvers": "^3.6.0",
"@icons-pack/react-simple-icons": "^9.4.0",
"@prisma/client": "^5.18.0",
Expand Down
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "User" ADD COLUMN "deviceFingerprint" TEXT;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ model User {
name String?
email String? @unique
token String?
deviceFingerprint String?
sessions Session[]
purchases UserPurchases[]
videoProgress VideoProgress[]
Expand Down
3 changes: 3 additions & 0 deletions src/components/Signin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useRouter } from 'next/navigation';
import React, { useRef, useState, useEffect } from 'react';
import { toast } from 'sonner';
import { motion } from 'framer-motion';
import { generateFingerprint } from '@/lib/utils';

const emailDomains = [
'gmail.com',
Expand Down Expand Up @@ -123,9 +124,11 @@ const Signin = () => {
return;
}
setCheckingPassword(true);
const fingerprint = await generateFingerprint();
const res = await signIn('credentials', {
username: email.current,
password: password.current,
deviceFingerprint: fingerprint,
redirect: false,
});

Expand Down
35 changes: 33 additions & 2 deletions src/components/VideoPlayer2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ import 'videojs-seek-buttons/dist/videojs-seek-buttons.css';
import 'videojs-mobile-ui';
import 'videojs-sprite-thumbnails';
import 'videojs-seek-buttons';
import { handleMarkAsCompleted } from '@/lib/utils';
import { useSearchParams } from 'next/navigation';
import { generateFingerprint, handleMarkAsCompleted } from '@/lib/utils';
import { useRouter, useSearchParams } from 'next/navigation';
import './QualitySelectorControllBar';
import { YoutubeRenderer } from './YoutubeRenderer';
import { toast } from 'sonner';
import { createRoot } from 'react-dom/client';
import { PictureInPicture2 } from 'lucide-react';
import { AppxVideoPlayer } from './AppxVideoPlayer';
import { validateFingerPrint } from '@/actions/deviceFingerprintValidation';

// todo correct types
interface VideoPlayerProps {
Expand Down Expand Up @@ -46,6 +47,7 @@ export const VideoPlayer: FunctionComponent<VideoPlayerProps> = ({
const videoRef = useRef<HTMLDivElement>(null);
const playerRef = useRef<Player | null>(null);
const [player, setPlayer] = useState<any>(null);
const router = useRouter();
const searchParams = useSearchParams();
const vidUrl = options.sources[0].src;

Expand Down Expand Up @@ -134,6 +136,35 @@ export const VideoPlayer: FunctionComponent<VideoPlayerProps> = ({
};
}, [player]);

useEffect(() => {
let timer: any;
const checkFingerprint = async () => {
try {
const fingerprint: string = await generateFingerprint();
timer = setInterval(async () => {
try {
await validateFingerPrint(fingerprint);
} catch (error) {
console.error('Fingerprint validation failed:', error);
router.push('/invalidsession');
}
}, 1000 * 60 * 2);

return () => timer;
} catch (error) {
console.error('Error during fingerprint generation or validation:', error);
}
};

checkFingerprint();

return () => {
if (timer) {
clearInterval(timer);
}
};
}, []);

useEffect(() => {
const t = searchParams.get('timestamp');
if (contentId && player && !t) {
Expand Down
1 change: 1 addition & 0 deletions src/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const authOptions = {
},
data: {
token: jwt,
deviceFingerprint: credentials?.deviceFingerprint
},
});

Expand Down

0 comments on commit cd7b4b8

Please sign in to comment.