Update OAuth2-Backend-Approach.md
This commit is contained in:
parent
17fad574ff
commit
4457e53ff1
@ -1,6 +1,6 @@
|
|||||||
### OAuth2 purpose
|
### OAuth2 purpose
|
||||||
|
|
||||||
A way for the `user` to tell `google` to give an access to `xorismesiti.gr` app
|
A way for the `user` to tell `google` to give an access to `myapp` app
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
@ -12,25 +12,25 @@ A way for the `user` to tell `google` to give an access to `xorismesiti.gr` app
|
|||||||
| 2 | Exchange Code with Token | ` Back ⇢ Google ⇢ Back ⇢ Front `|
|
| 2 | Exchange Code with Token | ` Back ⇢ Google ⇢ Back ⇢ Front `|
|
||||||
| 4 | Use Token | ` Front ⇢ Back ⇢ Google ⇢ Back ⇢ Front `|
|
| 4 | Use Token | ` Front ⇢ Back ⇢ Google ⇢ Back ⇢ Front `|
|
||||||
|
|
||||||
<br>
|
<br><br>
|
||||||
|
|
||||||
|
|
||||||
### Details:
|
### Details:
|
||||||
|
|
||||||
1. Get Code
|
1. Get Authorization Code
|
||||||
|
|
||||||
1. Frontend **GET** to Google `https://accounts.google.com/o/oauth2` with callback url
|
1. Frontend **Navigate** to Google URL with a callback url
|
||||||
2. Google **302** to Backend `https://xorismesiti.gr/api/auth/callback` with authorization code
|
2. Google **Redirect** to Backend's callback url with the authorization code
|
||||||
|
|
||||||
2. Exchange Code with Token
|
2. Exchange Code with Token
|
||||||
|
|
||||||
1. Backend **POST** the `code` to Google `https://oauth2.googleapis.com/token`
|
1. Backend **POST** the `code` to Google `https://oauth2.googleapis.com/token`
|
||||||
2. Google **response** to Backend with an `access_token` and a `refresh token`
|
2. Google **response** to Backend with an `access_token` and a `refresh token`
|
||||||
3. Backend **response** to Frontend with the `access_token` in a `cookie`
|
3. Backend **redirect** to Frontend `https://myapp/auth/success` with the `access_token` in a `cookie`
|
||||||
|
|
||||||
3. Use Token
|
3. Use Token
|
||||||
|
|
||||||
1. Frontend **GET** profile data from Backend `https://xorismesiti.gr/api/auth/profile` using the `cookie`
|
1. Frontend **GET** profile data from Backend `https://myapp/api/auth/profile` using the `cookie`
|
||||||
2. Backend **GET** profile data from Google `https://www.googleapis.com/oauth2/v3/userinfo` using the `access_token` from Frontend `cookie`
|
2. Backend **GET** profile data from Google `https://www.googleapis.com/oauth2/v3/userinfo` using the `access_token` from Frontend `cookie`
|
||||||
3. Google **response** to Backend with profile data
|
3. Google **response** to Backend with profile data
|
||||||
4. Backend **response** to Frontend with profile data
|
4. Backend **response** to Frontend with profile data
|
||||||
@ -42,24 +42,24 @@ A way for the `user` to tell `google` to give an access to `xorismesiti.gr` app
|
|||||||
# 1. Get Code
|
# 1. Get Code
|
||||||
|
|
||||||
1. Frontend **GET** to Google `https://accounts.google.com/o/oauth2` with callback url
|
1. Frontend **GET** to Google `https://accounts.google.com/o/oauth2` with callback url
|
||||||
2. Google **302** to Backend `https://xorismesiti.gr/api/auth/callback` with authorization code
|
2. Google **302** to Backend `https://myapp/api/auth/callback` with authorization code
|
||||||
|
|
||||||
### 1. Front **GET** to Google
|
### 1. Front **GET** to Google
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
GET https://accounts.google.com/o/oauth2/v2/auth?
|
GET https://accounts.google.com/o/oauth2/v2/auth?
|
||||||
response_type=code& # This indicates you're using the "authorization code" flow.
|
response_type=code& # This indicates you're using the "authorization code" flow.
|
||||||
client_id=ABC34JHS9D& # Your Google API client ID created on the google API console.
|
client_id=ABC34JHS9D& # Your Google API client ID created on the google API console.
|
||||||
redirect_uri=https://xorismesiti.gr/api/auth/callback& # The URI Google will redirect to after the user consents.
|
redirect_uri=https://myapp/api/auth/callback& # The URI Google will redirect to after the user consents.
|
||||||
scope=email%20profile& # The permissions you're requesting (e.g., email, profile).
|
scope=email%20profile& # The permissions you're requesting (e.g., email, profile).
|
||||||
state=xyz123 # A random string to protect against CSRF attacks.
|
state=xyz123 # A random string to protect against CSRF attacks.
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Google **302** to Back
|
### 2. Google **302** to Back
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
HTTP/1.1 302 Found
|
HTTP/1.1 302 Found
|
||||||
Location: https://xorismesiti.gr/api/auth/callback?code=4/0AX4XfWgyVyz-uT8k7WiyLg0Q&state=xyz123
|
Location: https://myapp/api/auth/callback?code=4/0AX4XfWgyVyz-uT8k7WiyLg0Q&state=xyz123
|
||||||
Content-Type: text/html; charset=UTF-8
|
Content-Type: text/html; charset=UTF-8
|
||||||
Content-Length: 0
|
Content-Length: 0
|
||||||
```
|
```
|
||||||
@ -86,7 +86,7 @@ grant_type=authorization_code&
|
|||||||
code=AAAABCX4XfWgyVyziyLg0QHHHHH&
|
code=AAAABCX4XfWgyVyziyLg0QHHHHH&
|
||||||
client_id=ABC34JHS9D&
|
client_id=ABC34JHS9D&
|
||||||
client_secret=PASS1234&
|
client_secret=PASS1234&
|
||||||
redirect_uri=https://xorismesiti.gr/callback
|
redirect_uri=https://myapp/callback
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Google **response** to Backend
|
### 2. Google **response** to Backend
|
||||||
@ -129,33 +129,43 @@ redirect_uri=https://xorismesiti.gr/callback
|
|||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// Backend callback URL: http://localhost:3000/auth/google/callback
|
app.get('/callback', async (req, res) => {
|
||||||
app.get('/auth/google/callback', async (req, res) => {
|
|
||||||
const { code } = req.query; // Extract the code from the query string
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Exchange the authorization code for access token and refresh token
|
// 1. Get the authorization code from Google's redirect
|
||||||
const response = await axios.post('https://oauth2.googleapis.com/token', null, {
|
const { code } = req.query;
|
||||||
params: {
|
|
||||||
code,
|
// 2. Exchange the code for tokens
|
||||||
client_id: clientId,
|
const tokenResponse = await fetch('https://oauth2.googleapis.com/token', {
|
||||||
client_secret: clientSecret,
|
method: 'POST',
|
||||||
redirect_uri: redirectUri, // Same as in Step 1
|
headers: {
|
||||||
grant_type: 'authorization_code',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
code,
|
||||||
|
client_id: process.env.GOOGLE_CLIENT_ID,
|
||||||
|
client_secret: process.env.GOOGLE_CLIENT_SECRET,
|
||||||
|
redirect_uri: 'https://myapp/callback',
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { access_token, refresh_token, expires_in } = response.data;
|
const { access_token, refresh_token } = await tokenResponse.json();
|
||||||
|
|
||||||
// Store tokens in session or cookies
|
// 3. Set the HTTP-only cookie with the access token
|
||||||
res.cookie('access_token', access_token, { httpOnly: true, secure: true, maxAge: expires_in * 1000 });
|
res.cookie('access', access_token, {
|
||||||
res.cookie('refresh_token', refresh_token, { httpOnly: true, secure: true });
|
httpOnly: true, // Cannot be accessed by client-side JavaScript
|
||||||
|
secure: true, // Only sent over HTTPS
|
||||||
// Respond to frontend or redirect as needed
|
sameSite: 'strict', // CSRF protection
|
||||||
res.send('Authentication successful! You can now use the app.');
|
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. Store refresh token securely in database (recommended)
|
||||||
|
// await db.storeRefreshToken(user_id, refresh_token);
|
||||||
|
|
||||||
|
// 5. Redirect back to frontend
|
||||||
|
res.redirect('https://myapp/authentication-success');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error exchanging code for tokens:', error);
|
res.redirect('https://myapp/authentication-error');
|
||||||
res.status(500).send('Error during authentication');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -173,7 +183,7 @@ app.get('/auth/google/callback', async (req, res) => {
|
|||||||
### 1. Frontend **GET** profile data from Backend
|
### 1. Frontend **GET** profile data from Backend
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X GET https://xorismesiti.gr/api/auth/profile \
|
curl -X GET https://myapp/api/auth/profile \
|
||||||
-H "Cookie: access_token=ya29.a0AfH6SMC8Op6zXZkHi2XITkDoOVzYXt3hTY6sny54UlWlxrnKlX5Xv78is7BEHekVX-VoA" \
|
-H "Cookie: access_token=ya29.a0AfH6SMC8Op6zXZkHi2XITkDoOVzYXt3hTY6sny54UlWlxrnKlX5Xv78is7BEHekVX-VoA" \
|
||||||
-H "Accept: application/json"
|
-H "Accept: application/json"
|
||||||
```
|
```
|
||||||
@ -282,7 +292,7 @@ export default App;
|
|||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
```bash
|
```bash
|
||||||
GET https://xorismesiti.gr/api/user-profile
|
GET https://myapp/api/user-profile
|
||||||
Authorization: Bearer access-token-from-backend
|
Authorization: Bearer access-token-from-backend
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user