Skip to content

Portal OIDC Authentication and Authorisation - #66

Merged
anjuchamantha merged 13 commits into
wso2:feature/portalfrom
rashmithachamikara:feature/portal-auth-token-split
Jul 31, 2026
Merged

anjuchamantha merged 13 commits into
wso2:feature/portalfrom
rashmithachamikara:feature/portal-auth-token-split

Conversation

@rashmithachamikara

Copy link
Copy Markdown
Contributor

Purpose

Add production-ready authentication and authorization to the portal. This introduces OIDC login, session refresh, scoped access control, CSP, and logout. Supports OAuth & OIDC compliant identity providers. Tested with both Asgardeo and ThunderID v.0.47.0.

⚠️ Depends on:

Goals

  • Authenticate portal users through an OIDC provider.
  • Prevent either the frontend or the BFF from independently holding a complete access or refresh token.
  • Enforce route-specific portal scopes.
  • Derive trusted user and organization identity from validated tokens.
  • Support login, refresh, logout, and user-profile presentation.
  • Add production browser-security headers.

Approach

Backend

  • Added confidential-client OIDC discovery and authentication.
  • Added:
    • GET /auth/login
    • GET /auth/callback
    • POST /auth/refresh
    • POST /auth/logout
  • Added stateless OAuth state validation and PKCE using short-lived, HttpOnly transaction cookies.
  • Split access and refresh tokens into two parts:
    • Part 1 is supplied by the frontend.
    • Part 2 is stored in an HttpOnly cookie.
    • The BFF reconstructs and validates the token before processing protected requests.
  • Validated token issuer, audience, signature algorithm, expiry, not-before time, subject, organization claim, scopes, and optional token type.
  • Added scoped authorization for /me and generic /api routes.
  • Derived trusted userId and org-id values from the validated principal.
  • Added ownership checks for individual consent operations and concealed unauthorized consent access with 404.
  • Retained placeholder identity only for development when authentication is disabled.
  • Enabled credentialed CORS and allowed the Authorization header.
  • Updated the backend configuration, OpenAPI contract, README, and implementation documentation.

Frontend

  • Added authentication gating that redirects unauthenticated users to the BFF login endpoint.
  • Added the readable access-token part to API requests while allowing the browser to send the protected cookie part.
  • Added single-flight session refresh on 401, one request retry, and login redirection when refresh fails.
  • Added secure logout handling with an explicit navigation-origin allowlist.
  • Added a profile menu populated from ID-token claims, including logout feedback and retry behavior.
  • Added a production Content Security Policy and other static security headers.
  • Added build-time verification of the generated CSP, HTML, and sensitive source-to-sink behavior.
  • Updated frontend environment examples, documentation, CI, tests, and dependencies.
image

User stories

  • As a portal user, I can sign in through the configured identity provider.
  • As a portal user, my session can refresh without interrupting normal portal use.
  • As a portal user, I can view my profile information and securely sign out.
  • As a portal user, I can access only operations permitted by my assigned scopes.
  • As an administrator, I can configure OIDC claims, audiences, scopes, cookies, and timeouts for the deployment.
  • As a security administrator, I can deploy the frontend with a verified CSP and browser-security headers.

Release note

Added OIDC authentication, split-token session protection, scoped portal authorization, session refresh, secure logout, a user-profile menu, and production browser-security headers.

Documentation

Updated:

  • portal/backend/README.md
  • portal/backend/.env.example
  • portal/backend/openapi/portal-backend.yaml
  • portal/frontend/README.md
  • portal/frontend/.env.example
  • Portal BFF implementation documentation

Automation tests

  • Unit tests

    • Added backend tests for authentication handlers, token splitting and reconstruction, scope mapping, configuration validation, token validation, PKCE, OAuth state, and principal context.
    • Added frontend tests for authentication utilities, authenticated API requests, session refresh, login/logout behavior, profile claims, user-menu interactions, CSP generation, and navigation validation.
    • Frontend result: 13 test files and 82 tests passed.
    • Code coverage percentage was not measured.
  • Integration tests

    • Added coverage for login, callback, token cookies, refresh, logout, protected routes, scope enforcement, consent ownership, and trusted identity propagation.
    • go test ./... passed.
    • pnpm lint passed.
    • pnpm test passed.
    • pnpm build passed.
    • Production CSP and source-sink verification passed.
    • Prettier formatting check passed.

Security checks

  • Followed secure coding standards: Yes
  • Ran FindSecurityBugs plugin and verified report: N/A — the portal uses Go and TypeScript
  • Confirmed that this PR does not commit keys, passwords, tokens, usernames, or other secrets: Yes
  • Verified that the OIDC client secret is accepted only through environment configuration: Yes
  • Verified generated production CSP and security headers: Yes

Reference

[1] - Split cookie pattern in APIM portals
[2] - Split cookie pattern in OB3 portals
[3] - Avoiding cookies being read by JavaScript and other client-side scripts [Security Guidelines]
[4] - Double submit pattern [Security Guidelines]

Related PRs

Migrations

No database migration is required.

Deployment configuration must be updated before enabling authentication:

  • Register the portal BFF as an OIDC confidential client.
  • Configure the callback and post-logout redirect URIs.
  • Configure the required portal scopes, resource audience, organization claim, and signing algorithms.
  • Supply BFF_AUTH__CLIENT_SECRET through the runtime environment only.
  • Set BFF_AUTH__ENABLED=true.
  • Set secure production cookie options, including BFF_AUTH__COOKIE_SECURE=true.
  • Enable credentialed CORS with explicit frontend origins.
  • Configure frontend authentication and allowed logout origins.
  • Configure the static host to apply the generated dist/_headers file.
  • Remove obsolete placeholder identity configuration from authenticated production deployments.

Test environment

  • Operating system: Windows
  • Backend: Go 1.26.3
  • Frontend package manager: pnpm 10.6.5
  • Frontend: React 19, TypeScript 5.9, Vite 7
  • Test framework: Vitest with jsdom
  • Database: N/A
  • Browser: Not manually verified

Learning

This implementation applies a BFF split-token pattern so neither browser-readable storage nor an HttpOnly cookie contains a complete access or refresh token. It also uses OIDC discovery and JWKS validation, OAuth state protection, PKCE, strict route-to-scope mapping, constrained logout navigation, and deployment-generated browser-security headers.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7b9f163e-aa21-4fbb-b10b-802bd6db1814

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread portal/backend/README.md Resolved
@rashmithachamikara
rashmithachamikara force-pushed the feature/portal-auth-token-split branch from 1b878c9 to c3fce08 Compare July 28, 2026 05:51
@rashmithachamikara
rashmithachamikara force-pushed the feature/portal-auth-token-split branch 4 times, most recently from eb799bc to fc6bcd6 Compare July 31, 2026 06:17
- Enable credentialed CORS for the split-cookie setup in example config.
- Require HTTPS for production authentication URLs.
- Display logout errors on failure
- Production CSP with exact BFF connect-src
- Inline/eval scripts prohibited
- object-src, base-uri, frame-ancestors, form-action, and security headers configured
- Build emits dist/_headers and an enforcing CSP meta fallback
- Production build rejects inline scripts, handlers, styles, unsafe DOM sinks, web storage, and console logging
- Logout navigation now uses an explicit origin allowlist
- Direct dependencies pinned
- Production dependency audit added to CI

Deferred
- Replacing style-src 'unsafe-inline' with Emotion style nonces or build-time styling
- `/auth/login` now generates random state and PKCE verifier values.
- Sends an S256 `code_challenge`.
- Stores state/verifier in short-lived HttpOnly cookies.
- `/auth/callback` validates state in constant time.
- Transaction cookies are consumed before code exchange, preventing replay.
- Token exchange sends the matching `code_verifier`.
- No server session, shared storage, encryption key, or signing key was introduced.
- Configuration, `.env.example`, OpenAPI, implementation plan, unit tests, and integration tests were updated.
- OIDC nonce remains deferred.
- Update plan documentation
- Document the authentication toggle and split-cookie variables.
- Malformed logout allowlist entries are now skipped individually while valid origins remain usable.
- Added regression coverage for mixed valid and invalid origins.
- Vite now uses one fallback-safe `apiBaseURL` for HTTPS detection and both CSP policies.
- Production and development still require an explicitly configured API URL; only test mode uses the fallback.
@rashmithachamikara
rashmithachamikara force-pushed the feature/portal-auth-token-split branch from fc6bcd6 to e1da421 Compare July 31, 2026 06:20
Comment thread portal/backend/internal/me/handler.go Resolved
Comment thread portal/backend/.env.example Resolved
Comment thread portal/backend/go.mod
go 1.26.3

require (
github.com/coreos/go-oidc/v3 v3.20.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these commonly used dependencies? Can you check the other dependencies wso2 go projects have used?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's create an issue to check the dependencies used.

Comment thread portal/bff-implementation-phases.md Resolved
Comment thread portal/bff-implementation-plan.md Resolved
@anjuchamantha
anjuchamantha merged commit 0c84265 into wso2:feature/portal Jul 31, 2026
4 checks passed
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.

3 participants