Skip to content

Conversation

rrayst
Copy link
Member

@rrayst rrayst commented Aug 7, 2025

Summary by CodeRabbit

  • New Features

    • Introduced support for OAuth2 B2C flows with customizable flow context, enabling dynamic token endpoint handling.
    • Added a configurable limit for HTTP body trace logging.
  • Bug Fixes

    • Improved refresh token tracking and validation for B2C OAuth2 flows in the mock authorization server.
    • Ensured proper URL encoding of parameters in OAuth2 redirects.
  • Tests

    • Enhanced and expanded test coverage for B2C OAuth2 flows, including new scenarios for refresh token usage and flow switching.

Copy link
Contributor

coderabbitai bot commented Aug 7, 2025

Walkthrough

This change introduces a FlowContext class to encapsulate flow-specific information in OAuth2 B2C scenarios, propagates it through the authorization and token request flows, and updates related method signatures and logic accordingly. The OAuth2 client, authorization service, and test infrastructure are modified to support and validate flow-aware token endpoint selection and refresh token handling.

Changes

Cohort / File(s) Change Summary
FlowContext Introduction & Propagation
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/FlowContext.java,
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/AuthorizationService.java,
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/FlowInitiator.java,
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/OAuth2Resource2Interceptor.java,
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/rf/OAuth2CallbackRequestHandler.java,
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/rf/StateManager.java
Introduces FlowContext to represent flow-specific state, updates method signatures and logic to pass and utilize FlowContext throughout OAuth2 flows, including redirect handling, state management, and token endpoint selection.
Mock Authorization Server & Test Enhancements
core/src/test/java/com/predic8/membrane/core/interceptor/oauth2/client/b2c/MockAuthorizationServer.java,
core/src/test/java/com/predic8/membrane/core/interceptor/oauth2/client/b2c/OAuth2ResourceB2CTest.java
Updates the mock server to track flow-specific refresh tokens and enforce correct flow validation, ensures URL encoding consistency, and expands tests to cover flow-specific refresh token handling and JWT audience validation.
HTTP Client Trace Body Configuration
core/src/main/java/com/predic8/membrane/core/transport/http/HttpClient.java
Adds a configurable maximum length for HTTP body tracing via a system property, replacing the previous hardcoded value.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant OAuth2Resource2Interceptor
    participant FlowInitiator
    participant StateManager
    participant AuthorizationService
    participant MockAuthorizationServer

    Client->>OAuth2Resource2Interceptor: Initiate OAuth2 flow
    OAuth2Resource2Interceptor->>FlowInitiator: handleRequestInternal()
    FlowInitiator->>AuthorizationService: respondWithRedirect(exc, FlowContext)
    AuthorizationService->>StateManager: buildStateParameter(..., FlowContext)
    StateManager-->>AuthorizationService: state parameter with FlowContext
    AuthorizationService-->>FlowInitiator: Redirect response with FlowContext in state
    FlowInitiator-->>Client: Redirect to Auth Server

    Client->>MockAuthorizationServer: Authorization request (with state)
    MockAuthorizationServer-->>Client: Redirect with code (flow-specific)

    Client->>OAuth2Resource2Interceptor: Callback with code & state
    OAuth2Resource2Interceptor->>StateManager: Parse state, extract FlowContext
    OAuth2Resource2Interceptor->>AuthorizationService: codeTokenRequest(..., FlowContext)
    AuthorizationService->>MockAuthorizationServer: Token request (flow-specific endpoint)
    MockAuthorizationServer-->>AuthorizationService: Token response (flow-specific)
    AuthorizationService-->>OAuth2Resource2Interceptor: Token & FlowContext
    OAuth2Resource2Interceptor-->>Client: Final response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

In the warren where flows now hop and play,
Context travels with each OAuth2 relay.
Tokens know their journey’s start and end,
Refresh secrets guarded, flows never bend.
With every hop, a context in tow—
B2C rabbits, ready, set, go!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch store-flow-via-oauth2-state-and-per-refresh-token

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@rrayst
Copy link
Member Author

rrayst commented Aug 7, 2025

/ok-to-test

@membrane-ci-server
Copy link

This pull request needs "/ok-to-test" from an authorized committer.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (4)
core/src/main/java/com/predic8/membrane/core/transport/http/HttpClient.java (1)

666-668: Consider whether the new default (10 KB) is still safe for production logs

The default limit has jumped from 1 KB to 10 KB.
While useful for debugging, logging larger bodies increases log volume and the risk of leaking sensitive data.
You may want to keep the previous default (1–2 KB) and rely on the system property for opt-in expansion.

core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/FlowContext.java (1)

71-74: Consider using a more robust URL encoding approach.

The manual URL encoding with hardcoded percent-encoded characters (%26fcd%3D) is fragile and could lead to double-encoding issues.

Consider using a builder pattern or proper URL parameter encoding:

-        return fc != null ? "%26fcd%3D" + urlencode(fc.defaultFlow) + "%26fct%3D" + urlencode(fc.triggerFlow) : "";
+        return fc != null ? "&fcd=" + urlencode(fc.defaultFlow) + "&fct=" + urlencode(fc.triggerFlow) : "";

Note: If the pre-encoded format is required for compatibility, add a comment explaining why.

core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/FlowInitiator.java (1)

124-126: Make the flow replacement pattern more specific.

The current regex pattern could inadvertently replace flow names in query parameters or other parts of the URL.

Consider using a more specific pattern that only matches path segments:

 private String replaceFlow(String text) {
-    return text.replaceAll("/" + defaultFlow + "/", "/" + triggerFlow + "/");
+    return text.replaceAll("/" + Pattern.quote(defaultFlow) + "/", "/" + triggerFlow + "/");
 }

Also add import: import java.util.regex.Pattern;

core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/AuthorizationService.java (1)

315-323: Consider adding null check for FlowContext parameter.

While the implementation correctly uses FlowContext, consider adding a null check or documenting whether null is an acceptable value, especially since getTokenEndpoint handles null FlowContext.

 public OAuth2TokenResponseBody codeTokenRequest(String redirectUri, String code, String verifier, FlowContext flowContext) throws Exception {
+    // flowContext can be null for non-B2C flows
     return parseTokenResponse(checkTokenResponse(doRequest(applyAuth(
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc4f060 and 1edd724.

📒 Files selected for processing (9)
  • core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/AuthorizationService.java (6 hunks)
  • core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/FlowContext.java (1 hunks)
  • core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/FlowInitiator.java (2 hunks)
  • core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/OAuth2Resource2Interceptor.java (3 hunks)
  • core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/rf/OAuth2CallbackRequestHandler.java (3 hunks)
  • core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/rf/StateManager.java (5 hunks)
  • core/src/main/java/com/predic8/membrane/core/transport/http/HttpClient.java (2 hunks)
  • core/src/test/java/com/predic8/membrane/core/interceptor/oauth2/client/b2c/MockAuthorizationServer.java (6 hunks)
  • core/src/test/java/com/predic8/membrane/core/interceptor/oauth2/client/b2c/OAuth2ResourceB2CTest.java (5 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/AuthorizationService.java (1)
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/FlowContext.java (1)
  • FlowContext (31-102)
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/FlowInitiator.java (1)
core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/FlowContext.java (1)
  • FlowContext (31-102)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Automated tests
  • GitHub Check: Analyze (java)
🔇 Additional comments (11)
core/src/main/java/com/predic8/membrane/core/transport/http/HttpClient.java (1)

52-53: Configurable trace-body length is a welcome addition

Replacing the hard-coded 1 KB limit with a configurable constant improves flexibility and debuggability.
No issues spotted in this declaration itself.

core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/rf/OAuth2CallbackRequestHandler.java (1)

32-32: LGTM! Flow context integration is correct.

The changes properly propagate the flow context from the OAuth2 state parameter through the token request and into the session, which aligns with the PR objectives to store B2C flow info in the OAuth2 state.

Also applies to: 107-107, 125-125

core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/OAuth2Resource2Interceptor.java (1)

142-142: LGTM! FlowContext parameter properly added to redirect handling.

The method signature change and subsequent usage correctly propagate the flow context through the OAuth2 redirect flow, ensuring the B2C flow information is included in the state parameter.

Also applies to: 169-169, 252-252, 260-260

core/src/test/java/com/predic8/membrane/core/interceptor/oauth2/client/b2c/MockAuthorizationServer.java (1)

49-49: LGTM! Test server correctly simulates flow-specific OAuth2 behavior.

The mock authorization server properly tracks refresh tokens per flow and validates them accordingly. The use of ConcurrentHashMap ensures thread safety for the refresh token storage.

Also applies to: 68-69, 143-146, 166-174, 200-204

core/src/test/java/com/predic8/membrane/core/interceptor/oauth2/client/b2c/OAuth2ResourceB2CTest.java (2)

528-534: Good security enhancement with audience validation.

Adding expected audience validation to the JWT consumer strengthens token security by ensuring tokens are only accepted by their intended recipients. This is particularly important in B2C scenarios with multiple flows.


336-362: Excellent test coverage for flow context edge cases.

This test effectively validates the critical scenario where users start but abort a new flow, ensuring the system correctly maintains flow context for refresh tokens. The assertions properly verify that tokens are issued from the expected flows.

core/src/main/java/com/predic8/membrane/core/interceptor/oauth2client/rf/StateManager.java (3)

48-60: Well-structured FlowContext integration.

The FlowContext field is properly integrated into both constructors, maintaining consistency between creation and deserialization paths. The delegation to FlowContext.fromUrlParam for deserialization maintains good separation of concerns.


68-75: Public visibility change is justified for code reuse.

Making getValueFromState public enables FlowContext to reuse this state parsing logic, which is appropriate. The method properly handles null checks and error cases.


122-125: FlowContext.toUrlParam correctly URL-encodes its values

Verified that FlowContext.toUrlParam(…) invokes OAuth2Util.urlencode, which uses URLEncoder.encode(..., UTF_8) (with “+” replaced by “%20”). Both defaultFlow and triggerFlow are fully percent-encoded, and the surrounding “%26”/“%3D” literals safely encode the ampersand and equals. No further changes needed.

core/src/main/java/com/predic8/membrane/core/interceptor/oauth2/authorizationservice/AuthorizationService.java (2)

231-242: Proper FlowContext propagation to client authentication.

The FlowContext is correctly passed through to createClientToken, ensuring JWT client assertions have the appropriate audience for the specific B2C flow.


304-313: Correct flow context handling in refresh token requests.

The implementation properly extracts FlowContext from the session and uses it consistently for both the token endpoint URL and authentication, maintaining flow context through token refreshes.

@rrayst rrayst requested a review from t-burch August 7, 2025 14:23
@t-burch t-burch merged commit fb1a506 into master Aug 7, 2025
4 of 5 checks passed
@t-burch t-burch deleted the store-flow-via-oauth2-state-and-per-refresh-token branch August 7, 2025 14:25
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