Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Binary file modified .DS_Store
Binary file not shown.
Binary file modified app/.DS_Store
Binary file not shown.
5 changes: 5 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,8 @@ evalio_app-*.tar
# In case you use Node.js/npm, you want to ignore these.
npm-debug.log
/assets/node_modules/

credentials.json
token.pickle
zoom_token.pickle
zoom_config.py
123 changes: 123 additions & 0 deletions app/google_auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Google Authentication

This module provides Google OAuth authentication specifically for IIITD domain users (@iiitd.ac.in).

## Setup Instructions

1. Install the required Python packages:
```bash
pip install -r requirements.txt
```

2. Set up Google OAuth credentials:
- Go to the [Google Cloud Console](https://console.cloud.google.com/)
- Create a new project or select an existing one
- Enable the Google+ API
- Go to Credentials
- Create OAuth 2.0 Client ID
- Choose "Desktop app" as the application type
- Download the credentials file and save it as `credentials.json` in this directory

3. Set up PostgreSQL Database:
```bash
# Install PostgreSQL (if not already installed)
brew install postgresql@14

# Start PostgreSQL service
brew services start postgresql@14

# Create the database
createdb google_auth_db
```

4. Configure Database Connection:
- Open `google_auth.py`
- Update the `DB_CONFIG` dictionary if needed:
```python
DB_CONFIG = {
'dbname': 'google_auth_db',
'user': 'postgres', # Your PostgreSQL username
'password': 'postgres', # Your PostgreSQL password
'host': 'localhost',
'port': '5432'
}
```

## Usage

To run on CLI:
1. Run the authentication script:
```bash
python google_auth.py
```

2. Enter your IIITD email address when prompted

3. A browser window will open asking you to sign in with your Google account

4. After successful authentication, you'll see your user information displayed

To run through phoenix:
1. run python server using python3 google_auth_server.py

2. run phoenix app using mix phx.server

## Viewing the Database

You can view the stored data in several ways:

1. Using PostgreSQL command line (psql):
```bash
# Connect to the database
psql google_auth_db

# List all tables
\dt

# View all users
SELECT * FROM users;

# Exit psql
\q
```

2. Using pgAdmin (GUI Tool):
- Download and install [pgAdmin](https://www.pgadmin.org/download/)
- Connect to your PostgreSQL server
- Navigate to google_auth_db > Schemas > public > Tables
- Right-click on 'users' table and select "View/Edit Data"

## Database Schema

The `users` table contains the following columns:
- `id` (VARCHAR): Google's unique identifier
- `email` (VARCHAR): User's email address (unique)
- `name` (VARCHAR): Full name
- `given_name` (VARCHAR): First name
- `family_name` (VARCHAR): Last name
- `picture` (TEXT): Profile picture URL
- `verified_email` (BOOLEAN): Email verification status
- `locale` (VARCHAR): Language/location settings
- `hd` (VARCHAR): Hosted domain (iiitd.ac.in)
- `last_login` (TIMESTAMP): Last authentication time

## Google OAuth API Fields

The Google OAuth API returns the following user information fields:

1. `id` - Google's unique identifier for the user account
2. `email` - User's email address
3. `verified_email` - Boolean indicating if the email is verified
4. `name` - User's full name
5. `given_name` - User's first name
6. `family_name` - User's last name
7. `picture` - URL to the user's profile picture
8. `locale` - User's preferred language/location settings
9. `hd` - The hosted domain (should be 'iiitd.ac.in' for IIITD users)

## Security Notes

- The script stores authentication tokens in `token.pickle`
- Only @iiitd.ac.in email addresses are allowed
- The credentials are verified to match the provided email address
- Database passwords should be properly secured in production environments
169 changes: 169 additions & 0 deletions app/google_auth/google_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
import os.path
import pickle
import psycopg2
from datetime import datetime

# Database configuration
DB_CONFIG = {
'dbname': 'google_auth_db',
'user': 'postgres',
'password': 'postgres',
'host': 'localhost',
'port': '5432'
}

# If modifying these scopes, delete the file token.pickle.
SCOPES = [
'openid',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'
]

def get_db_connection():
"""Create and return a database connection."""
try:
conn = psycopg2.connect(**DB_CONFIG)
return conn
except Exception as e:
print(f"Error connecting to database: {str(e)}")
raise

def init_db():
"""Initialize the PostgreSQL database."""
conn = get_db_connection()
cur = conn.cursor()

# Create users table if it doesn't exist
cur.execute('''
CREATE TABLE IF NOT EXISTS users (
id VARCHAR(255) PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255),
given_name VARCHAR(255),
family_name VARCHAR(255),
picture TEXT,
verified_email BOOLEAN DEFAULT FALSE,
locale VARCHAR(10),
hd VARCHAR(255),
last_login TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
)
''')

conn.commit()
cur.close()
conn.close()

def store_user_data(user_info):
"""Store user information in the database."""
conn = get_db_connection()
cur = conn.cursor()

try:
# Prepare data for insertion
data = (
user_info.get('id'),
user_info.get('email'),
user_info.get('name'),
user_info.get('given_name'),
user_info.get('family_name'),
user_info.get('picture'),
user_info.get('verified_email', False),
user_info.get('locale'),
user_info.get('hd'),
datetime.now()
)

# Insert or update user data
cur.execute('''
INSERT INTO users
(id, email, name, given_name, family_name, picture,
verified_email, locale, hd, last_login)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
ON CONFLICT (id) DO UPDATE SET
email = EXCLUDED.email,
name = EXCLUDED.name,
given_name = EXCLUDED.given_name,
family_name = EXCLUDED.family_name,
picture = EXCLUDED.picture,
verified_email = EXCLUDED.verified_email,
locale = EXCLUDED.locale,
hd = EXCLUDED.hd,
last_login = EXCLUDED.last_login
''', data)

conn.commit()
except Exception as e:
print(f"Error storing user data: {str(e)}")
conn.rollback()
raise
finally:
cur.close()
conn.close()

def get_credentials():
"""Gets valid user credentials from storage."""
creds = None
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)

if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)

return creds

def verify_iiitd_domain(email):
"""Verifies if the email belongs to IIITD domain."""
return email.endswith('@iiitd.ac.in')

def main():
print("Welcome to IIITD Google Authentication")
print("Please enter your IIITD email address:")
email = input().strip()

if not verify_iiitd_domain(email):
print("Error: Only @iiitd.ac.in email addresses are allowed.")
return

try:
# Initialize database
init_db()

# Get credentials
creds = get_credentials()

# Get user info
from googleapiclient.discovery import build
service = build('oauth2', 'v2', credentials=creds)
user_info = service.userinfo().get().execute()

# Verify the email matches
if user_info['email'] != email:
print("Error: The authenticated email does not match the provided email.")
return

print("\nAuthentication successful!")
print("\nUser Information:")
print("-" * 50)
print(f"Name: {user_info.get('name', 'N/A')}")
print(f"Email: {user_info.get('email', 'N/A')}")
print(f"Profile Picture URL: {user_info.get('picture', 'N/A')}")

# Store user data in database
store_user_data(user_info)

except Exception as e:
print(f"An error occurred: {str(e)}")

if __name__ == '__main__':
main()
64 changes: 64 additions & 0 deletions app/google_auth/google_auth_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from flask import Flask, redirect, request, session
from google_auth_oauthlib.flow import Flow
import os
import secrets
from google_auth import init_db, store_user_data, verify_iiitd_domain

app = Flask(__name__)
app.secret_key = secrets.token_hex(16)
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" # For local testing only

CLIENT_SECRETS_FILE = "credentials.json"
SCOPES = [
'openid',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile'
]
REDIRECT_URI = "http://127.0.0.1:5000/auth/google/callback"

@app.route("/login/google")
def login():
flow = Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE,
scopes=SCOPES,
redirect_uri=REDIRECT_URI
)
authorization_url, state = flow.authorization_url()
session["state"] = state
return redirect(authorization_url)

@app.route("/auth/google/callback")
def callback():
state = session["state"]
flow = Flow.from_client_secrets_file(
CLIENT_SECRETS_FILE,
scopes=SCOPES,
state=state,
redirect_uri=REDIRECT_URI
)
flow.fetch_token(authorization_response=request.url)
credentials = flow.credentials

from googleapiclient.discovery import build
service = build('oauth2', 'v2', credentials=credentials)
user_info = service.userinfo().get().execute()

# Restrict to IIITD domain
if not verify_iiitd_domain(user_info.get('email', '')):
return "Error: Only @iiitd.ac.in email addresses are allowed.", 403

# Initialize DB and store user
try:
init_db()
store_user_data(user_info)
except Exception as e:
return f"Error storing user data: {str(e)}", 500

# For demo: create a simple token (in production, use JWT or similar)
token = user_info["id"] # Or sign a JWT with user_info

# Redirect back to Phoenix with the token
return redirect("http://127.0.0.1:4000/auth/google/callback?token={token}")

if __name__ == "__main__":
app.run(port=5000, debug=True)
Loading