Skip to content

Commit

Permalink
Admin: Add Google SSO for Compiler users (#1855)
Browse files Browse the repository at this point in the history
- Adds several new settings and Key Vault secrets
- Adds Django Google SSO package
- Fix: Django JS files are now allowed on Admin site
- Feat: Allow specific users with @complier.la emails to create and log into account on Admin
  • Loading branch information
machikoyasuda authored Feb 8, 2024
2 parents 4eec8a5 + 147cd51 commit 8faf1a7
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 3 deletions.
23 changes: 22 additions & 1 deletion benefits/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
The core application: Admin interface configuration.
"""

from django.conf import settings
import requests

from django.conf import settings

if settings.ADMIN:
import logging
Expand All @@ -21,3 +22,23 @@
]:
logger.debug(f"Register {model.__name__}")
admin.site.register(model)

def pre_login_user(user, request):
logger.debug(f"Running pre-login callback for user: {user.username}")
token = request.session.get("google_sso_access_token")
if token:
headers = {
"Authorization": f"Bearer {token}",
}

# Request Google user info to get name and email
url = "https://www.googleapis.com/oauth2/v3/userinfo"
response = requests.get(url, headers=headers, timeout=settings.REQUESTS_TIMEOUT)
user_data = response.json()
logger.debug(f"Updating admin user data from Google for user with email: {user_data['email']}")

user.first_name = user_data["given_name"]
user.last_name = user_data["family_name"]
user.username = user_data["email"]
user.email = user_data["email"]
user.save()
26 changes: 24 additions & 2 deletions benefits/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def _filter_empty(ls):

ADMIN = os.environ.get("DJANGO_ADMIN", "False").lower() == "true"

ALLOWED_HOSTS = _filter_empty(os.environ.get("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1").split(","))
ALLOWED_HOSTS = _filter_empty(os.environ.get("DJANGO_ALLOWED_HOSTS", "localhost").split(","))

# Application definition

Expand All @@ -37,11 +37,27 @@ def _filter_empty(ls):
]

if ADMIN:
GOOGLE_SSO_CLIENT_ID = os.environ.get("GOOGLE_SSO_CLIENT_ID", "secret")
GOOGLE_SSO_PROJECT_ID = os.environ.get("GOOGLE_SSO_PROJECT_ID", "benefits-admin")
GOOGLE_SSO_CLIENT_SECRET = os.environ.get("GOOGLE_SSO_CLIENT_SECRET", "secret")
GOOGLE_SSO_ALLOWABLE_DOMAINS = _filter_empty(os.environ.get("GOOGLE_SSO_ALLOWABLE_DOMAINS", "compiler.la").split(","))
GOOGLE_SSO_STAFF_LIST = _filter_empty(os.environ.get("GOOGLE_SSO_STAFF_LIST", "").split(","))
GOOGLE_SSO_SUPERUSER_LIST = _filter_empty(os.environ.get("GOOGLE_SSO_SUPERUSER_LIST", "").split(","))
GOOGLE_SSO_LOGO_URL = "/static/img/icon/google_sso_logo.svg"
GOOGLE_SSO_SAVE_ACCESS_TOKEN = True
GOOGLE_SSO_PRE_LOGIN_CALLBACK = "benefits.core.admin.pre_login_user"
GOOGLE_SSO_SCOPES = [
"openid",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
]

INSTALLED_APPS.extend(
[
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django_google_sso", # Add django_google_sso
]
)

Expand Down Expand Up @@ -282,7 +298,11 @@ def _filter_empty(ls):
if len(env_frame_src) > 0:
CSP_FRAME_SRC = env_frame_src

CSP_IMG_SRC = ["'self'", "data:"]
CSP_IMG_SRC = [
"'self'",
"data:",
"*.googleusercontent.com",
]

# Configuring strict Content Security Policy
# https://django-csp.readthedocs.io/en/latest/nonce.html
Expand All @@ -294,9 +314,11 @@ def _filter_empty(ls):
CSP_REPORT_URI = [sentry.SENTRY_CSP_REPORT_URI]

CSP_SCRIPT_SRC = [
"'self'",
"https://cdn.amplitude.com/libs/",
"https://cdn.jsdelivr.net/",
"*.littlepay.com",
"https://code.jquery.com/jquery-3.6.0.min.js",
]
env_script_src = _filter_empty(os.environ.get("DJANGO_CSP_SCRIPT_SRC", "").split(","))
CSP_SCRIPT_SRC.extend(env_script_src)
Expand Down
7 changes: 7 additions & 0 deletions benefits/static/img/icon/google_sso_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions benefits/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@ def trigger_error(request):

logger.debug("Register admin urls")
urlpatterns.append(path("admin/", admin.site.urls))
urlpatterns.append(path("google_sso/", include("django_google_sso.urls", namespace="django_google_sso")))
else:
logger.debug("Skip url registrations for admin")
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies = [
"Authlib==1.3.0",
"Django==5.0.1",
"django-csp==3.7",
"django-google-sso==5.0.0",
"eligibility-api==2023.9.1",
"requests==2.31.0",
"sentry-sdk==1.40.2",
Expand Down
9 changes: 9 additions & 0 deletions terraform/app_service.tf
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ resource "azurerm_linux_web_app" "main" {

"HEALTHCHECK_USER_AGENTS" = local.is_dev ? null : "${local.secret_prefix}healthcheck-user-agents)",

# Google SSO for Admin

"GOOGLE_SSO_CLIENT_ID" = "${local.secret_prefix}google-sso-client-id",
"GOOGLE_SSO_PROJECT_ID" = "${local.secret_prefix}google-sso-project-id",
"GOOGLE_SSO_CLIENT_SECRET" = "${local.secret_prefix}google-sso-client-secret",
"GOOGLE_SSO_ALLOWABLE_DOMAINS" = "${local.secret_prefix}google-sso-allowable-domains",
"GOOGLE_SSO_STAFF_LIST" = "${local.secret_prefix}google-sso-staff-list",
"GOOGLE_SSO_SUPERUSER_LIST" = "${local.secret_prefix}google-sso-superuser-list"

# Sentry
"SENTRY_DSN" = "${local.secret_prefix}sentry-dsn)",
"SENTRY_ENVIRONMENT" = local.env_name,
Expand Down

0 comments on commit 8faf1a7

Please sign in to comment.