Skip to content

Connection based verification#802

Merged
esune merged 18 commits intomainfrom
connection-based-verification
Jul 24, 2025
Merged

Connection based verification#802
esune merged 18 commits intomainfrom
connection-based-verification

Conversation

@Gavinok
Copy link
Contributor

@Gavinok Gavinok commented Jul 16, 2025

This PR resolves #513

The current implementation focuses on ephemeral connections as
specified in the plans, with connection-based verification made
optional via the USE_CONNECTION_BASED_VERIFICATION configuration
flag.

Key Components Added:

  1. Configuration Support (oidc-controller/api/core/config.py:224-225)
  • Added USE_CONNECTION_BASED_VERIFICATION setting (defaults to True)
  • Configurable via environment variable
  1. Enhanced ACA-Py Client (oidc-controller/api/core/acapy/client.py)
  • Extended with 294 new lines of connection handling logic
  • Added support for connection-based proof requests
  1. Webhook Handler Enhancement (oidc-controller/api/routers/acapy_handler.py)
  • Added 168 lines of new webhook processing logic
  • Handles connection state transitions ("request" -> "active"/"completed")
  • Automatically sends presentation requests when connections are established
  1. OIDC Flow Updates (oidc-controller/api/routers/oidc.py)
  • Modified authorization flow to support connection-based verification
  • Added conditional logic based on USE_CONNECTION_BASED_VERIFICATION flag
  • Enhanced auth session management with connection tracking
  1. Auth Session Model (oidc-controller/api/authSessions/models.py)
  • Added connection tracking capabilities to auth sessions
  1. Docker Configuration (docker/manage)
  • Enabled connection-based verification by default

  • Added environment variable support

    Current Status

    • Ephemeral connections - Basic implementation complete
    • Connection cleanup - Ran by default but will need to be made optional in the future
    • Problem reporting on errors - Not yet implemented
    • New Unit Tests - Not yet implemented
    • Persistent connections - Not yet implemented (per user instructions)
    • User profiles - Not yet implemented
    • Multiple agent support - Not yet implemented

The implementation provides a foundation for connection-based
verification that can be toggled on/off, focusing on the ephemeral
connection model outlined in the plans while maintaining backward
compatibility with the existing QR code flow.

Gavinok and others added 4 commits July 16, 2025 13:35
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Signed-off-by: Gavinok <34443260+Gavinok@users.noreply.github.com>
@Gavinok Gavinok marked this pull request as draft July 16, 2025 21:46
@coveralls
Copy link

coveralls commented Jul 16, 2025

Pull Request Test Coverage Report for Build 16483119139

Details

  • 164 of 207 (79.23%) changed or added relevant lines in 7 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+2.1%) to 89.92%

Changes Missing Coverage Covered Lines Changed/Added Lines %
oidc-controller/api/core/models.py 7 8 87.5%
oidc-controller/api/core/acapy/client.py 72 76 94.74%
oidc-controller/api/routers/acapy_handler.py 72 110 65.45%
Totals Coverage Status
Change from base Build 16456992816: 2.1%
Covered Lines: 1017
Relevant Lines: 1131

💛 - Coveralls

Gavinok added 3 commits July 16, 2025 15:09
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>

1. Updated timestamps in models to use UTC for consistency across the application.
2. Added comprehensive tests for ACA-Py webhook handler, covering various scenarios including connection status changes, presentation request handling, and error reporting.
3. Introduced new dependencies in the `pyproject.toml` for HTTP handling in tests.
4. Improved mocking strategies in test cases for better isolation and reliability.

These changes ensure better adherence to time standards and robustness in handling connection-based verification's and related testing.
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
@Gavinok Gavinok force-pushed the connection-based-verification branch from 834c9ce to c1eb8ec Compare July 17, 2025 18:45
@Gavinok Gavinok requested review from esune and loneil and removed request for esune July 17, 2025 18:46
@Gavinok Gavinok marked this pull request as ready for review July 17, 2025 18:46
… auth_sessions

Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
@Gavinok Gavinok force-pushed the connection-based-verification branch from 5937a76 to 7a5d3ba Compare July 21, 2025 18:00
Copy link
Contributor

@loneil loneil left a comment

Choose a reason for hiding this comment

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

Great stuff, mostly some question about existing OOB code and the flag that removes it out, let me know if I'm misunderstanding.

Tried out locally and can get QR code/login etc.
Payload of QR code link just to have here:

image

export INVITATION_LABEL=${INVITATION_LABEL:-"VC-AuthN"}
export SET_NON_REVOKED="True"
export USE_OOB_LOCAL_DID_SERVICE=${USE_OOB_LOCAL_DID_SERVICE:-"true"}
export USE_CONNECTION_BASED_VERIFICATION=${USE_CONNECTION_BASED_VERIFICATION:-"true"}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be in the main docker-compose yaml too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I should have spotted this by testing oob again after implementing connections. Thanks for catching that

Copy link
Member

Choose a reason for hiding this comment

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

This may still need to be added to docker-compose - the diff is not showing changes on that file

@loneil
Copy link
Contributor

loneil commented Jul 22, 2025

@Gavinok any weird behavior on yours with QR expiry?
I'm not sure if this is any existing thing on local, or some other issue (could try main tomorrow) but I get immediate expires it seems:

Screen.Recording.2025-07-21.222112.mp4

I'm not sure if related to any of the changes in this PR but worth a check.

Actually I see the expiry time wierdly set minutes in the past from when I created it
Or if I catch the DB record on immediate creation there isn't an expiry or created time.

image

Gavinok added 4 commits July 22, 2025 10:49
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>

- Removed commented-out code for the depreciated create_invitation method
- Changed comments in the acapy_handler and oidc router modules to remove "NEW" indicators for clarification.
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>

- Removed the hardcoded "pending-" prefix from the session ID lookup when searching by `pres_exch_id` in `acapy_handler.py`, allowing for more flexible ID matching.
- Added a check in `oidc.py` to raise an HTTP 500 error if the invitation message ID is missing, ensuring proper error handling and clearer diagnostics when creating an OOB invitation message.
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
…and pyproject.toml

Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>

- Removed 'httpx' packages from pyproject.toml as they were not needed.
@esune esune requested a review from loneil July 22, 2025 23:40
Copy link
Member

@esune esune left a comment

Choose a reason for hiding this comment

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

I flagged a super minor change - using debug for a couple of log statements to avoid polluting logs in regular mode with information that is not essential.

Other than that changes look good - tested locally as well and verified connection is created with BC Wallet and deleted when interaction ends. Excellent work @Gavinok !

Gavinok and others added 3 commits July 23, 2025 09:40
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Copy link
Contributor

@loneil loneil left a comment

Choose a reason for hiding this comment

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

Need to sort the expiry thing
#802 (comment)

I tried on main and it's working with the configured time but switching to this branch is instant-expiring (unless I'm doing somethng wierd on local)

Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
@Gavinok
Copy link
Contributor Author

Gavinok commented Jul 23, 2025

@loneil Resolved the expiry issue. Just had a timezone inconsistancy it seems. I have all the timestamps now created with UTC for consistancy and that seems to have resolved it

@Gavinok Gavinok requested review from esune and loneil July 23, 2025 18:16
@loneil
Copy link
Contributor

loneil commented Jul 23, 2025

@Gavinok behavior is working ok but see this error throwing out every second

controller-1     | {"event": "Traceback (most recent call last):\n  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 148, in call_next\n    message = await recv_stream.receive()\n              
^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.12/site-packages/anyio/streams/memory.py\", line 111, in receive\n    return self.receive_nowait()\n           ^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.12/site-packages/anyio/streams/memory.py\", line 104, in receive_nowait\n    raise EndOfStream\nanyio.EndOfStream\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n  File \"/app/src/api/main.py\", line 98, in logging_middleware\n    response: Response = await call_next(request)\n                         ^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 156, in call_next\n    raise app_exc\n  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/base.py\", line 141, in coro\n    await self.app(scope, receive_or_disconnect, send_no_error)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/cors.py\", line 85, in __call__\n    await self.app(scope, receive, send)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/middleware/exceptions.py\", line 62, in __call__\n    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n    raise exc\n  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 42, in wrapped_app\n    await app(scope, receive, sender)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 714, in __call__\n    await self.middleware_stack(scope, receive, send)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 734, in app\n    await route.handle(scope, receive, send)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 288, in handle\n    await self.app(scope, receive, send)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 76, in app\n    await wrap_app_handling_exceptions(app, request)(scope, receive, send)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 53, in wrapped_app\n    raise exc\n  File \"/usr/local/lib/python3.12/site-packages/starlette/_exception_handler.py\", line 42, in wrapped_app\n    await app(scope, receive, sender)\n  File \"/usr/local/lib/python3.12/site-packages/starlette/routing.py\", line 73, in app\n    response = await f(request)\n            
   ^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.12/site-packages/fastapi/routing.py\", line 301, in app\n    raw_response = await run_endpoint_function(\n                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/usr/local/lib/python3.12/site-packages/fastapi/routing.py\", line 212, in run_endpoint_function\n    return await dependant.call(**values)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/app/src/api/routers/oidc.py\", line 69, in poll_pres_exch_complete\n    auth_session.expired_timestamp < datetime.now(UTC)\nTypeError: can't compare offset-naive and offset-aware datetimes\n", "logger": "api.main", "level": "error", "timestamp": "2025-07-23T18:43:58.664683Z"}

Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Copy link
Member

@esune esune left a comment

Choose a reason for hiding this comment

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

New changes look goo, tested both in connection-less and short-lived mode and things seem to work as expected.

The USE_CONNECTION_BASED_VERIFICATION flag is not being set in docker-compose.yaml though, I added it manually for testing, but we should have it referenced like other variables for clarity/consistency.

Signed-off-by: Gavin Jaeger-Freeborn <gavinfreeborn@gmail.com>
Copy link
Member

@esune esune left a comment

Choose a reason for hiding this comment

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

LGTM 👍🏻
Next step is updating the chart to support the new configurations (will log separate issue).

Copy link
Contributor

@loneil loneil left a comment

Choose a reason for hiding this comment

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

Think it's all good now, not getting errors logged out. Also tested deep link and it worked ok.

@esune esune merged commit 1a5eb05 into main Jul 24, 2025
6 checks passed
@esune esune deleted the connection-based-verification branch July 24, 2025 17:08
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.

Use short-lived/ephemeral connections instead of connection-less

4 participants