Dashboard / Auth & Encryption
--:--:--
Staging Live
3 Alerts
Total Users
50
Mock dataset · Mockaroo
2FA Enrolled
—
— of users protected
Encrypted Fields
6
AES-256-GCM · at rest
Pending 2FA
—
— setup incomplete
User Security Status
Live · Staging DB
UserRole2FAOAuthPhone (enc.)Last Login
Activity Log
Live
Field Encryption
AES-256-GCM
2FA Adoption
TOTP · RFC 6238
Enrollment rate —
MonTueWedThuFriSatSun
Active 2FA—
Pending setup—
Not enrolled—
OAuth Providers
PKCE
🔴
Google
Active
—
⬡
GitHub
Active
—
✉
Email
bcrypt×12
—
Security Alerts
3 Open
AES-256-GCM — Core Encryption Snippet
Python · PyCryptodome
Production-ready
from Crypto.Cipher import AES
import os, base64

# 256-bit key loaded from env / secret vault — never hardcoded
KEY = bytes.fromhex(os.environ["AES_MASTER_KEY"]) # 32-byte key

def encrypt_field(plaintext: str) -> str:
    cipher = AES.new(KEY, AES.MODE_GCM)
    ct, tag = cipher.encrypt_and_digest(plaintext.encode("utf-8"))
    # Pack: nonce(16) + tag(16) + ciphertext
    return base64.b64encode(cipher.nonce + tag + ct).decode()

def decrypt_field(token: str) -> str:
    raw = base64.b64decode(token)
    nonce, tag, ct = raw[:16], raw[16:32], raw[32:]
    cipher = AES.new(KEY, AES.MODE_GCM, nonce=nonce)
    return cipher.decrypt_and_verify(ct, tag).decode("utf-8")
All Users
50 total
UserEmailRole2FAOAuthActions
TOTP Simulator
Google Authenticator

Simulate 2FA verification. The demo code changes every 30 seconds like a real TOTP token.

Current TOTP Code
------
Expires in 30s
Enter the 6-digit code to verify:
2FA Status Overview
All 50 users
Overall enrollment —
User2FA StatusAction
Google OAuth
Active
Client IDconfigured ✓
Redirect URIconfigured ✓
Scopeemail, profile
FlowCode + PKCE
Users—
GitHub OAuth
Active
Client IDconfigured ✓
Redirect URIconfigured ✓
Scoperead:user, user:email
FlowCode + PKCE
Users—
Email / Password
bcrypt × 12
Hash algobcrypt
Work factor12 rounds
Saltauto-generated
Reset flowJWT · 15 min TTL
Users—
OAuth Flow — Authorization Code + PKCE
RFC 7636
# Flask-Dance — Google OAuth 2.0 + PKCE (simplified)
from flask import Flask, redirect, url_for, session
from flask_dance.contrib.google import make_google_blueprint, google
import os

app = Flask(__name__)
app.secret_key = os.environ["FLASK_SECRET"]

bp = make_google_blueprint(
    client_id=os.environ["GOOGLE_CLIENT_ID"],
    client_secret=os.environ["GOOGLE_CLIENT_SECRET"],
    scope=["openid", "email", "profile"],
)
app.register_blueprint(bp, url_prefix="/login")

@app.route("/dashboard")
def dashboard():
    if not google.authorized: return redirect(url_for("google.login"))
    resp = google.get("/oauth2/v2/userinfo")
    user = resp.json() # { email, name, picture, ... }
    return f"Welcome {user['name']}"
Field Encryption Status
AES-256-GCM
Live Encrypt / Decrypt Demo
Browser simulation
— click Encrypt to see output —
—
⚠ Browser simulation using Web Crypto AES-GCM (identical algorithm). Production uses PyCryptodome on the server.
Complete AES-256-GCM Implementation
Python · Full module
"""aes_crypto.py — Internee.pk field-level AES-256-GCM encryption"""
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import os, base64, json
from functools import wraps

# ── Key management ──────────────────────────────────────────────
_KEY: bytes | None = None

def load_key() -> bytes:
    global _KEY
    if _KEY is None:
        hex_key = os.environ.get("AES_MASTER_KEY")
        if not hex_key: raise RuntimeError("AES_MASTER_KEY not set")
        _KEY = bytes.fromhex(hex_key)
        if len(_KEY) != 32: raise ValueError("Key must be 256-bit (32 bytes)")
    return _KEY

# ── Core encrypt / decrypt ───────────────────────────────────────
def encrypt_field(plaintext: str) -> str:
    """Encrypt a string field → base64(nonce+tag+ciphertext)"""
    key = load_key()
    cipher = AES.new(key, AES.MODE_GCM)
    ct, tag = cipher.encrypt_and_digest(plaintext.encode("utf-8"))
    return base64.b64encode(cipher.nonce + tag + ct).decode()

def decrypt_field(token: str) -> str:
    """Decrypt a base64 token → original string. Raises on tamper."""
    key = load_key()
    raw = base64.b64decode(token)
    nonce, tag, ct = raw[:16], raw[16:32], raw[32:]
    cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
    return cipher.decrypt_and_verify(ct, tag).decode("utf-8")

# ── SQLAlchemy TypeDecorator (auto-encrypt columns) ──────────────
from sqlalchemy import TypeDecorator, Text

class EncryptedString(TypeDecorator):
    """Column type that transparently encrypts/decrypts values."""
    impl = Text; cache_ok = True
    def process_bind_param(self, value, dialect):
        return encrypt_field(value) if value is not None else None
    def process_result_value(self, value, dialect):
        return decrypt_field(value) if value is not None else None

# ── Model usage ──────────────────────────────────────────────────
# class User(Base):
# phone = Column(EncryptedString) # auto-encrypts on save
# cnic = Column(EncryptedString) # auto-decrypts on read
Security Alerts
3 Open
Audit Log
Last 24h
Key Vault
4 active keys
Security Settings
Global config