Open temichelle13 opened 2 months ago
To implement Google, Microsoft, and LinkedIn sign-in on your website, we need to make changes to both the front end and the back end of the application. This will involve adding sign-in buttons to the HTML, handling button clicks with JavaScript, styling the buttons with CSS, setting up OAuth routes in the backend, and configuring the necessary authentication providers.
index.html
Add sign-in buttons for Google, Microsoft, and LinkedIn within the appropriate section of the HTML file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Study Planner</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Study Planner</h1>
</header>
<main>
<section id="schedule">
<h2>Your Schedule</h2>
<!-- Schedule content goes here -->
</section>
<section id="tasks">
<h2>Your Tasks</h2>
<!-- Task list and management interface goes here -->
<div id="taskForm">
<form>
<!-- Form content for adding tasks -->
</form>
</div>
<div id="taskList">
<!-- Dynamic task list will be rendered here -->
</div>
</section>
<section id="auth">
<h2>Sign In</h2>
<button id="google-signin" class="oauth-button google-button">Sign in with Google</button>
<button id="microsoft-signin" class="oauth-button microsoft-button">Sign in with Microsoft</button>
<button id="linkedin-signin" class="oauth-button linkedin-button">Sign in with LinkedIn</button>
</section>
</main>
<footer>
<p>© 2023 Study Planner</p>
</footer>
<script src="main.js"></script>
</body>
</html>
main.js
Add JavaScript code to handle click events for the new sign-in buttons and redirect users to the appropriate OAuth endpoints.
document.addEventListener('DOMContentLoaded', function() {
const taskForm = document.getElementById('taskForm');
const taskList = document.getElementById('taskList');
taskForm.addEventListener('submit', function(e) {
e.preventDefault();
const title = document.getElementById('taskTitle').value;
const description = document.getElementById('taskDescription').value;
const dueDate = document.getElementById('taskDueDate').value;
fetch('/api/tasks', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ title, description, dueDate })
})
.then(response => response.json())
.then(addTaskToList)
.catch(error => console.error('Error:', error));
taskForm.reset();
});
function addTaskToList(task) {
const div = document.createElement('div');
div.innerHTML = `<h3>${task.title}</h3><p>${task.description}</p><p>Due: ${new Date(task.dueDate).toDateString()}</p>`;
taskList.appendChild(div);
}
fetch('/api/tasks')
.then(response => response.json())
.then(tasks => tasks.forEach(addTaskToList))
.catch(error => console.error('Error:', error));
document.getElementById('google-signin').addEventListener('click', function() {
window.location.href = '/auth/google';
});
document.getElementById('microsoft-signin').addEventListener('click', function() {
window.location.href = '/auth/microsoft';
});
document.getElementById('linkedin-signin').addEventListener('click', function() {
window.location.href = '/auth/linkedin';
});
});
style.css
Add specific CSS rules to style the new sign-in buttons.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
font-size: 16px;
}
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f4;
line-height: 1.6;
color: #333;
}
header {
background-color: #007bff;
color: white;
padding: 1rem;
text-align: center;
}
header h1 {
margin: 0;
}
main {
padding: 1rem;
}
section {
background-color: white;
margin-bottom: 1rem;
padding: 1rem;
border-radius: 0.5rem;
}
h2 {
margin-bottom: 0.5rem;
}
footer {
background-color: #f8f8f8;
text-align: center;
padding: 1rem;
}
@media (min-width: 768px) {
section {
margin: 1rem auto;
max-width: 80%;
}
}
.oauth-button {
display: inline-block;
width: 100%;
max-width: 300px;
padding: 10px;
margin: 10px 0;
border: none;
border-radius: 5px;
font-size: 1rem;
color: white;
text-align: center;
cursor: pointer;
transition: background-color 0.3s ease;
}
.oauth-button:hover {
opacity: 0.9;
}
.google-button {
background-color: #db4437;
}
.microsoft-button {
background-color: #2b579a;
}
.linkedin-button {
background-color: #0077b5;
}
routes/userRoutes.js
Add routes to handle OAuth callbacks from Google, Microsoft, and LinkedIn.
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const passport = require('passport');
const User = require('../models/user');
const router = express.Router();
router.post('/register', async (req, res) => {
try {
const user = new User(req.body);
await user.save();
const token = jwt.sign({ _id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.status(201).send({ user, token });
} catch (error) {
res.status(400).send(error);
}
});
router.post('/login', async (req, res) => {
try {
const user = await User.findByCredentials(req.body.email, req.body.password);
const token = jwt.sign({ _id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.send({ user, token });
} catch (error) {
res.status(400).send(error);
}
});
router.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
router.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), (req, res) => {
res.redirect('/');
});
router.get('/auth/microsoft', passport.authenticate('microsoft', { scope: ['user.read'] }));
router.get('/auth/microsoft/callback', passport.authenticate('microsoft', { failureRedirect: '/login' }), (req, res) => {
res.redirect('/');
});
router.get('/auth/linkedin', passport.authenticate('linkedin', { scope: ['r_liteprofile', 'r_emailaddress'] }));
router.get('/auth/linkedin/callback', passport.authenticate('linkedin', { failureRedirect: '/login' }), (req, res) => {
res.redirect('/');
});
module.exports = router;
auth/providers.json
Add configurations for Google, Microsoft, and LinkedIn authentication providers.
{
"anon-user": {
"name": "anon-user",
"type": "anon-user",
"disabled": false
},
"api-key": {
"name": "api-key",
"type": "api-key",
"disabled": true
},
"local-userpass": {
"name": "local-userpass",
"type": "local-userpass",
"config": {
"autoConfirm": true,
"resetFunctionName": "resetFunc",
"runConfirmationFunction": false,
"runResetFunction": true
},
"disabled": false
},
"google-oauth": {
"name": "google-oauth",
"type": "oauth2-google",
"config": {
"clientId": "YOUR_GOOGLE_CLIENT_ID",
"clientSecret": "YOUR_GOOGLE_CLIENT_SECRET",
"redirectUri": "YOUR_GOOGLE_REDIRECT_URI"
},
"disabled": false
},
"microsoft-oauth": {
"name": "microsoft-oauth",
"type": "oauth2-microsoft",
"config": {
"clientId": "YOUR_MICROSOFT_CLIENT_ID",
"clientSecret": "YOUR_MICROSOFT_CLIENT_SECRET",
"redirectUri": "YOUR_MICROSOFT_REDIRECT_URI"
},
"disabled": false
},
"linkedin-oauth": {
"name": "linkedin-oauth",
"type": "oauth2-linkedin",
"config": {
"clientId": "YOUR_LINKEDIN_CLIENT_ID",
"clientSecret": "YOUR_LINKEDIN_CLIENT_SECRET",
"redirectUri": "YOUR_LINKEDIN_REDIRECT_URI"
},
"disabled": false
}
}
app.js
Include middleware for handling OAuth authentication and session management.
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const morgan = require('morgan');
const helmet = require('helmet');
const session = require('express-session');
const passport = require('passport');
require('./auth/passport-setup');
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(helmet());
app.use(morgan('tiny'));
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
}));
app.use(passport.initialize());
app.use(passport.session());
process.on('uncaughtException', (error) => {
console.error(`Uncaught Exception: ${error.message}`);
process.exit(1);
});
process.on('unhandledRejection', (error) => {
console.error(`Unhandled Rejection: ${error.message}`);
process.exit(1);
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
auth/passport-setup.js
Configure the Passport strategies for Google, Microsoft, and LinkedIn.
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const MicrosoftStrategy = require('passport-microsoft').Strategy;
const LinkedInStrategy = require('passport-linkedin-oauth2').Strategy;
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback'
}, (accessToken, refreshToken, profile, done) => {
return done(null, profile);
}));
passport.use(new MicrosoftStrategy({
clientID: process.env.MICROSOFT_CLIENT_ID,
clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
callbackURL: '/auth/microsoft/callback'
}, (accessToken, refreshToken, profile, done) => {
return done(null, profile);
}));
passport.use(new LinkedInStrategy({
clientID: process.env.LINKEDIN_CLIENT_ID,
clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
callbackURL: '/auth/linkedin/callback',
scope: ['r_emailaddress', 'r_liteprofile'],
}, (accessToken, refreshToken, profile, done) => {
return done(null, profile);
}));
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((obj, done) => {
done(null, obj);
});
By following these steps, you will have implemented Google, Microsoft, and LinkedIn sign-in on your website, enhancing the user experience with easier sign-in options.
Click here to create a Pull Request with the proposed solution
Files used for this task:
${task.description}
Due: ${new Date(task.dueDate).toDateString()}
`; taskList.appendChild(div); } // Load existing tasks on page load fetch('/api/tasks') .then(response => response.json()) .then(tasks => tasks.forEach(addTaskToList)) .catch(error => console.error('Error:', error)); // Event listeners for OAuth sign-in buttons document.getElementById('googleSignIn').addEventListener('click', function() { window.location.href = '/auth/google'; }); document.getElementById('microsoftSignIn').addEventListener('click', function() { window.location.href = '/auth/microsoft'; }); document.getElementById('linkedinSignIn').addEventListener('click', function() { window.location.href = '/auth/linkedin'; }); }); ``` ### Explanation: 1. **Event Listeners for OAuth Buttons**: - Added event listeners for the Google, Microsoft, and LinkedIn sign-in buttons. - When a button is clicked, the user is redirected to the respective OAuth endpoint (`/auth/google`, `/auth/microsoft`, `/auth/linkedin`). 2. **HTML Button IDs**: - Ensure that the buttons in your `index.html` file have the IDs `googleSignIn`, `microsoftSignIn`, and `linkedinSignIn` respectively. This change will enable the front-end to handle click events for the new sign-in buttons and redirect users to the appropriate OAuth endpoints for authentication.
What - description of what you me to do Example: Hey @autopilot implement a Google, Microsoft, and Linkedin sign-in on my website. Make changes to the front end and the back end of the application.
Why - explain why this is important Example: Easier sign-in with Google, Microsoft, and LinkedIn.
Enhancements to front end and backend will ensure ease of navigation and that the layout is logical and functional without bugs.