Update OAuth2.md

This commit is contained in:
Ste Vaidis 2024-12-15 12:01:30 +02:00
parent e4eceec39f
commit 54c8948b21

112
OAuth2.md
View File

@ -14,6 +14,20 @@ A way for the `user` to tell `google` to give an access token to `xorismesiti.gr
### Summary of Tasks Split Across Frontend and Backend:
***Frontend**
1. Redirect the user to Google's OAuth authorization endpoint.
2. Capture the authorization code after Google redirects back to the frontend.
3. Send the authorization code to the backend for token exchange.
**Backend**
1. Handle the token exchange (exchange the authorization code for an access token and refresh token).
2. Optionally fetch user profile data from Google (or other resources) using the access token.
3. Store the tokens securely (in session or a database).
4. Provide a way to refresh the access token if it expires.
5. By splitting the OAuth flow this way, the sensitive details (like the client secret and token exchange) remain secure on the backend, while the frontend handles user interaction.
# 1. [Frontend] Request Authorization code
@ -39,6 +53,24 @@ GET https://accounts.google.com/o/oauth2/v2/auth?
- `scope`: The permissions you're requesting (e.g., email, profile).
- `state`: A random string to protect against CSRF attacks.
<details>
<summary><h3>Example Frontent Code</h3></summary>
```js
// Redirect to Google's OAuth 2.0 endpoint when user clicks login
const loginWithGoogle = () => {
const clientId = 'YOUR_GOOGLE_CLIENT_ID'; // 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
};
```
</details>
@ -52,7 +84,7 @@ GET https://accounts.google.com/o/oauth2/v2/auth?
The frontend must not directly exchange the `code` for an `access_token`. Instead, it sends the `code` to the backend via an API request.
<details>
<summary><h3>Frontend Code:</h3></summary>
<summary><h3>Example Frontend Code</h3></summary>
```js
// On the backend callback URL, the frontend receives the authorization code
@ -92,6 +124,10 @@ export default Callback;
</details>
# 3. Backend (Node.js): Handle Token Exchange
1. The backend receives the authorization `code` from the frontend,
@ -122,7 +158,7 @@ client_secret=YOUR_GOOGLE_CLIENT_SECRET
```
<details>
<summary><h3>Backend Code:</h3></summary>
<summary><h3>Example Backend Code:</h3></summary>
```js
const express = require('express');
@ -172,6 +208,78 @@ app.listen(3000, () => {
# 5. [Backend] Fetch User Data (Optional)
If you want to fetch the user profile data (e.g., from Google), your backend can use the `access_token` to request it from Googles user info endpoint.
<details>
<summary><h3>Example Backend Code:</h3></summary>
```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' });
}
});
```
</details>
# 6. [Backend] Token Expiry and Refresh (Optional)
<details>
<summary><h3>Example Backend Code:</h3></summary>
```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' });
}
});
```
</details>
```sh
GET https://xorismesiti.gr/callback?
code=4/0AX4XfWgNmGZVbV7Kdr8Q9yVyzIYBnbbBdLfX39ZaE8m0w8zT8jKRLl7w-uT8k7WiyLg0Q&