Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): implement Passkey authentication #109

Merged
merged 12 commits into from
Feb 2, 2025
Merged

Conversation

espaciofuturoio
Copy link
Collaborator

@espaciofuturoio espaciofuturoio commented Feb 1, 2025

Notes

Remenber to use a valid redis url or implement another DB.

Registration Flow

  1. Request Registration Options: The user device initiates the registration process by requesting options from the API.
  2. Return WebAuthn Registration Options: The API responds with the necessary WebAuthn registration options.
  3. Create Registration Response: The user device uses these options to create a registration response.
  4. Verify Registration: The API verifies the registration response and returns the result to the user device.

Authentication Flow

  1. Request Authentication Options: The user device requests authentication options from the API.
  2. Return WebAuthn Authentication Options: The API provides the necessary WebAuthn authentication options.
  3. Create Authentication Response: The user device creates an authentication response using the provided options.
  4. Verify Authentication: The API verifies the authentication response and returns the result to the user device.

You should add some env vars to your CI. This is an example:

REDIS_URL=''
RP_ID='["localhost", "kind-fi.com"]'
RP_NAME='["App", "Kind-Fi"]'
EXPECTED_ORIGIN='["http://localhost:3000", "https://kind-fi.com"]'
CHALLENGE_TTL_SECONDS=60

Summary by CodeRabbit

  • New Features

    • Introduced secure passkey workflows for registration and authentication, leveraging WebAuthn to enhance security and user verification.
  • Documentation

    • Updated the Passkey API guides with clear instructions and flow details for both registration and authentication, including common error scenarios.

Copy link

vercel bot commented Feb 1, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
kindfi ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 2, 2025 10:03pm

Copy link
Contributor

coderabbitai bot commented Feb 1, 2025

Walkthrough

The changes add comprehensive Passkey API documentation and implement new endpoints for passkey registration and authentication. Each endpoint’s route includes a dedicated asynchronous POST function with robust error handling. In addition, new modules and utility functions are introduced to manage challenges, credentials, and cryptographic operations using Redis and Stellar. Environment variable validation is established via a schema using zod. A custom error handling mechanism is also incorporated along with a deployment utility for Stellar contracts. Finally, package dependencies are updated to support these functionalities.

Changes

File(s) Change Summary
apps/web/app/api/passkey/README.md Added documentation for Passkey API endpoints including registration and authentication flows, request/response formats, and common errors.
apps/web/app/api/passkey/*/route.ts Added new asynchronous POST functions for generating/validating registration and authentication options with structured error handling.
apps/web/lib/passkey/deploy.ts Introduced handleDeploy to deploy Stellar contracts, including transaction simulation and error checks.
apps/web/lib/passkey/env.ts Added environment schema validation using zod with default values and computed configuration properties.
apps/web/lib/passkey/errors.ts Implemented custom error handling with an ErrorCode enum, error messages record, and InAppError class.
apps/web/lib/passkey/passkey.ts Added functions for generating and verifying WebAuthn registration and authentication options, managing challenges, and user credentials.
apps/web/lib/passkey/redis.ts Created a Redis module for storing and retrieving challenges and user credentials with utility conversion functions.
apps/web/lib/passkey/stellar.ts Added utilities for account string formatting, extracting public keys from responses, and converting ECDSA signatures.
package.json Added new dependencies including libraries for WebAuthn, base64 encoding, bigint conversion, CBOR, and Redis integration.

Sequence Diagram(s)

sequenceDiagram
    participant Client as User Device
    participant API as Passkey API
    participant Handler as Registration Handler
    Client->>API: POST /api/passkey/generate-registration-options<br>(identifier, origin)
    API->>Handler: Call getRegistrationOptions
    Handler-->>API: Return registration options
    API-->>Client: Return registration options

    Client->>API: POST /api/passkey/verify-registration<br>(registration response)
    API->>Handler: Call verifyRegistration
    Handler-->>API: Return verification result
    API-->>Client: Return verification result
Loading
sequenceDiagram
    participant Client as User Device
    participant API as Passkey API
    participant Handler as Authentication Handler
    Client->>API: POST /api/passkey/generate-authentication-options<br>(identifier, origin)
    API->>Handler: Call getAuthenticationOptions
    Handler-->>API: Return authentication options
    API-->>Client: Return authentication options

    Client->>API: POST /api/passkey/verify-authentication<br>(authentication response)
    API->>Handler: Call verifyAuthentication
    Handler-->>API: Return verification result
    API-->>Client: Return verification result
Loading

Suggested reviewers

  • AndlerRL

Poem

I'm a rabbit now, full of glee,
Hopping through endpoints wild and free.
Carrots of code piled in a row,
Registration and auth now in a glow!
With Stellar hops and Redis cheer,
I celebrate these changes—happy ear to ear!
🐰🥕

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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. (Beta)
  • @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.

@coderabbitai coderabbitai bot added documentation Improvements or additions to documentation enhancement New feature improvement or request webapp web app related labels Feb 1, 2025
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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 31

🛑 Comments failed to post (31)
apps/web/lib/passkey/deploy.ts (5)

16-40: 🧹 Nitpick (assertive)

Team-based code clarity.
The generation of deployee involves constructing a unique contract address using FACTORY_CONTRACT_ID and a salt. This logic is concise and clear. However, it may be beneficial to add inline comments explaining how the ContractIdPreimage is assembled to assist new contributors.


48-79: 🧹 Nitpick (assertive)

Consider broader simulation error details.
After simulating the transaction (simulateTransaction), the code checks if there's an error or restore, then immediately throws. In some cases, providing more context or user-friendly messages (e.g., “Insufficient funds” or “Invalid sequence number”) can help troubleshooting.


80-93: 🧹 Nitpick (assertive)

Robust Horizon response handling.
Currently, the code checks txResp.successful and otherwise throws txResp. For improved user experience, consider examining txResp.extras or other response fields to provide clearer error handling messages (e.g., insufficient fee, bad sequence, etc.).


1-14: 💡 Codebase verification

Action Required: Implement Environment Variable Validations in deploy.ts

The grep output confirms that the file only destructures values from ENV without any explicit validation checks. Please add logic to verify that RPC_URL, FACTORY_CONTRACT_ID, HORIZON_URL, and NETWORK_PASSPHRASE are defined (or non-empty) and throw a clear error if any are missing.

  • File: apps/web/lib/passkey/deploy.ts
  • Issue: Lack of validations for critical environment variables
🔗 Analysis chain

Ensure environment variables are validated.
The code relies on RPC_URL, FACTORY_CONTRACT_ID, HORIZON_URL, and NETWORK_PASSPHRASE from the environment. Consider verifying these values to handle missing or misconfigured environment variables gracefully (e.g., throw an explicit error if any is undefined).

A quick check script might look like this:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
rg -A 3 'ENV.' |
  grep -E 'FACTORY_CONTRACT_ID|HORIZON_URL|RPC_URL|NETWORK_PASSPHRASE'

Length of output: 194


41-47: 🧹 Nitpick (assertive)

Handle potential exceptions from getContractData.
Calling rpc.getContractData(...) can fail if the contract data is not found or if there's a connection error. Currently, there's no explicit error handling or fallback logic. Consider catching exceptions or checking the status to avoid letting an unhandled rejection bubble up.

  if (!publicKey) {
-    await rpc.getContractData(deployee, xdr.ScVal.scvLedgerKeyContractInstance())
-    return deployee
+    try {
+      await rpc.getContractData(deployee, xdr.ScVal.scvLedgerKeyContractInstance())
+      return deployee
+    } catch (error) {
+      // Handle or re-throw with context
+      throw new Error(`Contract data retrieval failed: ${error}`)
+    }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  if (!publicKey) {
    try {
      await rpc.getContractData(deployee, xdr.ScVal.scvLedgerKeyContractInstance())
      return deployee
    } catch (error) {
      // Handle or re-throw with context
      throw new Error(`Contract data retrieval failed: ${error}`)
    }
  }
apps/web/lib/passkey/stellar.ts (3)

108-184: 🧹 Nitpick (assertive)

Consider using a well-tested library for ECDSA signature parsing.
convertEcdsaSignatureAsnToCompact manually parses ASN.1 sequences and manipulates buffers. While instructive, it can be error-prone. If a widely adopted library exists (e.g., from a crypto library), it can reduce the risk of subtle bugs and make future maintenance easier.


1-13: 🧹 Nitpick (assertive)

Prevent unexpected truncation issues.
In truncateAccount(), slicing a string assumes a minimum length. Consider a defensive check for very short strings or adding a comment to clarify assumptions about the account's expected format or length.

 export const truncateAccount = (account: string) => {
-  return `${account.slice(0, 5)}...${account.slice(-5)}`
+  if (account.length <= 10) {
+    return account
+  }
+  return `${account.slice(0, 5)}...${account.slice(-5)}`
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

import type {
	AuthenticationResponseJSON,
	RegistrationResponseJSON,
} from '@simplewebauthn/browser'
import { hash } from '@stellar/stellar-sdk'
import base64url from 'base64url'
import { bigintToBuf, bufToBigint } from 'bigint-conversion'
import * as CBOR from 'cbor-x/decode'

export const truncateAccount = (account: string) => {
	if (account.length <= 10) {
		return account
	}
	return `${account.slice(0, 5)}...${account.slice(-5)}`
}

80-106: ⚠️ Potential issue

Avoid logging full registration data in production.
console.log(JSON.stringify(registration, null, 2)) can leak sensitive PII or cryptographic details. Use an environment-based conditional or remove these logs in production builds.

- console.log(JSON.stringify(registration, null, 2))
+ // console.debug('Received registration payload (truncated)', registration.id)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

export const getPublicKeys = async (
	registration: RegistrationResponseJSON | AuthenticationResponseJSON,
) => {
	const contractSalt = hash(base64url.toBuffer(registration.id))

	// console.debug('Received registration payload (truncated)', registration.id)

	if ('attestationObject' in registration.response) {
		// Handle RegistrationResponseJSON
		const { publicKeyObject } = getPublicKeyObject(
			registration.response.attestationObject,
		)
		const publicKey = Buffer.from([
			4, // (0x04 prefix) https://en.bitcoin.it/wiki/Elliptic_Curve_Digital_Signature_Algorithm
			...(publicKeyObject.get('-2') as Buffer),
			...(publicKeyObject.get('-3') as Buffer),
		])

		return {
			contractSalt,
			publicKey,
		}
	}
	return {
		contractSalt,
	}
}
apps/web/lib/passkey/passkey.ts (5)

51-101: 🧹 Nitpick (assertive)

Avoid partial user creation errors.
When generating registration options, if getUser or saveChallenge fails, it may leave the system in an inconsistent state. Although these operations might rarely fail, consider wrapping them in a try-catch or adding transactional guarantees to handle partial failures gracefully.


103-164: 🧹 Nitpick (assertive)

Note concurrency or race conditions in challenge storage.
verifyRegistration fetches a challenge from Redis and deletes it afterward. If multiple parallel requests are made, one might unintentionally invalidate the other's challenge. If this is undesired, consider a locking mechanism or a single-flight pattern to prevent collisions.


166-202: 🧹 Nitpick (assertive)

Check for unregistered users in getAuthenticationOptions.
If userResponse is undefined, an UNEXPECTED_ERROR is thrown, but consider adding more specific debugging or user-friendly messages. This helps differentiate between a non-existent user vs. a database or caching issue.


204-261: 🧹 Nitpick (assertive)

Potential multi-credential concurrency edge cases.
verifyAuthentication updates the credential’s counter. If multiple authentications happen near-simultaneously, the counter might incorrectly update. Although rare, consider if the DB handles concurrency well or if a check for older counters is needed.


1-49: 💡 Codebase verification

Add validation to guarantee consistent lengths among ENV arrays

  • The arrays EXPECTED_ORIGIN, RP_NAME, and RP_ID are defined separately in apps/web/lib/passkey/env.ts with default values that are consistent (each default is a one-element array). However, there is no mechanism to validate their lengths at runtime.
  • Without additional checks, if an environment variable is misconfigured (i.e., set with arrays of different lengths), the getRpInfo function may attempt to access a non-existent index, leading to runtime errors.
  • Consider implementing a validation step—either during the environment parsing or within getRpInfo—to ensure that all three arrays always have matching lengths.
🔗 Analysis chain

Ensure consistent lengths for environment arrays.
ENV.EXPECTED_ORIGIN, ENV.RP_NAME, and ENV.RP_ID should have matching lengths. Consider adding a validation step ensuring each index is safe to use for all.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the arrays in env have the same length by searching their definitions:
rg -A 5 'EXPECTED_ORIGIN|RP_NAME|RP_ID'

Length of output: 3386

apps/web/app/api/passkey/generate-registration-options/route.ts (2)

15-22: 🛠️ Refactor suggestion

Differentiate error status codes.

Using status code 500 for all errors doesn't properly communicate the nature of the error to clients.

Consider differentiating status codes:

 if (error instanceof InAppError) {
-  return NextResponse.json({ error: error.message }, { status: 500 })
+  const status = error.code === ErrorCode.INVALID_INPUT ? 400 : 500
+  return NextResponse.json({ error: error.message }, { status })
 }
 return NextResponse.json(
   { error: 'Failed to generate registration options' },
   { status: 500 },
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		if (error instanceof InAppError) {
			const status = error.code === ErrorCode.INVALID_INPUT ? 400 : 500
			return NextResponse.json({ error: error.message }, { status })
		}
		return NextResponse.json(
			{ error: 'Failed to generate registration options' },
			{ status: 500 },
		)
	}

8-11: ⚠️ Potential issue

Add input validation for identifier and origin.

The current implementation lacks input validation for critical security parameters:

  1. identifier should be validated for format and length
  2. Empty origin fallback could pose security risks in WebAuthn implementation

Consider adding validation:

 const input = {
+  identifier: validateIdentifier(body.identifier),
-  origin: req.headers.get('origin') || body.origin || '',
+  origin: validateOrigin(req.headers.get('origin') || body.origin),
 }

+ function validateIdentifier(identifier: unknown): string {
+   if (!identifier || typeof identifier !== 'string' || identifier.length > 64) {
+     throw new InAppError(ErrorCode.INVALID_INPUT, 'Invalid identifier format')
+   }
+   return identifier
+ }

+ function validateOrigin(origin: string | null): string {
+   if (!origin || !origin.startsWith('https://')) {
+     throw new InAppError(ErrorCode.INVALID_INPUT, 'Invalid origin')
+   }
+   return origin
+ }

Committable suggestion skipped: line range outside the PR's diff.

apps/web/app/api/passkey/generate-authentication-options/route.ts (1)

8-12: 🛠️ Refactor suggestion

⚠️ Potential issue

Add input validation and consider extracting common code.

Similar to the registration endpoint, input validation is missing. Additionally, there's code duplication between authentication and registration handlers.

  1. Add validation:
 const input = {
+  identifier: validateIdentifier(body.identifier),
+  origin: validateOrigin(req.headers.get('origin') || body.origin),
+  challenge: validateChallenge(body.challenge),
-  identifier: body.identifier,
-  origin: req.headers.get('origin') || body.origin || '',
-  challenge: body.challenge,
 }

+ function validateChallenge(challenge: unknown): string {
+   if (!challenge || typeof challenge !== 'string' || !/^[A-Za-z0-9+/=]+$/.test(challenge)) {
+     throw new InAppError(ErrorCode.INVALID_INPUT, 'Invalid challenge format')
+   }
+   return challenge
+ }
  1. Consider creating a shared middleware for common validation logic between registration and authentication handlers.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		const input = {
			identifier: validateIdentifier(body.identifier),
			origin: validateOrigin(req.headers.get('origin') || body.origin),
			challenge: validateChallenge(body.challenge),
		}

		function validateChallenge(challenge: unknown): string {
			if (!challenge || typeof challenge !== 'string' || !/^[A-Za-z0-9+/=]+$/.test(challenge)) {
				throw new InAppError(ErrorCode.INVALID_INPUT, 'Invalid challenge format')
			}
			return challenge
		}
apps/web/lib/passkey/errors.ts (2)

1-6: 🛠️ Refactor suggestion

Add error codes for input validation and rate limiting.

The current error codes don't cover common WebAuthn implementation needs.

 export enum ErrorCode {
   NO_MATCHING_RP_ID = 'NO_MATCHING_RP_ID',
   CHALLENGE_NOT_FOUND = 'CHALLENGE_NOT_FOUND',
   AUTHENTICATOR_NOT_REGISTERED = 'AUTHENTICATOR_NOT_REGISTERED',
   UNEXPECTED_ERROR = 'UNEXPECTED_ERROR',
+  INVALID_INPUT = 'INVALID_INPUT',
+  RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
+  INVALID_CREDENTIAL = 'INVALID_CREDENTIAL',
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

export enum ErrorCode {
	NO_MATCHING_RP_ID = 'NO_MATCHING_RP_ID',
	CHALLENGE_NOT_FOUND = 'CHALLENGE_NOT_FOUND',
	AUTHENTICATOR_NOT_REGISTERED = 'AUTHENTICATOR_NOT_REGISTERED',
	UNEXPECTED_ERROR = 'UNEXPECTED_ERROR',
	INVALID_INPUT = 'INVALID_INPUT',
	RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED',
	INVALID_CREDENTIAL = 'INVALID_CREDENTIAL',
}

16-23: 🧹 Nitpick (assertive)

Add HTTP status code mapping to error codes.

To ensure consistent error responses across endpoints, add status code mapping.

 export class InAppError extends Error {
   code: ErrorCode
+  status: number
   constructor(code: ErrorCode, message?: string) {
     super(message || ERROR_MESSAGES[code])
     this.name = 'InAppError'
     this.code = code
+    this.status = this.getStatusCode()
   }
+  
+  private getStatusCode(): number {
+    switch (this.code) {
+      case ErrorCode.INVALID_INPUT:
+        return 400
+      case ErrorCode.RATE_LIMIT_EXCEEDED:
+        return 429
+      case ErrorCode.NO_MATCHING_RP_ID:
+      case ErrorCode.AUTHENTICATOR_NOT_REGISTERED:
+        return 403
+      default:
+        return 500
+    }
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

export class InAppError extends Error {
	code: ErrorCode
	status: number
	constructor(code: ErrorCode, message?: string) {
		super(message || ERROR_MESSAGES[code])
		this.name = 'InAppError'
		this.code = code
		this.status = this.getStatusCode()
	}
  
	private getStatusCode(): number {
		switch (this.code) {
			case ErrorCode.INVALID_INPUT:
				return 400
			case ErrorCode.RATE_LIMIT_EXCEEDED:
				return 429
			case ErrorCode.NO_MATCHING_RP_ID:
			case ErrorCode.AUTHENTICATOR_NOT_REGISTERED:
				return 403
			default:
				return 500
		}
	}
}
apps/web/app/api/passkey/verify-registration/route.ts (2)

19-19: ⚠️ Potential issue

Avoid logging sensitive error details.

The current error logging could expose sensitive information.

- console.error('Error verifying registration', error)
+ console.error('Error verifying registration:', {
+   code: error instanceof InAppError ? error.code : 'UNEXPECTED_ERROR',
+   message: error instanceof InAppError ? error.message : 'An unexpected error occurred',
+   // Add request context but exclude sensitive data
+   context: {
+     hasIdentifier: !!body?.identifier,
+     hasOrigin: !!body?.origin,
+     hasResponse: !!body?.registrationResponse,
+   }
+ })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		console.error('Error verifying registration:', {
		  code: error instanceof InAppError ? error.code : 'UNEXPECTED_ERROR',
		  message: error instanceof InAppError ? error.message : 'An unexpected error occurred',
		  // Add request context but exclude sensitive data
		  context: {
		    hasIdentifier: !!body?.identifier,
		    hasOrigin: !!body?.origin,
		    hasResponse: !!body?.registrationResponse,
		  }
		})

8-12: ⚠️ Potential issue

Add validation for registrationResponse.

The registration response should be validated before processing.

 const input = {
+  identifier: validateIdentifier(body.identifier),
+  origin: validateOrigin(req.headers.get('origin') || body.origin),
+  registrationResponse: validateRegistrationResponse(body.registrationResponse),
-  identifier: body.identifier,
-  origin: req.headers.get('origin') || body.origin || '',
-  registrationResponse: body.registrationResponse,
 }

+ function validateRegistrationResponse(response: unknown): WebAuthnRegistrationResponse {
+   if (!response || typeof response !== 'object' || !response.clientDataJSON || !response.attestationObject) {
+     throw new InAppError(ErrorCode.INVALID_INPUT, 'Invalid registration response format')
+   }
+   return response as WebAuthnRegistrationResponse
+ }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		const input = {
			identifier: validateIdentifier(body.identifier),
			origin: validateOrigin(req.headers.get('origin') || body.origin),
			registrationResponse: validateRegistrationResponse(body.registrationResponse),
		}

		function validateRegistrationResponse(response: unknown): WebAuthnRegistrationResponse {
			if (
				!response ||
				typeof response !== 'object' ||
				!response.clientDataJSON ||
				!response.attestationObject
			) {
				throw new InAppError(ErrorCode.INVALID_INPUT, 'Invalid registration response format')
			}
			return response as WebAuthnRegistrationResponse
		}
apps/web/app/api/passkey/verify-authentication/route.ts (2)

15-24: ⚠️ Potential issue

Improve error handling.

The current implementation has several issues:

  1. Uses generic 500 status code for all errors
  2. Exposes error details in production
  3. Logs sensitive information to console

Apply this diff to improve error handling:

 } catch (error) {
-  console.error('Error verifying authentication', error)
+  console.error('Error verifying authentication')
   if (error instanceof InAppError) {
     return NextResponse.json({ error: error.message }, { status: 500 })
   }
+  if (error instanceof Error && error.message.includes('Missing')) {
+    return NextResponse.json({ error: 'Invalid request' }, { status: 400 })
+  }
   return NextResponse.json(
     { error: 'Failed to verify authentication' },
     { status: 500 },
   )
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	} catch (error) {
		console.error('Error verifying authentication')
		if (error instanceof InAppError) {
			return NextResponse.json({ error: error.message }, { status: 500 })
		}
		if (error instanceof Error && error.message.includes('Missing')) {
			return NextResponse.json({ error: 'Invalid request' }, { status: 400 })
		}
		return NextResponse.json(
			{ error: 'Failed to verify authentication' },
			{ status: 500 },
		)
	}

8-12: ⚠️ Potential issue

Add input validation for required fields.

The code should validate that all required fields (identifier, authenticationResponse) are present in the request body before proceeding.

Apply this diff to add input validation:

 const body = await req.json()
+if (!body.identifier || !body.authenticationResponse) {
+  return NextResponse.json(
+    { error: 'Missing required fields' },
+    { status: 400 }
+  )
+}
 const input = {
   identifier: body.identifier,
   origin: req.headers.get('origin') || body.origin || '',
   authenticationResponse: body.authenticationResponse,
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	const body = await req.json()
	if (!body.identifier || !body.authenticationResponse) {
	  return NextResponse.json(
	    { error: 'Missing required fields' },
	    { status: 400 }
	  )
	}
	const input = {
		identifier: body.identifier,
		origin: req.headers.get('origin') || body.origin || '',
		authenticationResponse: body.authenticationResponse,
	}
apps/web/lib/passkey/env.ts (2)

65-70: 🛠️ Refactor suggestion

Improve error handling for environment validation.

The current implementation exits the process on validation failure, which might not be suitable for all environments. Consider implementing a more graceful failure mode.

Apply this diff to improve error handling:

 } catch (err) {
   if (err instanceof z.ZodError) {
-    console.error(err.issues)
+    console.error('Invalid environment configuration')
+    if (process.env.NODE_ENV !== 'production') {
+      console.error(err.issues)
+    }
   }
-  process.exit(1)
+  throw new Error('Failed to load environment configuration')
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

} catch (err) {
	if (err instanceof z.ZodError) {
		console.error('Invalid environment configuration')
		if (process.env.NODE_ENV !== 'production') {
			console.error(err.issues)
		}
	}
	throw new Error('Failed to load environment configuration')
}

4-50: 💡 Codebase verification

Review default values in passkey/env.ts may be unsuitable for production.

The investigation indicates that while most production modules appropriately source environment variables (e.g. via process.env), the passkey configuration in apps/web/lib/passkey/env.ts still defines hardcoded defaults (for values like REDIS_URL, RP_ID, etc.) that could inadvertently be used if the production environment does not override them.

  • apps/web/lib/passkey/env.ts: Uses Zod to validate and transform values but falls back to defaults that seem better suited for local/testing environments rather than production.
  • Other parts of the codebase: Production files (e.g. in services/ai, apps/kyc-server, etc.) rely on explicit environment variables, confirming that production settings are expected to be set externally.

Please ensure that for production deployments the required passkey environment variables are provided so that these defaults do not inadvertently take effect.

🔗 Analysis chain

Review default values for production readiness.

The schema includes hardcoded default values that might not be suitable for production:

  1. Empty Redis URL
  2. Default contract IDs and URLs pointing to test networks
  3. Short challenge TTL

Run this script to check if these defaults are used in production:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if production environment variables are properly set
# Test: Verify that production doesn't rely on default values

# Check environment variables in production deployment
echo "Checking environment variables..."
rg -l 'process\.env\.' | while read -r file; do
  echo "=== $file ==="
  rg 'process\.env\.' "$file" -A 2 -B 2
done

Length of output: 3984

apps/web/lib/passkey/redis.ts (2)

76-108: 🧹 Nitpick (assertive)

Consider data persistence and security improvements.

The TODO comment indicates this is a temporary solution. Additionally:

  1. User data is stored without encryption
  2. No key prefix for multi-tenant isolation
  3. Error handling returns null instead of throwing

Consider implementing:

  1. Data encryption for sensitive user data
  2. Key prefixing for multi-tenant support
  3. Proper error propagation
  4. Migration to a persistent database as mentioned in the TODO

Would you like me to create an issue to track these improvements?


10-19: ⚠️ Potential issue

Add Redis connection error handling and pooling.

The current Redis connection implementation lacks error handling and connection pooling.

Apply this diff to improve Redis connection handling:

+const REDIS_RECONNECT_ATTEMPTS = 10
+const REDIS_RECONNECT_DELAY = 1000

 const getRedis = () => {
   if (!ENV.REDIS_URL) {
     console.log('Using Redis Mock')
     return new RedisMock()
   }
   console.log('Using Cloud Redis')
-  return new Redis(ENV.REDIS_URL)
+  const client = new Redis(ENV.REDIS_URL, {
+    retryStrategy: (times) => {
+      if (times > REDIS_RECONNECT_ATTEMPTS) {
+        return null
+      }
+      return REDIS_RECONNECT_DELAY
+    }
+  })
+  client.on('error', (err) => {
+    console.error('Redis connection error:', err)
+  })
+  return client
 }

-const redis = getRedis()
+const redis = getRedis()
+process.on('SIGTERM', () => {
+  redis.disconnect()
+})
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

const REDIS_RECONNECT_ATTEMPTS = 10
const REDIS_RECONNECT_DELAY = 1000

const getRedis = () => {
	if (!ENV.REDIS_URL) {
		console.log('Using Redis Mock')
		return new RedisMock()
	}
	console.log('Using Cloud Redis')
	const client = new Redis(ENV.REDIS_URL, {
		retryStrategy: (times) => {
			if (times > REDIS_RECONNECT_ATTEMPTS) {
				return null
			}
			return REDIS_RECONNECT_DELAY
		}
	})
	client.on('error', (err) => {
		console.error('Redis connection error:', err)
	})
	return client
}

const redis = getRedis()
process.on('SIGTERM', () => {
	redis.disconnect()
})
apps/web/app/api/passkey/README.md (5)

1-2: 🧹 Nitpick (assertive)

Top-Level Heading Recommendation:
The file currently begins with "## Usage". According to Markdown lint MD041, the first line should be a top-level heading. Consider updating this line to use a single hash (e.g., "# Usage") to adhere to common markdown style guidelines.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

1-1: First line in a file should be a top-level heading
null

(MD041, first-line-heading, first-line-h1)


3-11: 🧹 Nitpick (assertive)

Clear API Endpoint Definition for Generate Registration Options:
The "Generate Registration Options" endpoint is clearly documented with its HTTP method, URL, request body, and a brief description of the expected WebAuthn registration options response. For even greater clarity, consider adding a complete example JSON response in future documentation updates.


12-18: 🧹 Nitpick (assertive)

Detailed Documentation for Verify Registration Endpoint:
The POST endpoint for verifying registration is well described, including both the required request body structure and the expected verification result. Adding an example response here might further assist developers in integrating with the API.


26-32: 🧹 Nitpick (assertive)

Clear Presentation for Verify Authentication Endpoint:
Documentation for this endpoint correctly outlines the POST request details and the structure of the request body. Providing a sample response could be beneficial for developers when implementing client-side logic.


35-87: 🧹 Nitpick (assertive)

ASCII Flow Diagram Review:
The diagram effectively illustrates the sequential interactions between the user device and the API for both registration and authentication flows. To improve its readability and ensure consistent formatting across various markdown viewers, consider enclosing the diagram within a fenced code block (e.g., using triple backticks with a language hint like plaintext).

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: 3

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between effe717 and 0279408.

📒 Files selected for processing (1)
  • apps/web/app/api/passkey/README.md (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
apps/web/app/api/passkey/README.md

1-1: First line in a file should be a top-level heading
null

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (4)
apps/web/app/api/passkey/README.md (4)

5-12: Generate Registration Options Documentation Clarity
The documentation for the "Generate Registration Options" endpoint is clear and provides all necessary details such as the HTTP method, endpoint URL, request body, and the expected response.


12-18: Verify Registration Endpoint Documentation
The description for the "Verify Registration" endpoint is well-detailed. The inclusion of both request payload and response information ensures clarity. Consider providing an explanation for the ellipsis ({...}) in the registrationResponse field elsewhere in the documentation if not already done.


19-25: Generate Authentication Options Documentation Clarity
The documentation for the "Generate Authentication Options" endpoint is consistent and clear, with a concise explanation of the expected request and response.


26-32: Verify Authentication Endpoint Documentation
The endpoint description for "Verify Authentication" is clearly outlined with the necessary details in the request body and the expected response format.

apps/web/app/api/passkey/README.md Outdated Show resolved Hide resolved
apps/web/app/api/passkey/README.md Outdated Show resolved Hide resolved
apps/web/app/api/passkey/README.md Outdated Show resolved Hide resolved
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: 1

♻️ Duplicate comments (2)
apps/web/app/api/passkey/README.md (2)

35-65: 🧹 Nitpick (assertive)

Registration Flow Diagram – Enhance Accessibility
The ASCII diagram effectively visualizes the registration process. However, to improve accessibility for users (especially those using screen readers), consider adding a brief textual description or alt-text caption immediately below the diagram. This will help users who might find ASCII diagrams less accessible.


73-103: 🧹 Nitpick (assertive)

Authentication Flow Diagram – Accessibility Improvement Suggested
The Authentication Flow diagram is well-structured and clear. To further enhance this section, consider adding a caption or brief textual summary below the diagram to describe the flow for those who might have difficulty interpreting ASCII art.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0279408 and eaa521d.

📒 Files selected for processing (1)
  • apps/web/app/api/passkey/README.md (1 hunks)
🔇 Additional comments (3)
apps/web/app/api/passkey/README.md (3)

1-3: Header and Section Titles are Well-Formatted
The use of a top-level header (# Usage) followed by structured section headings (e.g., ## API Endpoints) complies with markdownlint standards and improves document readability.


66-72: Registration Flow Summary is Concise and Clear
The summary provided after the registration flow diagram succinctly captures the sequence of actions. The steps are numbered and clearly explain the process, which aids comprehension.


104-109: Authentication Flow Summary is Well-Structured
The summary clearly outlines the steps of the authentication process, paralleling the registration flow summary well. This clarity aids users in understanding the complete authentication cycle.

apps/web/app/api/passkey/README.md Outdated Show resolved Hide resolved
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: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between eaa521d and f4322a2.

📒 Files selected for processing (2)
  • apps/web/.env.sample (1 hunks)
  • apps/web/app/api/passkey/README.md (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
apps/web/app/api/passkey/README.md

11-11: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


15-15: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


17-17: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


29-29: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


33-33: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


35-35: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


47-47: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


51-51: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


53-53: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


65-65: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


69-69: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


71-71: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)

🔇 Additional comments (9)
apps/web/.env.sample (1)

7-11: New Environment Variables for Passkey Authentication Added
The addition of REDIS_URL, RP_ID, RP_NAME, EXPECTED_ORIGIN, and CHALLENGE_TTL_SECONDS is essential for configuring Passkey authentication. Verify that these default values are appropriately updated for your local and production environments.

apps/web/app/api/passkey/README.md (8)

1-4: Documentation Header and Structure are Well-Defined
The document starts with a top-level # Usage header and properly segments the API documentation. This establishes a clear organizational context for the reader.


5-22: Clear Documentation for Generating Registration Options
This section clearly explains the POST endpoint /api/passkey/generate-registration-options along with its request body, success response, and error response. It might be beneficial to include a brief note on when the error "No matching RP ID found for the given origin" is triggered.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

11-11: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


15-15: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


17-17: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


23-40: Comprehensive Verify Registration Endpoint Documentation
The Verify Registration endpoint is well documented with its request structure and sample responses. Consider adding a short explanation of the underlying verification process or any prerequisites that must be met for successful verification.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

29-29: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


33-33: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


35-35: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


41-58: Generate Authentication Options Endpoint is Well-Documented
The POST endpoint /api/passkey/generate-authentication-options is clearly detailed with both the expected request body and the sample responses. The error response "Authenticator not registered" provides a clear example of potential failure modes.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

47-47: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


51-51: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


53-53: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


59-76: Clear Documentation of the Verify Authentication Endpoint
This section details the request and response for the Verify Authentication endpoint precisely. Ensure that the error conditions described here consistently reflect the API’s implementation.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

65-65: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


69-69: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


71-71: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


77-83: Accurate and Useful Listing of Common Error Messages
Listing common error messages in a dedicated section improves troubleshooting. Optionally, you might consider linking these errors to the specific endpoints where they may occur.


110-125: Authentication Flow Diagram Provides Clear Process Overview
The mermaid sequence diagram effectively visualizes the authentication process, detailing interactions among the client, verification API, passkey service, and Redis. It is important to ensure this diagram remains consistent with any future backend changes.


127-132: Concise Summary of Authentication Steps
The summary following the authentication diagram succinctly outlines the key steps in the authentication process. This clear enumeration reinforces the overall documentation.

apps/web/app/api/passkey/README.md Show resolved Hide resolved
apps/web/app/api/passkey/README.md Show resolved Hide resolved
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: 5

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f4322a2 and fd7091e.

📒 Files selected for processing (2)
  • apps/web/app/api/passkey/README.md (1 hunks)
  • apps/web/lib/passkey/stellar.ts (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
apps/web/app/api/passkey/README.md

11-11: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


15-15: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


17-17: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


29-29: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


33-33: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


35-35: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


47-47: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


51-51: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


53-53: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


65-65: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


69-69: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)


71-71: Fenced code blocks should be surrounded by blank lines
null

(MD031, blanks-around-fences)

🔇 Additional comments (2)
apps/web/app/api/passkey/README.md (2)

88-101: Add alt-text or a textual summary for the registration flow diagram.
This reiterates a past accessibility recommendation to help screen-reader users and those unfamiliar with ASCII/mermaid diagrams.


112-125: Add alt-text or a textual summary for the authentication flow diagram.
Again, repeating a past request for improved accessibility for diagrams.

apps/web/lib/passkey/stellar.ts Show resolved Hide resolved
apps/web/lib/passkey/stellar.ts Show resolved Hide resolved
apps/web/lib/passkey/stellar.ts Show resolved Hide resolved
apps/web/app/api/passkey/README.md Show resolved Hide resolved
AndlerRL
AndlerRL previously approved these changes Feb 2, 2025
Copy link
Member

@AndlerRL AndlerRL left a comment

Choose a reason for hiding this comment

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

LVGTM! Excellent feature to add to the authentication process! It is very valuable to provide documentation ann short code comments in the endpoints and library 👌

I just noticed a build error. After handling that, it will be good to go! 👍

Screenshot_20250202-044543.png

@espaciofuturoio
Copy link
Collaborator Author

@AndlerRL @Bran18 can you check please?

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: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 81396ce and 1d93e73.

📒 Files selected for processing (1)
  • apps/web/lib/passkey/stellar.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
apps/web/lib/passkey/stellar.ts (1)
Learnt from: AndlerRL
PR: kindfi-org/kindfi#109
File: apps/web/lib/passkey/stellar.ts:52-54
Timestamp: 2025-02-02T10:35:42.632Z
Learning: WebAuthn credential public keys can have varying lengths depending on the authenticator, and should not be assumed to be 77 bytes. The length should be parsed from the COSE structure.
🔇 Additional comments (7)
apps/web/lib/passkey/stellar.ts (7)

52-54: Validate credential public key length instead of assuming 77 bytes.
Relying on a fixed length can cause errors for certain authenticators yielding differently sized credential public keys.


90-94: Check for missing public key components.
If -2 or -3 keys are missing in publicKeyObject, calling .get('-2') as Buffer could throw an error. Validate these keys and handle potential undefined values.


107-112: Mismatch between declared curve (secp256k1) and the provided order (P-256).
The comment references secp256k1, but the specified hex corresponds to P-256 (secp256r1). This discrepancy may break signature operations.


117-117: Use throw new Error(...) instead of throwing raw strings.
Throwing strings creates less informative error objects.


125-125: Use throw new Error(...) instead of throwing raw strings.
Same reasoning as above.


146-146: Use throw new Error(...) instead of throwing raw strings.
Same reasoning as above.


157-157: Use throw new Error(...) instead of throwing raw strings.
Same reasoning as above.

apps/web/lib/passkey/stellar.ts Show resolved Hide resolved
apps/web/lib/passkey/stellar.ts Show resolved Hide resolved
Copy link
Contributor

@Bran18 Bran18 left a comment

Choose a reason for hiding this comment

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

Hello @espaciofuturoio everything looks great, but the build is showing the following error:

Screenshot 2025-02-02 at 1 29 47 PM

Can you please take a look at it?

@espaciofuturoio
Copy link
Collaborator Author

@Bran18 those errors are not related to my PR

@Bran18
Copy link
Contributor

Bran18 commented Feb 2, 2025

@Bran18 those errors are not related to my PR

Already fix the issues, let me double check your branch and merge

Copy link
Contributor

@Bran18 Bran18 left a comment

Choose a reason for hiding this comment

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

Hi @espaciofuturoio,

Great job! Thank you so much for assisting us with these changes. We’re really pleased to have you on board and are very impressed by your performance as a new contributor in the Only Dust space and kindFi.

Let’s merge this code that closed issue #64

@Bran18 Bran18 merged commit b606803 into develop Feb 2, 2025
4 of 5 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Feb 5, 2025
JoE11-y pushed a commit to JoE11-y/kindfi that referenced this pull request Feb 5, 2025
* feat(web): add passkey authentication

# Users can authenticate with a simple biometric.

* feat(web): add passkey authentication. close kindfi-org#64

* feat(wip): add passkey authentication

* feat(wip): add passkey authentication

* chore(docs): improve passkey documentation

* chore(docs): improve passkey documentation

* chore(docs): add api errors example

* chore: restore (api-routes) folder

* chore: use @ts-expect-error

* chore: fix ts error

---------

Co-authored-by: Ruben Abarca <[email protected]>
Co-authored-by: Brandon Fernández <[email protected]>
This was referenced Feb 5, 2025
@Bran18 Bran18 linked an issue Feb 7, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature improvement or request webapp web app related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Upgrade Authentication with Passkey Integration System
3 participants