Update OAuth2.md
This commit is contained in:
parent
e4eceec39f
commit
54c8948b21
112
OAuth2.md
112
OAuth2.md
@ -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
|
# 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).
|
- `scope`: The permissions you're requesting (e.g., email, profile).
|
||||||
- `state`: A random string to protect against CSRF attacks.
|
- `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.
|
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>
|
<details>
|
||||||
<summary><h3>Frontend Code:</h3></summary>
|
<summary><h3>Example Frontend Code</h3></summary>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// On the backend callback URL, the frontend receives the authorization code
|
// On the backend callback URL, the frontend receives the authorization code
|
||||||
@ -92,6 +124,10 @@ export default Callback;
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 3. Backend (Node.js): Handle Token Exchange
|
# 3. Backend (Node.js): Handle Token Exchange
|
||||||
|
|
||||||
1. The backend receives the authorization `code` from the frontend,
|
1. The backend receives the authorization `code` from the frontend,
|
||||||
@ -122,7 +158,7 @@ client_secret=YOUR_GOOGLE_CLIENT_SECRET
|
|||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><h3>Backend Code:</h3></summary>
|
<summary><h3>Example Backend Code:</h3></summary>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const express = require('express');
|
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 Google’s 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
|
```sh
|
||||||
GET https://xorismesiti.gr/callback?
|
GET https://xorismesiti.gr/callback?
|
||||||
code=4/0AX4XfWgNmGZVbV7Kdr8Q9yVyzIYBnbbBdLfX39ZaE8m0w8zT8jKRLl7w-uT8k7WiyLg0Q&
|
code=4/0AX4XfWgNmGZVbV7Kdr8Q9yVyzIYBnbbBdLfX39ZaE8m0w8zT8jKRLl7w-uT8k7WiyLg0Q&
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user