Bella OpenAPI OAuth 2.0 and CAS Integration: Complete SSO Implementation Guide

Bella OpenAPI activates OAuth 2.0 or CAS single sign-on through conditional Spring Boot filters that validate tickets, map user attributes to an Operator object, and persist sessions via a pluggable SessionManager.

Bella OpenAPI (lianjiatech/bella-openapi) provides enterprise-grade single sign-on by implementing two distinct authentication protocols as configurable Spring Boot modules. Whether you need social login via OAuth 2.0 providers like Google and GitHub or enterprise CAS server integration, the system uses servlet filters and conditional bean registration to handle the complete authentication lifecycle without code changes. Both mechanisms share a common session architecture that stores the authenticated Operator in Redis or HTTP sessions.

OAuth 2.0 Implementation Architecture

The OAuth 2.0 stack activates automatically when you set bella.login.type=oauth and define bella.login.login-page-url in your configuration. This triggers the @ConditionalOnOAuthEnable annotation, which registers the OAuthLoginFilter through BellaLoginConfiguration.oauthLoginFilter (lines 71-81).

Activation and Configuration

The OAuthProperties bean holds provider-specific credentials and redirect URIs. When the application context loads, BellaLoginConfiguration instantiates the OAuthLoginFilter and assigns it high precedence in the servlet filter chain.

bella:
  login:
    type: oauth
    login-page-url: /login
  oauth:
    providers:
      google:
        client-id: YOUR_GOOGLE_ID
        client-secret: YOUR_GOOGLE_SECRET
        redirect-uri: https://myapp.com/openapi/oauth/callback/google

Authentication Flow

The implementation follows a standard authorization code flow with CSRF protection:

  1. Discovery endpoint: Clients call /openapi/oauth/config?redirect=.... The OAuthLoginFilter.handleOAuthConfig method (lines 68-84) returns a JSON array containing the authorization URL for each enabled provider.
  2. State generation: The TicketManager generates a secure ticket stored in the state parameter to prevent CSRF attacks.
  3. Provider redirect: The user agent navigates to the provider's authorization endpoint.
  4. Callback handling: Upon return to /openapi/oauth/callback/{provider}, OAuthLoginFilter.handleCallback (lines 92-128) validates the state ticket, exchanges the code for an access token via the concrete OAuthService implementation, and fetches user information.
  5. Session creation: The filter creates an Operator instance and calls sessionManager.create(operator, request, response) to persist the authentication.

Core OAuth Components

  • OAuthLoginFilter: Orchestrates the config endpoint, callback processing, and ticket validation.
  • OAuthService interface: Defines the contract for provider-specific logic including URL construction and user info retrieval.
  • GoogleOAuthService / GithubOAuthService: Concrete implementations that format provider requests and parse responses.
  • ConditionalOnOAuthEnable: Spring condition that activates the OAuth bean stack only when required properties are present.

CAS (Central Authentication Service) Integration

Bella OpenAPI implements enterprise CAS integration through a three-filter chain that handles redirection, ticket validation, and post-login forwarding. Activation requires bella.login.type=cas and bella.cas.server-url-prefix.

Filter Chain Configuration

When @ConditionalOnCasEnable matches, BellaLoginConfiguration (lines 47-69) creates three filters via BellaCasClient:

  • BellaCasLoginFilter: Detects unauthenticated console requests and redirects to the CAS server.
  • BellaValidatorFilter: Extends Cas30ProxyReceivingTicketValidationFilter to validate service tickets and extract user attributes.
  • BellaRedirectFilter: Handles the final redirect to the originally requested resource.

Login and Validation Flow

The CAS flow begins when a request includes the X-Console-Login header:

  1. Redirect generation: BellaCasLoginFilter.doFilter (lines 64-79) constructs a service URL pointing back to the application and redirects the browser to CasProperties.serverLoginUrl.
  2. Ticket validation: After authentication at the CAS server, the user returns with a ticket parameter. BellaValidatorFilter validates this against the CAS server and maps attributes (ucid, displayName, email) to an Operator in onSuccessfulValidation (lines 37-55).
  3. Attribute mapping: The filter reads attribute names from CasProperties (id-attribute, name-attribute, email-attribute) to populate the Operator.
  4. Post-login routing: If the original request contained a redirect parameter, BellaValidatorFilter stores it for BellaRedirectFilter to complete the navigation (lines 56-58).
bella:
  login:
    type: cas
  cas:
    server-url-prefix: https://cas.mycompany.com/cas
    server-login-url: https://cas.mycompany.com/cas/login
    client-host: https://myapp.com
    id-attribute: ucid
    name-attribute: displayName
    email-attribute: email

Key CAS Components

  • BellaCasLoginFilter: Initiates the CAS protocol by building the service URL and redirecting unauthenticated users.
  • BellaValidatorFilter: Bridges the CAS client library with Bella's SessionManager by converting successful validations into persisted sessions.
  • CasProperties: Type-safe configuration holder for server URLs and attribute mappings.
  • ConditionalOnCasEnable: Ensures CAS beans load only when explicitly configured.

Shared Session Management

Both OAuth and CAS implementations delegate session persistence to the SessionManager interface defined in BellaLoginConfiguration.sessionManager (lines 90-115). The system selects an implementation based on your deployment profile:

  • RedisSessionManager: Production-ready distributed session storage.
  • HttpSessionManager: Cookie-based sessions for single-node deployments.

After successful authentication, the Operator object remains available for the duration of the session. The generic LoginFilter intercepts all subsequent requests, retrieves the Operator from the session, and injects it as a request attribute for downstream controllers.

Practical Configuration Examples

Enabling Google and GitHub OAuth

Configure multiple providers simultaneously by listing them under bella.oauth.providers:

bella:
  login:
    type: oauth
    login-page-url: /login
  oauth:
    providers:
      google:
        client-id: ${GOOGLE_CLIENT_ID}
        client-secret: ${GOOGLE_CLIENT_SECRET}
        redirect-uri: https://api.example.com/openapi/oauth/callback/google
      github:
        client-id: ${GITHUB_CLIENT_ID}
        client-secret: ${GITHUB_CLIENT_SECRET}
        redirect-uri: https://api.example.com/openapi/oauth/callback/github

Frontend integration – Fetch available providers and redirect the user:

async function initiateLogin(returnUrl) {
  const response = await fetch(`/openapi/oauth/config?redirect=${encodeURIComponent(returnUrl)}`);
  const { data: providers } = await response.json();
  
  // providers = [{type: 'google', authUrl: 'https://accounts.google.com/...'}]
  const google = providers.find(p => p.type === 'google');
  if (google) window.location.href = google.authUrl;
}

Configuring Enterprise CAS

Trigger CAS authentication by including the special header when accessing protected console resources:

<script>
  fetch('/console', {
    headers: { 'X-Console-Login': 'true' },
    redirect: 'follow'
  }).then(response => {
    if (response.redirected) {
      window.location.href = response.url; // Redirects to CAS server
    }
  });
</script>

Accessing the Authenticated Operator

Retrieve the current user in your Spring controllers by casting the request attribute set by LoginFilter:

@RestController
@RequestMapping("/api/user")
public class UserController {

    @GetMapping("/profile")
    public Operator getProfile(HttpServletRequest request) {
        return (Operator) request.getAttribute("operator");
    }
}

Summary

  • OAuth 2.0 activates via @ConditionalOnOAuthEnable when bella.login.type=oauth is set, using OAuthLoginFilter to handle the authorization code flow and provider callbacks.
  • CAS activates via @ConditionalOnCasEnable when bella.login.type=cas is set, employing three specialized filters (BellaCasLoginFilter, BellaValidatorFilter, BellaRedirectFilter) to manage the ticket validation dance.
  • Both mechanisms store the resulting Operator object through the shared SessionManager interface, supporting both Redis-backed and HTTP session storage.
  • Configuration is purely property-driven, allowing you to switch between OAuth, CAS, or client-mode authentication without modifying source code or rebuilding the application.

Frequently Asked Questions

How do I switch between OAuth and CAS in Bella OpenAPI?

Change the value of bella.login.type to oauth or cas in your application.yml. Ensure you include the required companion properties (bella.login.login-page-url for OAuth, bella.cas.server-url-prefix for CAS) to satisfy the conditional activation annotations.

What triggers the CAS login flow in Bella OpenAPI?

The BellaCasLoginFilter specifically checks for the X-Console-Login: true header on incoming requests. When this header is present and the user lacks a valid session, the filter redirects the browser to the configured CAS server login URL.

How does Bella OpenAPI prevent CSRF attacks during OAuth authentication?

The OAuthLoginFilter generates a cryptographically secure ticket through the TicketManager and embeds it in the state parameter of the authorization URL. When the provider redirects back to /openapi/oauth/callback/{provider}, the filter validates that the returned state matches the stored ticket before processing the authorization code.

Where does Bella OpenAPI store authenticated user sessions?

Both OAuth and CAS implementations call sessionManager.create(operator, request, response) upon successful authentication. Depending on your configuration, this persists the Operator object to either Redis (via RedisSessionManager) or HTTP sessions (via HttpSessionManager). Subsequent requests retrieve this object via the generic LoginFilter and expose it as a request attribute named "operator".

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →