This repository has been archived by the owner on Dec 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
940 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
modules = ["python-3.11"] | ||
|
||
[nix] | ||
channel = "stable-24_05" | ||
|
||
[workflows] | ||
runButton = "Project" | ||
|
||
[[workflows.workflow]] | ||
name = "Project" | ||
mode = "parallel" | ||
author = "agent" | ||
|
||
[[workflows.workflow.tasks]] | ||
task = "workflow.run" | ||
args = "Start Flask App" | ||
|
||
[[workflows.workflow]] | ||
name = "Start Flask App" | ||
author = "agent" | ||
|
||
[workflows.workflow.metadata] | ||
agentRequireRestartOnSave = false | ||
|
||
[[workflows.workflow.tasks]] | ||
task = "shell.exec" | ||
args = "python main.py" | ||
waitForPort = 5000 | ||
|
||
[deployment] | ||
run = ["sh", "-c", "python main.py"] | ||
|
||
[[ports]] | ||
localPort = 5000 | ||
externalPort = 80 |
258 changes: 258 additions & 0 deletions
258
...structions-you-can-pass-on-to-your-developers-to-build-the-Pehchan-Port-1726671759041.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
Here’s a set of detailed instructions you can pass on to your developers to build the **Pehchan Portal** for registration: | ||
|
||
--- | ||
|
||
### **Project Overview:** | ||
Build a **Pehchan Registration Portal** that allows Pakistani citizens to register for an account, enabling them to use the Pehchan service for logging into government services. The portal should integrate with Keycloak for identity and access management, and optionally validate CNIC via an external API. | ||
|
||
### **1. Project Structure and Tech Stack** | ||
|
||
- **Frontend**: Use HTML, CSS, and JavaScript for the UI. You may use a framework like **React** or **Vue** if needed. | ||
- **Backend**: Use **Node.js** with **Express.js** to manage API calls and integrate with Keycloak. | ||
- **Authentication**: Use **Keycloak** for identity management. | ||
- **Database**: Use PostgreSQL (already configured with Keycloak) for storing additional user attributes if needed. | ||
- **Environment**: Use **Docker** for local development and containerization of services. | ||
|
||
### **2. Key Features** | ||
|
||
The Pehchan portal should provide the following functionality: | ||
1. **User Registration Form** | ||
- Collect user's full name, email, phone number, CNIC, and password. | ||
- Optionally allow users to upload a profile picture or integrate biometric registration. | ||
|
||
2. **CNIC Validation** | ||
- Validate CNIC using a third-party service (e.g., NADRA API) if available. | ||
- Prevent users from proceeding without a valid CNIC. | ||
|
||
3. **Email/Phone Verification** | ||
- Send verification codes to the user’s email or phone for validation. | ||
- Block user registration until verification is complete. | ||
|
||
4. **Multi-Factor Authentication (MFA)** | ||
- Optionally integrate MFA during registration (SMS OTP or email OTP). | ||
|
||
5. **User Login Integration** | ||
- Redirect users to Keycloak’s login page after registration. | ||
- Handle the OAuth2 authentication flow for future logins. | ||
|
||
--- | ||
|
||
### **3. Detailed Step-by-Step Instructions** | ||
|
||
#### **Step 1: Set Up Project Structure** | ||
|
||
- **Frontend:** | ||
- Create a directory for the frontend code: | ||
``` | ||
pehchan-portal/ | ||
├── public/ | ||
│ └── styles.css | ||
├── views/ | ||
│ └── register.ejs | ||
├── app.js | ||
└── package.json | ||
``` | ||
|
||
- Use `EJS` for templating and serve static assets (CSS/JS). | ||
|
||
- **Backend:** | ||
- Set up **Express.js** for handling form submissions, API calls, and interactions with Keycloak. | ||
|
||
#### **Step 2: Build the Registration UI** | ||
|
||
**Registration Form:** | ||
|
||
1. **Frontend Form (register.ejs):** | ||
- Build a form that captures the following fields: | ||
- Full Name | ||
- Email Address | ||
- Phone Number | ||
- CNIC Number | ||
- Password | ||
- Add client-side validation for the fields (especially CNIC and email). | ||
|
||
```html | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Pehchan Registration</title> | ||
<link rel="stylesheet" href="/styles.css"> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<h1>Register for Pehchan</h1> | ||
<form action="/register" method="POST"> | ||
<label for="fullName">Full Name:</label> | ||
<input type="text" id="fullName" name="fullName" required> | ||
|
||
<label for="email">Email:</label> | ||
<input type="email" id="email" name="email" required> | ||
|
||
<label for="phone">Phone Number:</label> | ||
<input type="tel" id="phone" name="phone" required> | ||
|
||
<label for="cnic">CNIC:</label> | ||
<input type="text" id="cnic" name="cnic" required> | ||
|
||
<label for="password">Password:</label> | ||
<input type="password" id="password" name="password" required> | ||
|
||
<button type="submit">Register</button> | ||
</form> | ||
</div> | ||
</body> | ||
</html> | ||
``` | ||
|
||
2. **CSS (styles.css):** | ||
- Create a simple, clean design with CSS. | ||
|
||
3. **Client-Side Validation:** | ||
- Use JavaScript to validate form inputs before submission (e.g., CNIC format, password strength). | ||
|
||
#### **Step 3: Backend for Registration** | ||
|
||
**Backend Logic (app.js):** | ||
|
||
1. **Set up Express.js:** | ||
- Install required packages: | ||
```bash | ||
npm init -y | ||
npm install express body-parser axios dotenv ejs | ||
``` | ||
|
||
2. **Handle Form Submission:** | ||
- Create a POST route to handle form submissions and send the data to Keycloak for registration: | ||
|
||
```javascript | ||
require('dotenv').config(); | ||
const express = require('express'); | ||
const axios = require('axios'); | ||
const bodyParser = require('body-parser'); | ||
const app = express(); | ||
|
||
app.use(bodyParser.urlencoded({ extended: true })); | ||
app.set('view engine', 'ejs'); | ||
|
||
// Serve static files | ||
app.use(express.static('public')); | ||
|
||
// Render the registration form | ||
app.get('/register', (req, res) => { | ||
res.render('register'); | ||
}); | ||
|
||
// Handle form submission | ||
app.post('/register', async (req, res) => { | ||
const { fullName, email, phone, cnic, password } = req.body; | ||
|
||
// Integrate NADRA API to validate CNIC (if available) | ||
const isValidCNIC = await validateCNIC(cnic); | ||
if (!isValidCNIC) { | ||
return res.status(400).send('Invalid CNIC'); | ||
} | ||
|
||
// Call Keycloak Admin API to register the user | ||
try { | ||
await registerUserInKeycloak(fullName, email, phone, cnic, password); | ||
res.send('Registration successful! Please check your email to verify your account.'); | ||
} catch (error) { | ||
console.error('Error registering user:', error); | ||
res.status(500).send('Registration failed.'); | ||
} | ||
}); | ||
|
||
async function validateCNIC(cnic) { | ||
// Call NADRA API or other government services to validate CNIC | ||
return true; // Assume validation is successful for this example | ||
} | ||
|
||
async function registerUserInKeycloak(fullName, email, phone, cnic, password) { | ||
const keycloakUrl = `${process.env.KEYCLOAK_URL}/auth/admin/realms/pehchan/users`; | ||
const response = await axios.post(keycloakUrl, { | ||
firstName: fullName.split(' ')[0], | ||
lastName: fullName.split(' ').slice(1).join(' '), | ||
email: email, | ||
username: email, | ||
enabled: true, | ||
attributes: { | ||
phoneNumber: phone, | ||
cnic: cnic | ||
}, | ||
credentials: [{ | ||
type: 'password', | ||
value: password, | ||
temporary: false | ||
}] | ||
}, { | ||
headers: { | ||
'Authorization': `Bearer ${process.env.KEYCLOAK_ADMIN_TOKEN}`, | ||
'Content-Type': 'application/json' | ||
} | ||
}); | ||
|
||
return response.data; | ||
} | ||
|
||
// Start the server | ||
const port = process.env.PORT || 3000; | ||
app.listen(port, () => { | ||
console.log(`Pehchan portal running on http://localhost:${port}`); | ||
}); | ||
``` | ||
|
||
#### **Step 4: Integrate with Keycloak** | ||
|
||
1. **Enable User Registration in Keycloak:** | ||
- In the Keycloak Admin Console: | ||
- Go to **Realm Settings** > **Login**. | ||
- Enable **User Registration**. | ||
- Enable **Email Verification** if desired. | ||
|
||
2. **Admin REST API Access:** | ||
- Use Keycloak’s Admin REST API to create users. Your backend will need to authenticate to Keycloak using the **Admin Token**: | ||
- Generate the token using the `/auth/realms/master/protocol/openid-connect/token` endpoint. | ||
- Use the token for API calls to create users. | ||
|
||
3. **Customize Registration Page:** | ||
- If using Keycloak’s default registration, customize the page by building a custom Keycloak theme as previously discussed. | ||
|
||
#### **Step 5: Email/Phone Verification** | ||
|
||
1. **Verification Process:** | ||
- After user registration, send a verification email or SMS with a code. | ||
- On successful verification, mark the user as **verified** in Keycloak. | ||
|
||
2. **Verification Handling:** | ||
- Use Keycloak’s email verification or handle the verification manually via the API. | ||
|
||
#### **Step 6: Multi-Factor Authentication (Optional)** | ||
|
||
1. **MFA Setup:** | ||
- Prompt users to set up multi-factor authentication after registration (e.g., OTP via SMS or email). | ||
- Keycloak supports various MFA mechanisms (TOTP, OTP via SMS, etc.). | ||
|
||
2. **Enforce MFA for Specific Users:** | ||
- Add roles in Keycloak for users who require MFA, and apply MFA policies during login. | ||
|
||
--- | ||
|
||
### **6. Testing the Pehchan Portal** | ||
|
||
1. **Test Registration:** | ||
- Test the registration flow from form submission to user creation in Keycloak. | ||
|
||
2. **Test CNIC Validation:** | ||
- Simulate or integrate a real CNIC validation service (like NADRA). | ||
|
||
3. **Test Email/Phone Verification:** | ||
- Ensure the verification process works correctly. | ||
|
||
4. **Test MFA (Optional):** | ||
- Test MFA setup and enforcement. | ||
|
||
--- | ||
|
||
These instructions should give your dev team a comprehensive overview of how to build the Pehchan Registration Portal. If you need further clarification or additional steps, let me know! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import sqlite3 | ||
from flask import g | ||
|
||
DATABASE = 'pehchan.db' | ||
|
||
def get_db(): | ||
db = getattr(g, '_database', None) | ||
if db is None: | ||
db = g._database = sqlite3.connect(DATABASE) | ||
return db | ||
|
||
def init_db(): | ||
with sqlite3.connect(DATABASE) as conn: | ||
conn.execute(''' | ||
CREATE TABLE IF NOT EXISTS users ( | ||
id INTEGER PRIMARY KEY AUTOINCREMENT, | ||
full_name TEXT NOT NULL, | ||
email TEXT UNIQUE NOT NULL, | ||
phone TEXT NOT NULL, | ||
cnic TEXT UNIQUE NOT NULL, | ||
password TEXT NOT NULL, | ||
verified BOOLEAN NOT NULL DEFAULT 0 | ||
) | ||
''') | ||
|
||
def add_user(full_name, email, phone, cnic, password): | ||
with sqlite3.connect(DATABASE) as conn: | ||
cursor = conn.cursor() | ||
cursor.execute(''' | ||
INSERT INTO users (full_name, email, phone, cnic, password) | ||
VALUES (?, ?, ?, ?, ?) | ||
''', (full_name, email, phone, cnic, password)) | ||
return cursor.lastrowid | ||
|
||
def get_user_by_email(email): | ||
with sqlite3.connect(DATABASE) as conn: | ||
cursor = conn.cursor() | ||
cursor.execute('SELECT * FROM users WHERE email = ?', (email,)) | ||
user = cursor.fetchone() | ||
if user: | ||
return { | ||
'id': user[0], | ||
'full_name': user[1], | ||
'email': user[2], | ||
'phone': user[3], | ||
'cnic': user[4], | ||
'password': user[5], | ||
'verified': user[6] | ||
} | ||
return None | ||
|
||
def verify_user(user_id): | ||
with sqlite3.connect(DATABASE) as conn: | ||
conn.execute('UPDATE users SET verified = 1 WHERE id = ?', (user_id,)) |
Oops, something went wrong.