Skip to content

Spring Boot Controllers Guide ​

πŸ“š Overview ​

The Open Agent Auth Spring Boot Starter provides pre-built REST controllers that expose the framework layer interfaces as HTTP endpoints. These controllers handle HTTP request/response processing, error handling, and session management, delegating business logic to the framework layer actors and executors.

🎯 Design Philosophy ​

The controllers follow the Facade Pattern, providing a clean HTTP layer while keeping authorization logic separate in the framework layer. This allows developers to:

  • Use REST APIs without understanding the complex protocol details
  • Integrate with web applications easily
  • Customize controllers by providing their own implementations
  • Leverage Spring Boot auto-configuration

πŸ—οΈ Controller Architecture ​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Spring Boot Controllers Layer                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ UserLoginController β”‚  β”‚ OAuth2Callback   β”‚  β”‚ WorkloadControllerβ”‚ β”‚
β”‚  β”‚   (IDP Role)        β”‚  β”‚   Controller     β”‚  β”‚  (Agent IDP)      β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  β”‚OAuth2Authorization β”‚  β”‚ OAuth2Dcr        β”‚  β”‚ OAuth2Par    β”‚       β”‚
β”‚  β”‚   Controller       β”‚  β”‚   Controller     β”‚  β”‚   Controller β”‚       β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ JwksController   β”‚  β”‚ PolicyRegistry   β”‚  β”‚ Discovery     β”‚        β”‚
β”‚  β”‚   (JWKS Endpoint)β”‚  β”‚   Controller     β”‚  β”‚   Controller  β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                                                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓ Delegates to ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Framework Layer (Actors & Executors)                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“– Controller Reference ​

1. UserLoginController ​

Role: User Identity Provider (IDP)
Enabled For: agent-user-idp, as-user-idp

Handles user authentication and login/logout functionality.

Endpoints ​

MethodPathDescription
GET/loginLogin page
POST/loginHandle login form submission
GET/oauth2/logoutLogout endpoint
GET/Home page

Usage Example ​

java
// Redirect to login page
@GetMapping("/secure")
public String securePage() {
    return "redirect:/login";
}

// After successful login, user is redirected to authorization endpoint

Configuration ​

yaml
open-agent-auth:
    role: agent-user-idp  # or as-user-idp
    login:
      enabled: true

2. OAuth2CallbackController ​

Role: Agent, Authorization Server
Enabled For: agent, authorization-server

Handles OAuth2 callback requests from the authorization server.

Endpoints ​

MethodPathDescription
GET/callbackOAuth2 callback endpoint

Usage Example ​

java
// The callback endpoint is automatically configured
// Redirect URL: https://your-app.com/callback?code=xxx&state=yyy

// The controller handles:
// 1. Validating state parameter
// 2. Exchanging authorization code for tokens
// 3. Redirecting to success/error page

Configuration ​

yaml
open-agent-auth:
  capabilities:
    oauth2-client:
      enabled: true
      client-id: your-client-id
      client-secret: your-client-secret
      callback:
        enabled: true
        endpoint: /callback

3. WorkloadController ​

Role: Agent Identity Provider (Agent IDP)
Enabled For: agent-idp

Manages agent workload identities and WIT issuance.

Endpoints ​

MethodPathDescription
POST/api/v1/workloads/createCreate agent workload
POST/api/v1/workloads/issueIssue WIT for existing workload
POST/api/v1/workloads/token/issueIssue WIT with automatic workload management
POST/api/v1/workloads/revokeRevoke workload identity
POST/api/v1/workloads/getRetrieve workload information

Usage Example ​

java
// Create workload
POST /api/v1/workloads/create
Content-Type: application/json

{
  "idToken": "eyJhbGciOiJSUzI1NiIs...",
  "context": {
    "operationType": "query",
    "resourceId": "product-catalog",
    "metadata": {
      "category": "clothing"
    }
  }
}

// Response
{
  "workloadId": "workload-123",
  "userId": "user-456",
  "publicKey": "-----BEGIN PUBLIC KEY-----...",
  "createdAt": "2026-02-08T10:00:00Z",
  "expiresAt": "2026-02-08T11:00:00Z",
  "status": "active"
}

// Issue WIT
POST /api/v1/workloads/token/issue
Content-Type: application/json

{
  "agent_user_binding_proposal": {
    "user_identity_token": "eyJhbGciOiJSUzI1NiIs..."
  },
  "context": {
    "agent": {
      "client": "sample-agent"
    }
  },
  "publicKey": "-----BEGIN PUBLIC KEY-----..."
}

// Response
{
  "wit": "eyJhbGciOiJSUzI1NiIs..."
}

Configuration ​

yaml
open-agent-auth:
    role: agent-idp
    services:
      provider:
        endpoints:
          workload:
            create: /api/v1/workloads/create
            issue: /api/v1/workloads/issue
            token-issue: /api/v1/workloads/token/issue
            revoke: /api/v1/workloads/revoke
            get: /api/v1/workloads/get

4. OAuth2AuthorizationController ​

Role: Authorization Server, IDP
Enabled For: authorization-server, agent-user-idp, as-user-idp

Handles OAuth 2.0 authorization endpoint.

Endpoints ​

MethodPathDescription
GET/oauth2/authorizeAuthorization endpoint
POST/oauth2/authorizeConsent submission endpoint

Usage Example ​

java
// Redirect to authorization endpoint
// URL: https://your-auth-server.com/oauth2/authorize?request_uri=urn:ietf:params:oauth:request_uri:xxx&state=yyy

// The controller handles:
// 1. PAR request validation
// 2. User authentication (via UserLoginController)
// 3. Consent display
// 4. Token issuance
// 5. Redirect to callback URL

Configuration ​

yaml
open-agent-auth:
    role: authorization-server
    services:
      provider:
        endpoints:
          oauth2:
            authorize: /oauth2/authorize

5. JwksController ​

Role: All Roles
Enabled For: All roles (when open-agent-auth.enabled=true)

Provides JWKS endpoint for public key discovery.

Endpoints ​

MethodPathDescription
GET/.well-known/jwks.jsonJWKS endpoint

Usage Example ​

bash
# Get JWKS
curl https://your-idp.com/.well-known/jwks.json

# Response
{
  "keys": [
    {
      "kty": "RSA",
      "kid": "key-1",
      "use": "sig",
      "alg": "RS256",
      "n": "...",
      "e": "AQAB"
    }
  ]
}

Configuration ​

yaml
open-agent-auth:
    enabled: true
    jwks:
      provider:
        path: /.well-known/jwks.json
        cache-ttl-seconds: 3600

6. OAuth2DcrController ​

Role: Authorization Server
Enabled For: authorization-server

Handles Dynamic Client Registration (DCR).

Endpoints ​

MethodPathDescription
POST/oauth2/registerOAuth client registration

Usage Example ​

java
// Register OAuth client
POST /oauth2/register
Content-Type: application/json

{
  "client_assertion": "eyJhbGciOiJSUzI1NiIs...",
  "redirect_uris": [
    "https://client.example.com/callback"
  ],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "private_key_jwt"
}

// Response
{
  "client_id": "client-123",
  "client_id_issued_at": 1704729600,
  "registration_access_token": "...",
  "registration_client_uri": "https://auth-server.com/oauth2/register/client-123"
}

7. OAuth2ParController ​

Role: Agent, Authorization Server
Enabled For: agent, authorization-server

Handles Pushed Authorization Request (PAR).

Endpoints ​

MethodPathDescription
POST/oauth2/parPAR submission endpoint

Usage Example ​

java
// Submit PAR request
POST /oauth2/par
Content-Type: application/json

{
  "client_assertion": "eyJhbGciOiJSUzI1NiIs...",
  "request": "eyJhbGciOiJSUzI1NiIs..."  // PAR-JWT
}

// Response
{
  "request_uri": "urn:ietf:params:oauth:request_uri:abc123",
  "expires_in": 600
}

8. OAuth2TokenController ​

Role: Authorization Server
Enabled For: authorization-server

Handles token issuance.

Endpoints ​

MethodPathDescription
POST/oauth2/tokenToken endpoint

Usage Example ​

java
// Exchange authorization code for tokens
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=xxx&redirect_uri=https://client.example.com/callback

// Response
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "id_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600
}

9. PolicyRegistryController ​

Role: Authorization Server
Enabled For: authorization-server

Manages OPA policy registration.

Endpoints ​

MethodPathDescription
POST/api/v1/policies/registerRegister policy
GET/api/v1/policies/getRetrieve policy
DELETE/api/v1/policies/deleteDelete policy

Usage Example ​

java
// Register policy
POST /api/v1/policies
Content-Type: application/json

{
  "policyId": "shopping-policy",
  "rego": "package auth\nallow { input.user == input.resource.owner }"
}

// Response
{
  "policyId": "shopping-policy",
  "status": "registered"
}

10. DiscoveryController ​

Role: Authorization Server, IDP
Enabled For: authorization-server, agent-user-idp, as-user-idp

Provides OpenID Connect Discovery endpoint.

Endpoints ​

MethodPathDescription
GET/.well-known/openid-configurationDiscovery endpoint

Usage Example ​

bash
# Get discovery document
curl https://your-idp.com/.well-known/openid-configuration

# Response
{
  "issuer": "https://your-idp.com",
  "authorization_endpoint": "https://your-idp.com/oauth2/authorize",
  "token_endpoint": "https://your-idp.com/oauth2/token",
  "jwks_uri": "https://your-idp.com/.well-known/jwks.json",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code"],
  "subject_types_supported": ["public"]
}

11. OAuth2ConsentController ​

Role: Authorization Server
Enabled For: authorization-server

Handles consent page display and submission.

Endpoints ​

MethodPathDescription
GET/oauth2/consentConsent page
POST/oauth2/consentConsent submission

12. OidcUserInfoController ​

Role: Authorization Server, IDP
Enabled For: authorization-server, agent-user-idp, as-user-idp

Provides OIDC UserInfo endpoint.

Endpoints ​

MethodPathDescription
GET/oauth2/userinfoUserInfo endpoint

Usage Example ​

bash
# Get user info
curl -H "Authorization: Bearer xxx" https://your-idp.com/oauth2/userinfo

# Response
{
  "sub": "user-123",
  "name": "John Doe",
  "email": "john@example.com",
  "preferred_username": "johndoe"
}

13. BindingInstanceController ​

Role: Agent IDP
Enabled For: agent-idp

Manages binding instances for agent-user binding.

Endpoints ​

MethodPathDescription
POST/api/v1/bindings/registerCreate binding instance
GET/api/v1/bindings/getRetrieve binding instance
DELETE/api/v1/bindings/deleteDelete binding instance

πŸš€ Quick Start ​

1. Add Dependency ​

xml
<dependency>
    <groupId>com.alibaba.openagentauth</groupId>
    <artifactId>open-agent-auth-spring-boot-starter</artifactId>
    <version>0.1.0-beta.1-SNAPSHOT</version>
</dependency>

Note: The Open Agent Auth artifacts are not yet published to Maven Central. For now, you need to build the project locally and install it to your local Maven repository:

bash
git clone https://github.com/alibaba/open-agent-auth.git
cd open-agent-auth
mvn clean install -DskipTests

2. Configure Application ​

yaml
open-agent-auth:
  enabled: true
  capabilities:
    oauth2-client:
      enabled: true
      client-id: your-client-id
      client-secret: your-client-secret
      redirect-uri: https://your-app.com/callback
      callback:
        enabled: true
  roles:
    agent:
      enabled: true
      issuer: https://your-app.com

3. Use Controllers ​

java
@RestController
@RequestMapping("/api")
public class MyController {
    
    @Autowired
    private AgentAapExecutor executor;
    
    @PostMapping("/authorize")
    public ResponseEntity<?> authorize(
            @RequestParam String userId,
            @RequestParam String userOriginalInput) {
        
        // Use executor or call controller endpoints directly
        RequestAuthUrlRequest request = RequestAuthUrlRequest.builder()
            .userIdentityToken(idToken)
            .userOriginalInput(userOriginalInput)
            .workloadContext(workloadContext)
            .sessionId(sessionId)
            .build();
        
        RequestAuthUrlResponse response = executor.requestAuthUrl(request);
        
        return ResponseEntity.ok(Map.of(
            "authorizationUrl", response.getAuthorizationUrl(),
            "state", response.getState()
        ));
    }
}

πŸ”§ Configuration ​

Controller-Specific Configuration ​

yaml
open-agent-auth:
  capabilities:
    oauth2-client:
      enabled: true
      client-id: your-client-id
      client-secret: your-client-secret
      callback:
        enabled: true
  roles:
    agent:
      enabled: true

🎨 Customization ​

Override Controller ​

java
@Controller
public class CustomUserLoginController {
    
    @GetMapping("/custom-login")
    public String customLoginPage(Model model) {
        // Custom login page logic
        return "custom-login";
    }
    
    @PostMapping("/custom-login")
    public RedirectView customLogin(
            @RequestParam String username,
            @RequestParam String password) {
        // Custom authentication logic
        return new RedirectView("/home");
    }
}

Customize Login Page ​

Create templates/login.html in your application:

html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
    <h1>Login</h1>
    <form method="post" th:action="@{/login}">
        <input type="hidden" name="redirect_uri" th:value="${redirect_uri}" />
        <div>
            <label>Username:</label>
            <input type="text" name="username" required />
        </div>
        <div>
            <label>Password:</label>
            <input type="password" name="password" required />
        </div>
        <div>
            <button type="submit">Login</button>
        </div>
        <div th:if="${error}" th:text="${error}" style="color: red;"></div>
    </form>
</body>
</html>

πŸ“š Best Practices ​

1. Use HTTPS for All Endpoints ​

yaml
server:
  ssl:
    enabled: true
    key-store: classpath:keystore.p12
    key-store-password: changeit
    key-store-type: PKCS12

2. Configure CORS for Cross-Origin Requests ​

java
@Configuration
public class CorsConfig {
    
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://your-frontend.com"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

3. Implement Rate Limiting ​

java
@Configuration
public class RateLimitConfig {
    
    @Bean
    public FilterRegistrationBean<RateLimitFilter> rateLimitFilter() {
        FilterRegistrationBean<RateLimitFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new RateLimitFilter());
        registration.addUrlPatterns("/oauth2/*", "/api/v1/*");
        return registration;
    }
}

4. Log Security Events ​

java
@Aspect
@Component
public class SecurityLoggingAspect {
    
    private static final Logger logger = LoggerFactory.getLogger(SecurityLoggingAspect.class);
    
    @Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public Object logSecurityEvent(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        
        logger.info("Security event: method={}, path={}, ip={}", 
                    request.getMethod(), 
                    request.getRequestURI(), 
                    request.getRemoteAddr());
        
        return joinPoint.proceed();
    }
}


Version: 0.1.0-beta.1-SNAPSHOT
Last Updated: 2026-02-08

Released under the Apache 2.0 License.