### OAuth2 purpose A way for the `user` to tell `google` to give an access token to `xorismesiti.gr` app


### OAuth2 Standar Flow: 1. **User** clicks button "Login with Google" on your platform `xorismesiti.gr` 2. **Authorization Request**: Button redirects user to Google's authorization endpoint `accounts.google.com/o/oauth2` 3. **User Login and Consent**: User login to Google and grants permissions. 4. **Authorization Code Response**: Google redirects user back to your app `xorismesiti.gr/callback` with an authorization `code`. 5. **Access Token Request**: App exchanges the authorization `code` for an `access_token`. 6. **Access Protected Resources**: App uses the `access_token` to fetch the user's Google profile and email from `googleapis.com/oauth2` 7. **Token Refresh** (Optional): If the `access_token` expires, app uses the `refresh token` to get a new `access_token`.


### OAuth2 Frontend/`Backend Flow: **Frontend** 1. **Redirect** the user to Google's OAuth authorization endpoint `accounts.google.com/o/oauth2` 2. **Get** the authorization `code` after Google redirects back to the frontend `xorismesiti.gr/callback` 3. **Send** the authorization `code` to the backend for `token` exchange. **Backend** 1. **exchange** the authorization `code` for an `access_token` and `refresh token` 2. **fetch** user profile data from from `googleapis.com/oauth2` using the `access_token` 3. **Store** the `tokens` securely in session (front) or a database (back) 4. **Refresh** the `access_token` if it expires


# 1. [Frontend] Request Authorization code 1. The use clicks a "Login with Google" link button with a URL to Google's OAuth 2.0 authorization endpoint and redirects the user there. 2. After this redirection, the user will log in to Google and grant permissions (if they haven’t already). 3. Google will redirect the user back to your specified redirect_uri with an authorization code.

Frontend HTTP Request to Google

```sh GET https://accounts.google.com/o/oauth2/v2/auth? response_type=code& client_id=ABC34JHS9D& redirect_uri=https://xorismesiti.gr/callback& scope=email%20profile& state=xyz123 ``` - `response_type=code`: This indicates you're using the "authorization code" flow. - `client_id`: Your Google API client ID. Created by the developers of the `xorismesiti.gr` on the google API console. - `redirect_uri`: The URI Google will redirect to after the user consents. - `scope`: The permissions you're requesting (e.g., email, profile). - `state`: A random string to protect against CSRF attacks.

Google HTTP Response to Frontend

```bash HTTP/1.1 302 Found Location: https://xorismesiti.gr/api/auth/callback?code=4/0AX4XfWgyVyz-uT8k7WiyLg0Q&state=xyz123 Content-Type: text/html; charset=UTF-8 Content-Length: 0 ```

Frontent Code

```js // Redirect to Google's OAuth 2.0 endpoint when user clicks login const loginWithGoogle = () => { const clientId = 'ABC34JHS9D'; // Replace with your actual Google Client ID const redirectUri = 'https://xorismesiti.gr/api/auth/callback'; // Backend URL where Google will send the user after login const scope = 'email profile'; // Scopes you're requesting (email, profile, etc.) const state = 'random-state-value'; // For CSRF protection const googleAuthUrl = `https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}&state=${state}`; window.location.href = googleAuthUrl; // Redirect user to Google }; ```



# 2. [Frontend] Receive Authorization Code 1. User grants permission 2. Google redirect the user to the `redirect_uri` you specified in the previous request (`https://xorismesiti.gr/api/auth/callback`) 3. The frontend must not directly exchange the `code` for an `access_token`. Instead, it sends the `code` to the backend via an API request.

Frontend HTTP Request to Backend

```bash POST https://xorismesiti.gr/api/auth/exchange-token Content-Type: application/json { "code": "authorization-code-from-google" } ```

Backend HTTP Response to Frontend

```json { "access_token": "ya29.a0AfH6SMC8Op6zXZkHi2XITkDoOVzYXt3hTY6sny54UlWlxrnKlX5Xv78is7BEHekVX-VoA", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "1//04d5XHqmn6Hdy3wTf5OYDP1SyBa74zEFURjddQ2A1cFw78PY13pQyWhlD2A6XhDQtKlrjAqU4kS3vGdMvckw", "scope": "email profile" } ```

Frontend Code

```js // On the backend callback URL, the frontend receives the authorization code import { useEffect } from 'react'; import { useRouter } from 'next/router'; const Callback = () => { const router = useRouter(); useEffect(() => { const { code, state } = router.query; // Send the authorization code to the backend for token exchange fetch('/api/auth/exchange-token', { method: 'POST', body: JSON.stringify({ code }), headers: { 'Content-Type': 'application/json', }, }) .then(response => response.json()) .then(data => { // Handle success (store token, update UI, etc.) console.log(data); // Typically, you'll store the access token here or manage the user session. router.push('/dashboard'); // Redirect the user to their dashboard or home page. }) .catch(error => { console.error('Error exchanging token:', error); }); }, []); return
Loading...
; }; export default Callback; ```



# 3. [Backend] Exchange Code with Token 1. The backend receives the authorization `code` from the frontend, 2. The backend makes a `POST` request to Google token endpoint, to exchange the authorization `code` for the `access_token` and optionally a `refresh token` 3. The backend ensures to never expose the client_secret to the frontend. This step should always be handled on the backend. 4. The backend will exchange the `code` for an `access_token` and `refresh_token`, which are sent back to the frontend or stored securely for subsequent API calls.

Backend HTTP Request to Google

- `HTTP` Method: POST - `URL`: https://oauth2.googleapis.com/token - `Headers`: - `Content`-Type: application/x-www-form-urlencoded - `Body` Parameters: - `grant_type`=authorization_code: This specifies the grant type. - `code`: The authorization code you received in the previous step. - `redirect_uri`: The same redirect URI used in the authorization request. - `client_id`: Your Google API client ID. - `client_secret`: Your Google API client secret (which should be kept secure). ```sh POST https://oauth2.googleapis.com/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code& code=4/0AX4XfWgNmGZVbV7Kdr8Q9yVyzIYBnbbBdLfX39ZaE8m0w8zT8jKRLl7w-uT8k7WiyLg0Q& redirect_uri=https://xorismesiti.gr/callback& client_id=YOUR_GOOGLE_CLIENT_ID& client_secret=YOUR_GOOGLE_CLIENT_SECRET ```

Google HTTP Response Backend and Backend response to Frontend

```json { "access_token": "ya29.a0AfH6SMC8Op6zXZkHi2XITkDoOVzYXt3hTY6sny54UlWlxrnKlX5Xv78is7BEHekVX-VoA", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "1//04d5XHqmn6Hdy3wTf5OYDP1SyBa74zEFURjddQ2A1cFw78PY13pQyWhlD2A6XhDQtKlrjAqU4kS3vGdMvckw", "scope": "email profile" } ```

Backend Code:

```js const express = require('express'); const axios = require('axios'); const app = express(); app.use(express.json()); // To parse JSON bodies const clientId = 'YOUR_GOOGLE_CLIENT_ID'; // Google Client ID const clientSecret = 'YOUR_GOOGLE_CLIENT_SECRET'; // Google Client Secret const redirectUri = 'https://xorismesiti.gr/api/auth/callback'; // Must match the one used in frontend // Handle token exchange app.post('/api/auth/exchange-token', async (req, res) => { const { code } = req.body; try { const response = await axios.post('https://oauth2.googleapis.com/token', null, { params: { code, client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri, grant_type: 'authorization_code', }, }); const { access_token, refresh_token, expires_in } = response.data; // Optionally, store the tokens in a secure location (e.g., session, database) // For now, send them back to the frontend (not recommended for production) res.json({ access_token, refresh_token, expires_in }); } catch (error) { console.error('Error exchanging authorization code for token:', error); res.status(500).json({ error: 'Failed to exchange authorization code for access token' }); } }); // Start the server app.listen(3000, () => { console.log('Server running on http://localhost:3000'); }); ```



# 4. [Frontend] Use the Access Token Once the backend exchanges the `code` for the `access_token`, the frontend can use it to make authenticated requests to the backend or Google APIs

Frontend HTTP Request to Backend

```bash GET https://xorismesiti.gr/api/user-profile Authorization: Bearer access-token-from-backend ```

Frontend HTTP Response from Backend

```json { "sub": "1234567890", "name": "John Doe", "given_name": "John", "family_name": "Doe", "profile": "https://plus.google.com/1234567890", "picture": "https://lh3.googleusercontent.com/a-/AOh14GgIXXl5JXzW0c1Szbl-e1Jch1vhl5rHhH65vlK6J5g5PqkGjj1O0p3t8bgVEOykQ6ykFSQ=s96", "email": "john.doe@example.com", "email_verified": true, "locale": "en" } ```

Frontend Code:

```js // After receiving the token, store it in the frontend (e.g., localStorage or context) localStorage.setItem('access_token', response.access_token); // Use it to make authenticated API requests to the backend fetch('/api/user-profile', { headers: { 'Authorization': `Bearer ${localStorage.getItem('access_token')}`, }, }) .then(response => response.json()) .then(data => { // Handle user data }) .catch(error => { console.error('Error fetching user profile:', error); }); ```



# 5. [Backend] Fetch User Data With the access token obtained in the previous step, your platform can now use it to fetch the user's Google profile and email information. The token is included in the Authorization header of the request.

HTTP Request

```sh GET https://www.googleapis.com/oauth2/v3/userinfo Authorization: Bearer ya29.a0AfH6SMC8Op6zXZkHi2XITkDoOVzYXt3hTY6sny54UlWlxrnKlX5Xv78is7BEHekVX-VoA ``` - URL: https://www.googleapis.com/oauth2/v3/userinfo - HTTP Method: GET - Headers: - Authorization: Bearer {access_token}: The access token obtained in step 5.

HTTP Response

```json { "sub": "1234567890", "name": "John Doe", "given_name": "John", "family_name": "Doe", "profile": "https://plus.google.com/1234567890", "picture": "https://lh3.googleusercontent.com/a-/AOh14GgIXXl5JXzW0c1Szbl-e1Jch1vhl5rHhH65vlK6J5g5PqkGjj1O0p3t8bgVEOykQ6ykFSQ=s96", "email": "john.doe@example.com", "email_verified": true, "locale": "en" } ```

Backend Code:

```js app.get('/api/user-profile', async (req, res) => { const accessToken = req.headers['authorization'].split(' ')[1]; // Extract token from Authorization header try { const response = await axios.get('https://www.googleapis.com/oauth2/v3/userinfo', { headers: { Authorization: `Bearer ${accessToken}`, }, }); // Send the user profile data to the frontend res.json(response.data); } catch (error) { console.error('Error fetching user profile:', error); res.status(500).json({ error: 'Failed to fetch user profile' }); } }); ```



# 6. [Backend] Token Expiry and Refresh (Optional) If the access token expires, your platform can use the refresh token (if provided) to obtain a new access token without requiring the user to log in again.

HTTP Request

```bash POST https://oauth2.googleapis.com/token Content-Type: application/x-www-form-urlencoded grant_type=refresh_token& refresh_token=refresh-token-from-backend& client_id=YOUR_GOOGLE_CLIENT_ID& client_secret=YOUR_GOOGLE_CLIENT_SECRET ``` - `URL`: https://oauth2.googleapis.com/token - `HTTP` Method: POST - `Headers`: - `Content`-Type: application/x-www-form-urlencoded - `Body` Parameters: - `grant_type`=refresh_token: This indicates the refresh token flow. - `refresh_token`: The refresh token obtained in step 5. - `client_id`: Your Google API client ID. - `client_secret`: Your Google API client secret.

HTTP Response

```json { "access_token": "ya29.a0AfH6SMC8Op6zXZkHi2XITkDoOVzYXt3hTY6sny54UlWlxrnKlX5Xv78is7BEHekVX-VoA", "token_type": "Bearer", "expires_in": 3600 } ```

Example Backend Code:

```js app.post('/api/auth/refresh-token', async (req, res) => { const { refresh_token } = req.body; try { const response = await axios.post('https://oauth2.googleapis.com/token', null, { params: { refresh_token, client_id: clientId, client_secret: clientSecret, grant_type: 'refresh_token', }, }); res.json(response.data); // Return new access token and refresh token } catch (error) { console.error('Error refreshing access token:', error); res.status(500).json({ error: 'Failed to refresh access token' }); } }); ```