OwlbanGroup / skills-review-pull-requests

My clone repository
MIT License
0 stars 0 forks source link

Task Tile #2

Closed OwlbanGroup closed 8 months ago

OwlbanGroup commented 8 months ago

What - description of what you me to do Example: Hey @autopilot implement a Google 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: I want to allow users to signup and login using their Google account

codeautopilot[bot] commented 8 months ago

Potential solution

The task involves implementing Google sign-in functionality on both the front end and back end of a web application. The front end requires a Google sign-in button and the necessary JavaScript to handle the sign-in process, while the back end needs to verify the Google ID token and manage user sessions.

How to implement

Front End (index.html and auth.js)

  1. index.html: Add the Google API script tag and the sign-in button to the HTML. Initialize the Google sign-in SDK and define the onSignIn function to handle the sign-in success event.
<!-- Add the Google API script tag -->
<script src="https://apis.google.com/js/platform.js" async defer></script>
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">

<!-- Add the Google sign-in button -->
<div class="g-signin2" data-onsuccess="onSignIn"></div>

<script>
  function onSignIn(googleUser) {
    // Handle sign-in
  }
  function signOut() {
    // Handle sign-out
  }
</script>
  1. auth.js: Implement the client-side logic to handle the Google sign-in process, including rendering the sign-in button, handling the sign-in response, and sending the ID token to the back end.
function loadGoogleAPI() {
  gapi.load('auth2', function() {
    gapi.auth2.init({
      client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
      scope: 'profile email'
    }).then(function () {
      gapi.signin2.render('google-signin-button', {
        'onsuccess': onSignIn
      });
    });
  });
}

function onSignIn(googleUser) {
  var id_token = googleUser.getAuthResponse().id_token;
  sendTokenToBackend(id_token);
}

function sendTokenToBackend(id_token) {
  fetch('YOUR_BACKEND_ENDPOINT', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ token: id_token })
  })
  .then(response => response.json())
  .then(data => {
    console.log('Token verified by backend:', data);
  })
  .catch(error => {
    console.error('Error sending token to backend:', error);
  });
}

window.onload = loadGoogleAPI;

Back End (userController.js)

  1. userController.js: Implement the server-side logic to verify the Google ID token, interact with the database to find or create a user, and manage user sessions.
const { OAuth2Client } = require('google-auth-library');
const User = require('./models/user');
const client = new OAuth2Client(CLIENT_ID);

async function verifyToken(token) {
  const ticket = await client.verifyIdToken({
      idToken: token,
      audience: CLIENT_ID,
  });
  const payload = ticket.getPayload();
  return payload;
}

async function findOrCreateUser(userData) {
  let user = await User.findOne({ googleId: userData.sub });
  if (!user) {
    user = new User({
      googleId: userData.sub,
      email: userData.email,
      name: userData.name,
    });
    await user.save();
  }
  return user;
}

exports.googleSignIn = async (req, res) => {
  try {
    const { token } = req.body;
    const userData = await verifyToken(token);
    const user = await findOrCreateUser(userData);
    req.session.userId = user._id;
    res.status(200).json({ message: 'User signed in successfully', user });
  } catch (error) {
    res.status(500).json({ message: 'Authentication failed', error });
  }
};

Make sure to replace CLIENT_ID with your actual Google client ID, adjust the User model according to your application, and set up the necessary middleware for handling sessions and JSON requests.

Click here to create a Pull Request with the proposed solution

Files used for this task:

Changes on index.html To add a Google sign-in button and include the Google sign-in JavaScript SDK to the `index.html` file, follow these steps: 1. Add the Google API script tag to the head of the HTML document. 2. Insert a Google sign-in button in the appropriate place within the body of the document. 3. Initialize the Google sign-in SDK in the script section. Here's how you can modify the `index.html` file: ```html Tic Tac Toe
``` Make sure to replace `YOUR_CLIENT_ID` with the actual client ID provided by Google for your application. This code adds a Google sign-in button to your web page and initializes the sign-in process. When a user successfully signs in, the `onSignIn` function is called, which logs the user's information to the console. In a real-world scenario, you would send the ID token to your backend server for verification and to create a user session.
Changes on userController.js To address the task for the `userController.js` file, we need to implement the server-side logic to handle the Google authentication token, manage user records in the database, and handle user sessions. Here's a practical proposal for solving the task: 1. **Verify Google Authentication Token:** - Use Google's library or a suitable package to verify the token received from the client-side. For Node.js, you can use the `google-auth-library`. - Extract the user's information from the token after verification. 2. **Database Interaction:** - Connect to the database using an ORM like Mongoose if you're using MongoDB, or Sequelize for SQL databases. - Check if the user already exists in the database by querying with the Google ID. - If the user exists, update their record if necessary. - If the user does not exist, create a new record with the information obtained from the Google profile. 3. **Manage User Sessions:** - Implement session management using a package like `express-session` for Express.js applications. - Store the user's session information in the server-side session storage. - Set up the session cookie to maintain the user's logged-in state. Here's a sample implementation outline for `userController.js`: ```javascript const { OAuth2Client } = require('google-auth-library'); const User = require('./models/user'); // Assuming you have a User model const client = new OAuth2Client(CLIENT_ID); // Replace with your Google client ID async function verifyToken(token) { const ticket = await client.verifyIdToken({ idToken: token, audience: CLIENT_ID, }); const payload = ticket.getPayload(); return payload; } async function findOrCreateUser(userData) { let user = await User.findOne({ googleId: userData.sub }); if (!user) { user = new User({ googleId: userData.sub, email: userData.email, name: userData.name, // Add other relevant user fields }); await user.save(); } // Update user logic if necessary return user; } exports.googleSignIn = async (req, res) => { try { const { token } = req.body; const userData = await verifyToken(token); const user = await findOrCreateUser(userData); // Set up user session here req.session.userId = user._id; res.status(200).json({ message: 'User signed in successfully', user }); } catch (error) { res.status(500).json({ message: 'Authentication failed', error }); } }; // Additional session management setup and middleware if needed ``` Remember to replace `CLIENT_ID` with your actual Google client ID and adjust the User model and session management according to your specific application setup. This code assumes you are using Express.js and have middleware set up for parsing JSON requests and handling sessions.
Changes on auth.js To implement the client-side logic for Google sign-in in the `auth.js` file, follow these steps: 1. **Load the Google API library**: Include the Google API library in your HTML file if it's not already there. Since this task is specific to `auth.js`, ensure that the library is loaded before this script runs. 2. **Initialize the Google API client**: Use the `gapi.client.init` function to initialize the Google API client with your app's client ID and the scopes your application requires. 3. **Render the Google sign-in button**: Use the `gapi.signin2.render` function to render the Google sign-in button on your webpage. 4. **Handle the sign-in button click**: Set up a click event listener for the sign-in button that calls the `signIn` function when clicked. 5. **Sign in the user**: Create a `signIn` function that uses the `gapi.auth2.getAuthInstance().signIn()` method to sign in the user. 6. **Handle the sign-in response**: After the user is signed in, handle the response by extracting the ID token and sending it to your backend for verification. Here's a sample implementation for `auth.js`: ```javascript // Ensure the Google API client library has been loaded function loadGoogleAPI() { gapi.load('auth2', function() { // Initialize the Google auth2 library gapi.auth2.init({ client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com', // Replace with your client ID scope: 'profile email' // Specify the scopes your application needs }).then(function () { // Render the Google sign-in button gapi.signin2.render('google-signin-button', { 'onsuccess': onSignIn }); }); }); } // Sign-in success callback function onSignIn(googleUser) { // Get the Google ID token var id_token = googleUser.getAuthResponse().id_token; // Send the ID token to your backend for verification sendTokenToBackend(id_token); } // Send the ID token to the backend function sendTokenToBackend(id_token) { // Make an AJAX call (using fetch, XMLHttpRequest, or any other method) to your backend // Replace 'YOUR_BACKEND_ENDPOINT' with the endpoint that will handle the verification of the token fetch('YOUR_BACKEND_ENDPOINT', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token: id_token }) }) .then(response => response.json()) .then(data => { // Handle the response from your backend // For example, you might store the user's session or redirect the user to a dashboard console.log('Token verified by backend:', data); }) .catch(error => { console.error('Error sending token to backend:', error); }); } // Call loadGoogleAPI when the window loads window.onload = loadGoogleAPI; ``` Remember to replace `'YOUR_CLIENT_ID.apps.googleusercontent.com'` with your actual Google client ID and `'YOUR_BACKEND_ENDPOINT'` with the endpoint on your server that will handle the token verification. This script handles the client-side logic for Google sign-in. The actual verification of the token and the creation or update of the user record in the database will be handled in the `userController.js` file, as per the task plan.