Conversation
There was a problem hiding this comment.
This PR is being reviewed by Cursor Bugbot
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
|
@claude review |
There was a problem hiding this comment.
Pull request overview
This PR adds NEAR wallet authentication using the NEP-413 signature standard, implementing a complete authentication flow with nonce replay protection, timestamp validation, and database-backed session management.
Key Changes:
- Implements NEP-413 signature verification with RPC-based public key ownership validation
- Adds database-backed nonce replay protection with automatic cleanup of expired nonces
- Integrates NEAR authentication into the existing OAuth-based auth system with session and token management
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
crates/services/src/auth/near.rs |
Core NEAR authentication service with NEP-413 verification, nonce validation, and timestamp checks |
crates/services/src/auth/ports.rs |
Adds NearNonceRepository trait for replay protection |
crates/services/src/auth/mod.rs |
Exports NEAR auth service module |
crates/database/src/repositories/near_nonce.rs |
PostgreSQL implementation of nonce repository with INSERT/CONFLICT pattern |
crates/database/src/repositories/mod.rs |
Exports NEAR nonce repository |
crates/database/src/migrations/sql/V0030__add_near_nonces.sql |
Creates near_used_nonces table with hex validation constraint and cleanup index |
crates/database/src/lib.rs |
Exports PostgreSQL nonce repository for public API |
crates/config/src/types.rs |
Adds NearConfig with RPC URL and expected recipient configuration |
crates/api/src/routes/auth.rs |
POST /v1/auth/near endpoint with request validation and structured error responses |
crates/api/src/lib.rs |
Wires NearAuthService into AuthComponents and route configuration |
crates/api/tests/e2e_near_auth.rs |
E2E tests for input validation, nonce expiration, and message/recipient validation |
crates/api/tests/common/mod.rs |
Test helpers for creating NEP-413 payloads with configurable timestamps |
crates/services/Cargo.toml |
Adds near-api dependency from GitHub |
crates/api/Cargo.toml |
Adds near-api, base64, and rand dependencies |
Cargo.lock |
Locks NEAR-related dependencies and transitive dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
crates/config/src/types.rs
Outdated
| Self { | ||
| rpc_url: env::var("NEAR_RPC_URL") | ||
| .unwrap_or_else(|_| "https://free.rpc.fastnear.com".to_string()), | ||
| expected_recipient: NEAR_DEFAULT_RECIPIENT.to_string(), |
There was a problem hiding this comment.
The expected_recipient field is hardcoded to NEAR_DEFAULT_RECIPIENT and cannot be configured via environment variable. This prevents customization for different deployment environments (e.g., staging vs production, different domains). Consider adding an environment variable option like NEAR_EXPECTED_RECIPIENT that falls back to the default if not set, similar to how rpc_url is handled.
| expected_recipient: NEAR_DEFAULT_RECIPIENT.to_string(), | |
| expected_recipient: env::var("NEAR_EXPECTED_RECIPIENT") | |
| .unwrap_or_else(|_| NEAR_DEFAULT_RECIPIENT.to_string()), |
crates/services/src/auth/near.rs
Outdated
| const EXPECTED_MESSAGE: &str = "Sign in to NEAR AI Cloud"; | ||
|
|
||
| /// Custom error type for NEAR authentication | ||
| #[derive(Debug)] |
There was a problem hiding this comment.
We should use thiserror. Example:
cloud-api/crates/services/src/auth/ports.rs
Lines 102 to 138 in 3e7f179
| Self::validate_message(&payload.message).map_err(|e| anyhow::anyhow!(e))?; | ||
|
|
||
| // 3. Cleanup expired nonces | ||
| self.cleanup_nonces().await; |
There was a problem hiding this comment.
I think that should be a periodic process. Not on every requests?
There was a problem hiding this comment.
actually it's a balance between optimization and code simplicity, since we have the index INDEX idx_near_used_nonces_used_at ON near_used_nonces(used_at), deletion won't cause a full table scan.
So the cleanup should be very effective each call. (Imagine we have 10k new NEAR auth each day, the deletion call will only touch about 20 rows each time)
crates/services/src/auth/near.rs
Outdated
| 1, | ||
| 7 * 24, |
crates/api/src/routes/auth.rs
Outdated
| status, | ||
| Json(serde_json::json!({ | ||
| "error": error_type, | ||
| "error_description": error_msg |
There was a problem hiding this comment.
Returns internal error?
There was a problem hiding this comment.
We shouldn't leak internal error details.
The comments has been resolved.
Note
Adds NEAR wallet authentication endpoint with NEP-413 verification, DB-backed nonce replay protection, config/env wiring, and E2E tests.
POST /v1/auth/nearroute and wire viabuild_auth_routes; passAuthComponentsand includenear_auth_serviceinAuthComponents.NearAuthService(NEP-413): validates recipient/message, nonce timestamp (5‑min window), verifies signature vianear-api, consumes nonce to prevent replay, then creates session.NearNonceRepositoryport; integrate with existingAuthServiceTrait.V0033__add_near_nonces.sqlcreatingnear_used_noncestable + index.PostgresNearNonceRepositorywithconsume_nonceand cleanup.NearConfig { rpc_url, expected_recipient }toAuthConfig; load from env (NEAR_EXPECTED_RECIPIENT, optionalNEAR_RPC_URL).e2e_near_authcovering invalid signatures, User‑Agent checks, nonce window, invalid message/recipient, malformed JSON, zero‑timestamp nonce.near-api,base64; lockfile updates and minor crate version pinning (e.g.,hmac,sha2,secp256k1).Written by Cursor Bugbot for commit 516db68. This will update automatically on new commits. Configure here.