index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
const express = require('express'); const axios = require('axios'); const cookieSession = require('cookie-session'); const cors = require('cors'); const app = express(); const port = 5000; // GitHub OAuth2 Configuration const clientId = ''; // Replace with your GitHub Client ID const clientSecret = ''; // Replace with your GitHub Client Secret const redirectUri = 'http://localhost:5000/oauth-callback'; // CORS to allow frontend requests app.use(cors({ origin: 'http://localhost:5173', // Replace with your frontend URL credentials: true, })); // Use cookie session to store the access token app.use(cookieSession({ name: 'github-oauth-session', keys: ['your-secret-key'], // Replace with a secure key maxAge: 24 * 60 * 60 * 1000, // 1 day })); // Route to initiate OAuth2 login app.get('/login', (req, res) => { const authorizationUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}`; res.redirect(authorizationUrl); }); // Callback route for GitHub OAuth app.get('/oauth-callback', async (req, res) => { const { code } = req.query; if (!code) { return res.status(400).send('No code received'); } try { // Exchange the code for an access token const tokenResponse = await axios.post('https://github.com/login/oauth/access_token', null, { params: { client_id: clientId, client_secret: clientSecret, code, redirect_uri: redirectUri, }, headers: { Accept: 'application/json', }, }); const { access_token } = tokenResponse.data; if (!access_token) { return res.status(400).send('Failed to obtain access token'); } // Store the access token in session req.session.access_token = access_token; // Redirect to the frontend res.redirect('http://localhost:5173'); } catch (error) { console.error(error); res.status(500).send('Error during OAuth callback'); } }); // Route to fetch user profile app.get('/user', async (req, res) => { const { access_token } = req.session; if (!access_token) { return res.status(401).send({ error: 'Not authenticated' }); } try { // Fetch user data from GitHub const userResponse = await axios.get('https://api.github.com/user', { headers: { Authorization: `Bearer ${access_token}`, }, }); const user = userResponse.data; console.log(user) res.json(user); } catch (error) { console.error(error); res.status(500).send({ error: 'Failed to fetch user data' }); } }); // Route to fetch user repositories app.get('/repos', async (req, res) => { const { access_token } = req.session; if (!access_token) { return res.status(401).send({ error: 'Not authenticated' }); } try { // Fetch user's repositories from GitHub const reposResponse = await axios.get('https://api.github.com/user/repos', { headers: { Authorization: `Bearer ${access_token}`, }, }); const repos = reposResponse.data; res.json(repos); } catch (error) { console.error(error); res.status(500).send({ error: 'Failed to fetch repositories' }); } }); // Start the server app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); }); |
App.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
import React, { useState, useEffect } from 'react'; import { Container, Button, Table, Alert } from 'react-bootstrap'; import 'bootstrap/dist/css/bootstrap.min.css'; const App = () => { const [user, setUser] = useState(null); const [repos, setRepos] = useState([]); const [error, setError] = useState(null); const loginWithGitHub = () => { // Redirect to the backend route for login window.location.href = 'http://localhost:5000/login'; }; const fetchUserProfile = async () => { try { // Fetch user profile data const userResponse = await fetch('http://localhost:5000/user', { method: 'GET', credentials: 'include', // Include cookies }); if (userResponse.status === 401) { throw new Error('Not authenticated'); } const userData = await userResponse.json(); setUser(userData); // Fetch user repositories const reposResponse = await fetch('http://localhost:5000/repos', { method: 'GET', credentials: 'include', }); if (!reposResponse.ok) { throw new Error('Failed to fetch repositories'); } const reposData = await reposResponse.json(); setRepos(reposData); } catch (err) { setError(err.message); } }; useEffect(() => { fetchUserProfile(); }, []); return ( <Container style={{ marginTop: '50px' }}> <h1 className="text-center">GitHub OAuth2 Login</h1> {!user ? ( <div className="text-center"> <Button onClick={loginWithGitHub} variant="primary"> Login with GitHub </Button> </div> ) : ( <div> <div className="text-center"> <h2>Welcome, {user.name}</h2> <img src={user.avatar_url} alt={user.login} style={{ width: 100, borderRadius: '50%' }} /> <p> <strong>Followers:</strong> {user.followers} |{' '} <strong>Following:</strong> {user.following} |{' '} <strong>Public Repos:</strong> {user.public_repos} </p> <Button onClick={() => { setUser(null); setRepos([]); document.cookie = 'github-oauth-session=; Max-Age=0'; // Clear session cookie }} variant="danger" > Logout </Button> </div> <hr /> <h3 className="text-center">Repositories</h3> {repos.length > 0 ? ( <Table striped bordered hover responsive> <thead> <tr> <th>#</th> <th>Name</th> <th>Description</th> <th>URL</th> </tr> </thead> <tbody> {repos.map((repo, index) => ( <tr key={repo.id}> <td>{index + 1}</td> <td>{repo.name}</td> <td>{repo.description || 'No description available'}</td> <td> <a href={repo.html_url} target="_blank" rel="noopener noreferrer" > View Repository </a> </td> </tr> ))} </tbody> </Table> ) : ( <p className="text-center">No repositories found.</p> )} </div> )} {error && <Alert variant="danger">{error}</Alert>} </Container> ); }; export default App; |