Skip to content

Custom nonce support for backend verification (Supabase, Firebase, custom OIDC)#6

Open
uogbuji wants to merge 1 commit into
NiqueWrld:mainfrom
OoriData:feature/client-controlled-nonce-flow
Open

Custom nonce support for backend verification (Supabase, Firebase, custom OIDC)#6
uogbuji wants to merge 1 commit into
NiqueWrld:mainfrom
OoriData:feature/client-controlled-nonce-flow

Conversation

@uogbuji

@uogbuji uogbuji commented Mar 11, 2026

Copy link
Copy Markdown

Proposed & tested fix for #5

Summary by CodeRabbit

Release Notes

  • New Features

    • Added nonce-enabled sign-in methods for enhanced security in backend token verification
  • Documentation

    • Introduced comprehensive "Backend Verification with Nonce" guide with workflow details and implementation examples

@coderabbitai

coderabbitai Bot commented Mar 11, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds nonce-based backend verification support for the Google Sign-In plugin. It introduces three new public methods for nonce-enabled sign-in flows, implements internal nonce hashing and generation logic, adds the Gradle wrapper script, and includes documentation describing the nonce verification workflow.

Changes

Cohort / File(s) Summary
Documentation
README.md
Adds "Backend Verification with Nonce" section with nonce workflow explanation and example code demonstrating raw nonce generation, nonce-enabled method usage, and backend verification patterns.
Build Configuration
plugin/gradlew
Introduces Unix shell Gradle wrapper script with cross-platform JVM configuration, Java executable resolution, and file descriptor handling for multiple operating systems.
Core Feature Implementation
plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt
Adds three public nonce-enabled sign-in methods (signInWithNonce, signInWithAccountChooserWithNonce, signInWithGoogleButtonWithNonce), implements internal variants to propagate optional raw nonces, adds hashNonce() for SHA-256 hashing, and modifies existing sign-in flows to conditionally use hashed nonces.

Sequence Diagram

sequenceDiagram
    participant Client as Client App
    participant GodotGoogleSignIn as GodotGoogleSignIn
    participant NonceHandler as Nonce Handler
    participant GoogleSignIn as Google Sign-In API
    participant Backend as Backend Server

    Client->>GodotGoogleSignIn: signInWithNonce(rawNonce)
    GodotGoogleSignIn->>NonceHandler: hashNonce(rawNonce)
    NonceHandler-->>GodotGoogleSignIn: hashedNonce (SHA-256)
    GodotGoogleSignIn->>GoogleSignIn: startSignIn(hashedNonce)
    GoogleSignIn-->>GodotGoogleSignIn: idToken
    GodotGoogleSignIn-->>Client: idToken
    Client->>Backend: verify(idToken, rawNonce)
    Backend->>NonceHandler: hashNonce(rawNonce)
    Backend-->>Client: verification result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A nonce arrives, hashed with care,
SHA-256 dancing through the air,
Three new pathways, secure and true,
Backend whispers, "I verify you!"
Sign-in blooms with cryptic grace. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding custom nonce support for backend verification across multiple platforms.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@uogbuji

uogbuji commented Mar 11, 2026

Copy link
Copy Markdown
Author

Closes #5

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt (1)

98-101: Consider validating that rawNonce is non-empty.

The method accepts any String including empty strings. An empty or very short nonce would produce a valid SHA-256 hash but would defeat the security purpose of the nonce (replay protection). Consider adding validation:

🛡️ Optional: Add nonce validation
 `@UsedByGodot`
 fun signInWithNonce(rawNonce: String) {
+    if (rawNonce.isBlank()) {
+        emitSignal(signInFailedSignal.name, "rawNonce must not be empty")
+        return
+    }
     signInInternal(rawNonce)
 }

Similar validation could be added to signInWithAccountChooserWithNonce and signInWithGoogleButtonWithNonce.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt`
around lines 98 - 101, Validate that the incoming rawNonce is non-empty (and
optionally meets a minimum length) before calling signInInternal; in
signInWithNonce check rawNonce.trim().isNotEmpty() and if not, log or throw a
clear error and return without calling signInInternal. Apply the same validation
pattern to signInWithAccountChooserWithNonce and signInWithGoogleButtonWithNonce
to ensure empty/too-short nonces are rejected consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt`:
- Around line 337-341: The hashNonce function currently calls
rawNonce.toByteArray() which relies on the platform default charset; change it
to use an explicit charset (e.g., StandardCharsets.UTF_8) when converting
rawNonce to bytes so hashing is consistent across devices and JVM locales—update
hashNonce to obtain bytes with rawNonce.toByteArray(StandardCharsets.UTF_8)
before passing to MessageDigest.getInstance("SHA-256").digest(...) and keep the
existing hex folding logic unchanged.

---

Nitpick comments:
In
`@plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt`:
- Around line 98-101: Validate that the incoming rawNonce is non-empty (and
optionally meets a minimum length) before calling signInInternal; in
signInWithNonce check rawNonce.trim().isNotEmpty() and if not, log or throw a
clear error and return without calling signInInternal. Apply the same validation
pattern to signInWithAccountChooserWithNonce and signInWithGoogleButtonWithNonce
to ensure empty/too-short nonces are rejected consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d819d4e1-fad3-4d5d-9f92-27f69fb1c53c

📥 Commits

Reviewing files that changed from the base of the PR and between 4ebc10f and 938c56f.

📒 Files selected for processing (4)
  • README.md
  • addons/GodotGoogleSignIn/bin/release/GodotGoogleSignIn-release.aar
  • plugin/gradlew
  • plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt

Comment on lines +337 to 341
private fun hashNonce(rawNonce: String): String {
val bytes = rawNonce.toByteArray()
val md = MessageDigest.getInstance("SHA-256")
val digest = md.digest(bytes)
val digest = MessageDigest.getInstance("SHA-256").digest(bytes)
return digest.fold("") { str, it -> str + "%02x".format(it) }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Specify charset explicitly for consistent hashing across platforms.

toByteArray() without a charset argument uses the platform's default encoding, which can vary across JVMs and locales. This could cause the hash to differ between devices, leading to nonce verification failures on the backend.

🔧 Proposed fix
 private fun hashNonce(rawNonce: String): String {
-    val bytes = rawNonce.toByteArray()
+    val bytes = rawNonce.toByteArray(Charsets.UTF_8)
     val digest = MessageDigest.getInstance("SHA-256").digest(bytes)
     return digest.fold("") { str, it -> str + "%02x".format(it) }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt`
around lines 337 - 341, The hashNonce function currently calls
rawNonce.toByteArray() which relies on the platform default charset; change it
to use an explicit charset (e.g., StandardCharsets.UTF_8) when converting
rawNonce to bytes so hashing is consistent across devices and JVM locales—update
hashNonce to obtain bytes with rawNonce.toByteArray(StandardCharsets.UTF_8)
before passing to MessageDigest.getInstance("SHA-256").digest(...) and keep the
existing hex folding logic unchanged.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds opt-in custom raw-nonce variants to the three sign-in flows so callers can perform backend ID-token verification (Supabase, Firebase, custom OIDC) where the backend needs the raw nonce that corresponds to the hashed nonce claim in the ID token. The internal generateNonce() is refactored to delegate to a new hashNonce(rawNonce) helper, and three new @UsedByGodot methods (signInWithNonce, signInWithAccountChooserWithNonce, signInWithGoogleButtonWithNonce) wrap private *Internal methods that accept a nullable raw nonce. README is updated with the new API rows and a new "Backend Verification with Nonce" section including a GDScript example.

Changes:

  • Add three nonce-accepting sign-in methods and refactor existing flows to share *Internal helpers that hash the supplied raw nonce instead of generating one.
  • Extract a hashNonce() helper from generateNonce() for SHA-256 hex hashing.
  • Document the new API and a Supabase-style backend verification flow in README.md.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

File Description
plugin/src/main/kotlin/com/niquewrld/casino/googlesignin/GodotGoogleSignIn.kt Adds signIn*WithNonce variants and *Internal helpers; refactors nonce generation to reuse hashNonce.
README.md Documents the new methods and adds a backend-verification-with-nonce guide and example.
plugin/gradlew Adds a gradlew script that is the standard Gradle wrapper template but with the upstream copyright header replaced by a personal/company copyright — unrelated to this PR.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugin/gradlew
Comment on lines +3 to +9
# © 2026 Uche Ogbuji (uche@oori.dev), Oori Data LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
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