Skip to content

Add ORCID OAuth 2.0 authentication integration#123

Merged
mpasternak merged 6 commits into
devfrom
claude/refine-local-plan-1S0E0
Apr 14, 2026
Merged

Add ORCID OAuth 2.0 authentication integration#123
mpasternak merged 6 commits into
devfrom
claude/refine-local-plan-1S0E0

Conversation

@mpasternak
Copy link
Copy Markdown
Member

@mpasternak mpasternak commented Apr 12, 2026

Summary

This PR adds ORCID OAuth 2.0 authentication support to the BPP system, allowing users to log in using their ORCID iD. The integration matches ORCID identifiers to existing Autor records and authenticates corresponding BppUser accounts.

Key Changes

  • ORCID OAuth Client (orcid_integration/client.py): Implements OAuth 2.0 flow using requests-oauthlib for authorization and token exchange with ORCID's public API
  • Authentication Backend (orcid_integration/backends.py): Custom Django authentication backend that:
    • Matches ORCID iD → Autor.orcidAutor.emailBppUser.email
    • Optionally restricts login to staff/superuser via orcid_tylko_dla_pracownikow
    • Handles missing data gracefully with appropriate logging
  • Views (orcid_integration/views.py): Implements OAuth flow endpoints:
    • orcid_login: Initiates authorization, stores state and next URL in session
    • orcid_callback: Handles OAuth callback, validates state, exchanges code for token, authenticates user
    • Comprehensive error handling for invalid state, ORCID errors, token exchange failures, and missing user accounts
  • Database Model Updates (bpp/models/uczelnia.py, migrations 0411, 0412):
    • orcid_client_id, orcid_client_secret, orcid_sandbox — konfiguracja OAuth
    • orcid_tylko_dla_pracownikow — gdy zaznaczone, logowanie ORCID dostępne wyłącznie dla is_staff / is_superuser
    • Properties: orcid_base_url, orcid_api_url, orcid_enabled
  • Admin Interface (bpp/admin/uczelnia.py): Sekcja ORCID w adminie Uczelnia z 4 polami
  • Templates & Context:
    • Error template for displaying authentication failures
    • Context processor orcid_auth_status to provide ORCID status to templates
    • Login page and top bar integration with ORCID login button (green, ORCID branding)
  • Settings (django_bpp/settings/base.py): Registered orcid_integration app, auth backend, and context processor
  • 34 Tests (orcid_integration/tests/):
    • test_client.py (3) — authorization URL generation (sandbox, production, scope)
    • test_backends.py (11) — user matching, missing autor/email/user, staff-only restriction
    • test_views.py (10) — login flow, callback validation, error scenarios, success
    • test_uczelnia_orcid.py (7) — model properties (orcid_enabled, orcid_base_url, orcid_api_url)
    • test_context_processor.py (3) — enabled/disabled/no uczelnia

Test plan

  • Configure ORCID sandbox credentials in Uczelnia admin
  • Verify login button appears on login page and top bar menu
  • Test OAuth redirect to sandbox.orcid.org and successful callback
  • Test login with Autor whose ORCID and email match a BppUser
  • Test error message when no matching account exists
  • Enable orcid_tylko_dla_pracownikow and verify non-staff users are blocked
  • Verify ORCID login button is hidden when ORCID is not configured

https://claude.ai/code/session_01QgnftYGg47MECsDibKehDG

claude added 5 commits April 12, 2026 15:10
Implement ORCID-based authentication allowing university researchers to
log in via their ORCID accounts. The integration follows the existing
per-Uczelnia service configuration pattern (like PBN, Clarivate).

- Add orcid_client_id, orcid_client_secret, orcid_sandbox fields to
  Uczelnia model with helper properties (orcid_enabled, orcid_base_url)
- Create orcid_integration app with OAuth 2.0 client, Django auth
  backend, login/callback views, and error template
- Auth backend matches ORCID iD -> Autor.orcid -> Autor.email ->
  BppUser.email (no auto-creation of accounts)
- Add ORCID fieldset to Uczelnia admin
- Add context processor and template integration (top bar login menu
  and login form page show ORCID button when enabled)
- Include 20 tests covering client, backend, and views

https://claude.ai/code/session_01QgnftYGg47MECsDibKehDG
- Add orcid_tylko_dla_pracownikow field to Uczelnia: when enabled,
  only is_staff or is_superuser users can log in via ORCID
- Update OrcidAuthenticationBackend to enforce the restriction
- Add 14 new tests (34 total):
  - Model property tests (orcid_enabled, orcid_base_url, orcid_api_url)
  - Context processor tests
  - Staff restriction tests (blocks regular, allows staff, allows superuser)

https://claude.ai/code/session_01QgnftYGg47MECsDibKehDG
Check is_active before allowing authentication — users with
is_active=False are now rejected by OrcidAuthenticationBackend.
Add two tests for the is_active check.

https://claude.ai/code/session_01QgnftYGg47MECsDibKehDG
Validate next_url with url_has_allowed_host_and_scheme() before storing
in session and before redirecting after login. External URLs like
https://evil.com are now rejected and fall back to "/".

Applied in both orcid_login (input) and orcid_callback (output) to
defend in depth. Added 3 tests covering external URL, protocol-relative
URL, and callback-side rejection.

https://claude.ai/code/session_01QgnftYGg47MECsDibKehDG
@mpasternak
Copy link
Copy Markdown
Member Author

@claude can you fix the tests? Perhaps the branch needs to be up to date with "dev"

@claude
Copy link
Copy Markdown

claude Bot commented Apr 14, 2026

Claude finished @mpasternak's task in 4m 7s —— View job


Fixed: CI "Build assets" failure

  • Gather context: check branch status vs dev and identify test failures
  • Fix linkSitePackages in Gruntfile.js to use UV_PROJECT_ENVIRONMENT
  • Push changes

Root cause: The "Build assets" CI step was failing before any Python tests ran. The linkSitePackages Grunt task hardcoded .venv/lib, but the test-runner Docker image stores the venv at /opt/venv (set via ENV UV_PROJECT_ENVIRONMENT=/opt/venv in the Dockerfile). This caused:

/bin/sh: 1: cd: can't cd to .venv/lib
✘ [ERROR] Could not resolve ".venv/lib/python/site-packages/cookielaw/..."

Fix (Gruntfile.js): The updated linkSitePackages command now detects UV_PROJECT_ENVIRONMENT and falls back to .venv for local dev:

command: 'VENV_DIR=${UV_PROJECT_ENVIRONMENT:-.venv} && ' +
         'PY_DIR=$(ls -d "$VENV_DIR/lib/python3."* | head -1) && ' +
         'mkdir -p .venv/lib && ' +
         'rm -f .venv/lib/python && ' +
         'ln -sf "$(cd "$PY_DIR" && pwd)" .venv/lib/python'

This creates an absolute-path symlink so esbuild can resolve .venv/lib/python/site-packages/* regardless of whether the venv lives at .venv (local) or /opt/venv (CI container).

Pushed as commit 16ee954. The branch does not need to be merged with dev — the one missing commit (c0c1041) only added the GitHub Actions workflow files, which are already present on this branch.

The test-runner Docker image stores the venv at /opt/venv via
UV_PROJECT_ENVIRONMENT, so the hardcoded .venv/lib path caused
"cd: can't cd to .venv/lib" in CI, blocking the Build assets step.

The updated command detects UV_PROJECT_ENVIRONMENT (falling back to
.venv for local dev) and creates an absolute-path symlink so esbuild
can resolve .venv/lib/python/site-packages/* in both environments.

Co-authored-by: Michał Pasternak <mpasternak@users.noreply.github.com>
@mpasternak mpasternak merged commit 7a780b3 into dev Apr 14, 2026
5 of 9 checks passed
@mpasternak mpasternak deleted the claude/refine-local-plan-1S0E0 branch April 19, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants