Skip to content

feat: add Google authentication integration with new identity services #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ SET_PASSWORD_TOKEN_EXPIRES_IN=86400
SET_SESSION=1

# DATABSES
REDIS_URL="redis://localhost:6380"
MONGO_DATABASE_URL="mongodb://root:example@localhost:27017/typescript-backend-toolkit?authSource=admin"
REDIS_URL="redis://localhost:6388"
MONGO_DATABASE_URL="mongodb://root:example@localhost:27028/typescript-backend-toolkit?authSource=admin"

# Mailgun Configuration (dummy values for development)
MAILGUN_API_KEY="dummy-key"
Expand Down
3 changes: 1 addition & 2 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ SET_SESSION=0

# GOOGLE AUTH
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=''
GOOGLE_REDIRECT_URI = ''


# DATABSES
REDIS_URL=""
Expand Down
104 changes: 104 additions & 0 deletions GoogleAuth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Google Authentication Implementation Guide

This document explains how to implement Google authentication in the Typescript Backend Toolkit using Google Identity Services.

## Overview

The implementation uses Google's newer Identity Services API, which provides a more secure and user-friendly authentication experience compared to the older OAuth 2.0 redirect flow. The key differences are:

| Feature | Google Identity Services (New) | OAuth 2.0 Redirect Flow (Old) |
| -------------------- | --------------------------------- | ------------------------------ |
| User Experience | One-tap sign-in, popup-based flow | Full page redirects |
| Security | JWT-based ID tokens | Authorization code flow |
| Implementation | Client-side token generation | Server-side code exchange |
| Session Disruption | Minimal - stays on same page | High - navigates away from app |
| Cross-device Support | Better mobile/desktop integration | Requires more custom handling |

## Prerequisites

1. A Google Cloud Platform account
2. A configured OAuth 2.0 Client ID
3. Proper configuration of authorized JavaScript origins and redirect URIs

## Environment Variables

Add these variables to your `.env` file:

```
GOOGLE_CLIENT_ID=your-client-id-here
```

## Implementation Steps

### 1. Frontend Implementation

The frontend implementation uses Google's Identity Services library to handle the authentication flow:

```html
<!-- Include the Google Identity Services library -->
<script src="https://accounts.google.com/gsi/client" async defer></script>

<!-- Configure the Google Sign-In button -->
<div
id="g_id_onload"
data-client_id="YOUR_CLIENT_ID"
data-context="signin"
data-ux_mode="popup"
data-callback="handleCredentialResponse"
data-auto_prompt="false"
></div>

<!-- Render the Google Sign-In button -->
<div
class="g_id_signin"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left"
></div>

<script>
function handleCredentialResponse(response) {
// Get the ID token from the response
const idToken = response.credential;

// Send the ID token to your backend
fetch('/api/auth/google/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ idToken }),
})
.then((res) => res.json())
.then((data) => {
// Store the authentication token
if (data.data && data.data.token) {
localStorage.setItem('_auth_token_', data.data.token);
}
});
}
</script>
```

## Security Considerations

1. **Token Validation**: Always verify the ID token on your server using Google's libraries.
2. **Email Verification**: Check that the email is verified (`email_verified` claim).
3. **Expiration Time**: Verify the token hasn't expired (`exp` claim).
4. **HTTPS**: Always use HTTPS for token transmission.

## Troubleshooting

### Common Issues

1. **Invalid Client ID**: Ensure your client ID is correctly configured in both frontend and backend.
2. **CORS Issues**: Make sure your domain is listed in the authorized JavaScript origins.
3. **Token Verification Failures**: Check that your server time is synchronized.
4. **Missing Scopes**: Ensure you're requesting the necessary scopes (email, profile).

## References

- [Google Identity Services Documentation](https://developers.google.com/identity/gsi/web/guides/overview)
- [Google OAuth 2.0 for Client-side Web Applications](https://developers.google.com/identity/protocols/oauth2/javascript-implicit-flow)
- [Verifying Google ID Tokens](https://developers.google.com/identity/sign-in/web/backend-auth)
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ services:
image: mongo:5.0.2
restart: 'unless-stopped'
ports:
- '27017:27017'
- '27028:27017'
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
Expand All @@ -13,7 +13,7 @@ services:
redis:
image: redis:latest
ports:
- 6380:6379
- 6388:6379
volumes:
- redis_ts_toolkit:/data

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"express": "^4.19.2",
"express-async-handler": "^1.2.0",
"express-session": "^1.18.0",
"google-auth-library": "^9.15.1",
"helmet": "^6.0.1",
"http-status-codes": "^2.3.0",
"ioredis": "^5.3.2",
Expand Down
Loading