Update OAuth2.md

This commit is contained in:
Ste Vaidis 2024-12-15 11:51:04 +02:00
parent d930c66c53
commit c5b29972c1

152
OAuth2.md
View File

@ -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. 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. 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, 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. <details>
<summary>Code:</summary>
```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 <div>Loading...</div>;
};
export default Callback;
```
</details>
# 3. Backend (Node.js): Handle Token Exchange # 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` 1. The backend receives the authorization `code` from the frontend,
2. Ensure you never expose the client_secret to the frontend. This step should always be handled on the backend. 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 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. 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
```
<details>
<summary>Code:</summary>
```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');
});
```
</details>
```sh ```sh
GET https://xorismesiti.gr/callback? 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. 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) # 5. Access Token Response (Google Returns Tokens)