Update OAuth2.md

This commit is contained in:
Ste Vaidis 2024-12-15 15:10:30 +02:00
parent 128d95b6c6
commit f374f492ac

View File

@ -41,6 +41,8 @@ A way for the `user` to tell `google` to give an access token to `xorismesiti.gr
2. After the redirection, the user will log in to Google and grant permissions (if they havent already). 2. After the redirection, the user will log in to Google and grant permissions (if they havent already).
3. Google will redirect the user back to your redirect_uri `https://xorismesiti.gr/callback` with an authorization code `?code=` 3. Google will redirect the user back to your redirect_uri `https://xorismesiti.gr/callback` with an authorization code `?code=`
*Security: the state string should be validated upon receiving the response from Google, as it ensures that the response corresponds to the request.*
<details> <details>
<summary><h3>Frontend HTTP GET Request to Google</h3></summary> <summary><h3>Frontend HTTP GET Request to Google</h3></summary>
@ -100,7 +102,7 @@ const loginWithGoogle = () => {
# 2. [Frontend] Receive Authorization Code # 2. [Frontend] Receive Authorization Code
Now that the frontend have the Authorization `code` on th callback url https://xorismesiti.gr/api/auth/callback`?code=AAAABCX4XfWgyVyziyLg0QHHHHH` it can send it to the backend with POST to `xorismesiti.gr/api/auth/exchange-token`, in order the backend to exchange the `code` for an `access_token` and optionally an `refresh_token` Now that the frontend has the Authorization `code` on th callback url https://xorismesiti.gr/api/auth/callback`?code=AAAABCX4XfWgyVyziyLg0QHHHHH` it can send it to the backend with POST to `xorismesiti.gr/api/auth/exchange-token`, in order the backend to exchange the `code` for an `access_token` and optionally an `refresh_token`
<details> <details>
<summary><h3>Frontend HTTP POST Request to Backend</h3></summary> <summary><h3>Frontend HTTP POST Request to Backend</h3></summary>
@ -324,22 +326,81 @@ Authorization: Bearer access-token-from-backend
<summary><h3>Frontend Code</h3></summary> <summary><h3>Frontend Code</h3></summary>
```js ```js
// After receiving the token, store it in the frontend (e.g., localStorage or context) // Store tokens and expiration time after receiving them from the backend
localStorage.setItem('access_token', response.access_token); const storeTokens = (access_token, refresh_token, expires_in) => {
const expirationTime = Date.now() + expires_in * 1000; // expires_in is in seconds, so multiply by 1000 to get ms
localStorage.setItem('access_token', access_token);
localStorage.setItem('refresh_token', refresh_token);
localStorage.setItem('token_expiration', expirationTime);
};
// Use it to make authenticated API requests to the backend // Function to check if the access token has expired
fetch('/api/user-profile', { const isTokenExpired = () => {
headers: { const expirationTime = localStorage.getItem('token_expiration');
'Authorization': `Bearer ${localStorage.getItem('access_token')}`, return Date.now() > expirationTime;
}, };
})
.then(response => response.json()) // Function to refresh the access token using the refresh token
.then(data => { const refreshAccessToken = async () => {
// Handle user data const refresh_token = localStorage.getItem('refresh_token');
}) try {
.catch(error => { const response = await fetch('/api/auth/refresh-token', {
method: 'POST',
body: JSON.stringify({ refresh_token }),
headers: {
'Content-Type': 'application/json',
},
});
const data = await response.json();
if (data.access_token) {
// Store the new access token and expiration time
storeTokens(data.access_token, data.refresh_token, data.expires_in);
return data.access_token;
}
} catch (error) {
console.error('Error refreshing token:', error);
return null; // Handle error appropriately (e.g., logout user or prompt to log in again)
}
};
// Function to get the access token, either from localStorage or by refreshing it if expired
const getAccessToken = async () => {
if (isTokenExpired()) {
console.log('Access token expired. Refreshing...');
const newAccessToken = await refreshAccessToken();
return newAccessToken;
} else {
return localStorage.getItem('access_token');
}
};
// Example usage: Get the access token and use it for an authenticated API request
const fetchUserProfile = async () => {
const access_token = await getAccessToken();
if (!access_token) {
console.error('No valid access token found. User might need to log in.');
return;
}
// Now you can use the access token to make an authenticated API request
try {
const response = await fetch('/api/user-profile', {
headers: {
'Authorization': `Bearer ${access_token}`,
},
});
const userData = await response.json();
console.log(userData);
} catch (error) {
console.error('Error fetching user profile:', error); console.error('Error fetching user profile:', error);
}); }
};
// Example call to fetch user profile
fetchUserProfile();
``` ```
</details> </details>