This is an example project demonstrating how to use the @blur-effect/oauth2-handler
package with Google Calendar API. The example showcases multi-account support, allowing users to connect and manage multiple Google accounts simultaneously.
- Install dependencies:
npm install
- Create a
.env
file in the root directory with the following variables:
# Server Configuration
PORT=3000
SESSION_SECRET=your-session-secret
# Google OAuth Configuration
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_CALLBACK_URL=http://localhost:3000/oauth2/callback/google
-
Set up a Google Cloud Project and OAuth 2.0 credentials:
- Go to the Google Cloud Console (https://console.cloud.google.com)
- Create a new project or select an existing one
- Enable the Google Calendar API for your project
- Go to Credentials > Create Credentials > OAuth client ID
- Choose "Web application" as the application type
- Set the following:
- Name: Your app name
- Authorized JavaScript origins: http://localhost:3000
- Authorized redirect URIs: http://localhost:3000/oauth2/callback/google
- Copy the Client ID and Client Secret to your
.env
file
-
Start the server:
npm start
- Visit http://localhost:3000 in your browser
This example demonstrates how to implement multi-account support using the OAuth2 handler:
- Log in with your first Google account
- Click "Add Another Account" to add additional accounts
- Use different Google accounts for each login
- Switch between accounts using the "Switch" button
- Use "Remove" to delete a specific account
- Use "Logout All" to clear all accounts
The multi-account functionality is implemented through:
-
Session Storage:
- Accounts are stored in an array within the Express session
- Each account maintains its own authentication state and calendar events
-
Account Management:
- Active account is tracked via
activeAccountIndex
in the session - Users can switch between accounts without re-authenticating
- The UI clearly indicates which account is currently active
- Active account is tracked via
-
Token Management:
- Each account has its own OAuth tokens
- Individual accounts can be deleted via the UI
- When an account is removed, its OAuth tokens are properly deleted
The UniversalTokenStore
class provides these key methods for multi-account support:
-
getUserAccounts(agentId, provider):
- Retrieves all user accounts for a specific agent and provider
- Returns an array of
StoredUserData
objects containing user info and tokens - Used to display multiple connected accounts in the UI
const userAccounts = await store.getUserAccounts(req.sessionID, 'google');
-
deleteByEmail(agentId, provider, email):
- Deletes a specific account by its email address
- Returns a boolean indicating if the deletion was successful
- Used when removing a specific account
const deleted = await store.deleteByEmail(req.sessionID, 'google', email);
-
save(agentId, provider, tokens):
- Saves OAuth tokens for a specific user
- Also fetches and stores user info using the provider's fetcher
- Called automatically during OAuth callback
-
registerProvider(provider, fetcher):
- Registers a user info fetcher for a specific provider
- The fetcher is used to retrieve user data from access tokens
- Essential for storing user information alongside tokens
store.registerProvider('google', new GoogleUserInfoFetcher());
The Express application implements these route handlers for multi-account management:
-
OAuth Callback Handler -
/oauth2/callback/google
:- Processes OAuth authentication callbacks
- Retrieves user information and adds to session accounts array
- Updates existing accounts or adds new ones
-
Switch Account -
/switch-account/:index
:- Changes the active account by updating
activeAccountIndex
- Preserves all connected accounts in the session
- Allows switching without re-authentication
- Changes the active account by updating
-
Logout Specific Account -
/logout/:index
:- Removes a specific account from the session
- Deletes the associated token from the token store
- Updates the active index if needed
-
Logout All Accounts -
/logout-all
:- Destroys the session entirely
- Removes all connected accounts at once
The application uses Express session middleware to maintain account state:
app.use(async (req, res, next) => {
// Initialize the accounts array if it doesn't exist
if (!req.session.accounts) {
req.session.accounts = [];
}
// Set the active account if there's at least one and none is active
if (req.session.accounts.length > 0 && req.session.activeAccountIndex === undefined) {
req.session.activeAccountIndex = 0;
}
next();
});
The session stores:
-
accounts
: Array of connected user accounts -
activeAccountIndex
: Index of the currently active account
The application refreshes account data on page load:
// In home route handler
if (req.session.accounts && req.session.accounts.length > 0) {
const userAccounts = await store.getUserAccounts(req.sessionID, 'google');
// Update accounts data if available
if (userAccounts && userAccounts.length > 0) {
// Create an updated accounts array preserving our events data
const updatedAccounts = [];
// Process all stored accounts from the token store
for (const userData of userAccounts) {
// Find if we already have this account in the session
const existingIndex = req.session.accounts.findIndex(
acc => acc.email === userData.userInfo.email
);
// Update existing or add new account
// ...
}
}
}
- Google OAuth authentication with multi-account support
- Google Calendar API integration
- Session management for multiple accounts
- Protected routes
- Calendar event display and management
- Token deletion by email
- Account switching interface
- UniversalTokenStore: Stores tokens and user data, supports multiple accounts per session
- Multiple Account UI: Displays all connected accounts with active account indication
- Middleware: Ensures session initialization and account data refreshing
-
src/index.js
- Main application file with multi-account implementation -
src/views/
- EJS templates with account management UI -
src/public/
- Static assets including CSS for multi-account interface -
.env
- Environment variables (not included in git)
The application includes debugging information to help understand the multi-account flow:
- Debug info panel shows active account index and total accounts
- Console logs for authentication flow and account management
- Visual indicators for the active account
-
/
- Home page with account list -
/auth/google
- Start Google OAuth flow -
/oauth2/callback/google
- OAuth callback handler -
/switch-account/:index
- Switch to another connected account -
/logout/:index
- Remove a specific account -
/logout-all
- Remove all connected accounts -
/calendar
- View calendar events for the active account -
/delete-token
- API endpoint to delete tokens by email