diff --git a/OAuth2.md b/OAuth2.md index 76f0eab..d2e6c8b 100644 --- a/OAuth2.md +++ b/OAuth2.md @@ -15,7 +15,9 @@ A way for the `user` to tell `google` to give an access token to `xorismesiti.gr -# 1. [Frontend] Authorization Request: Redirect the user to Google's OAuth Authorization Endpoint +# 1. [Frontend] Request Authorization code + +### Redirect the user to Google's OAuth Authorization Endpoint 1. Action: The frontend provides a "Login with Google" button. 2. When the user clicks it, the frontend constructs a URL to Google's OAuth 2.0 authorization endpoint and redirects the user there. @@ -40,22 +42,135 @@ GET https://accounts.google.com/o/oauth2/v2/auth? -# 2. Frontend (Next.js): Receive the Authorization Code and Send it to the Backend +# 2. [Frontend] Receive Authorization Code + +### And send it to the Backend 1. Once the user grants permission, -2. Google will redirect the user to the `redirect_uri` you specified in the previous step (e.g., https://xorismesiti.gr/api/auth/callback) +2. Google will redirect the user to the `redirect_uri` you specified in the previous step (`https://xorismesiti.gr/api/auth/callback`) -The frontend must not directly exchange the `code` for an `access_token`. +The frontend must not directly exchange the `code` for an `access_token`. Instead, it sends the `code` to the backend via an API request. -Instead, it sends the `code` to the backend via an API request. +
+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 (Node.js): Handle Token Exchange -1. The backend makes a `POST` request to Google token endpoint, to exchange the authorization `code` for the `access_token` and optionally a `refresh token` -2. Ensure you never expose the client_secret to the frontend. This step should always be handled on the backend. -3. 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. +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. + +- `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 +``` + +
+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'); +}); +``` + +
+ + + ```sh GET https://xorismesiti.gr/callback? @@ -74,30 +189,9 @@ GET https://xorismesiti.gr/callback? Now your platform can use exchange the authorization code for an access token and refresh token. -1. it sends a POST request to Google's token endpoint - -- `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 -``` # 5. Access Token Response (Google Returns Tokens)