Skip to content

fix(auth): explain invalid scopes in auth login#427

Open
cookier wants to merge 2 commits intolarksuite:mainfrom
cookier:fix/auth-login-invalid-scope-diagnostics
Open

fix(auth): explain invalid scopes in auth login#427
cookier wants to merge 2 commits intolarksuite:mainfrom
cookier:fix/auth-login-invalid-scope-diagnostics

Conversation

@cookier
Copy link
Copy Markdown

@cookier cookier commented Apr 11, 2026

Summary

Improve lark-cli auth login --scope error reporting when device authorization fails because the requested scope list contains invalid entries.

Instead of only surfacing the upstream OAuth error, this change diagnoses the requested scope list locally and reports:

  • unknown scopes
  • scopes that are known but not enabled for the current app
  • close suggestions for malformed scope names

Changes

  • hook invalid-scope diagnostics into the device authorization failure path
  • add login_scope_validation.go to analyze requested scopes against known registry scopes and currently enabled app scopes
  • add focused tests for unknown scope detection, suggestion output, and non-scope error pass-through

Test Plan

  • go test ./cmd/auth -run 'TestDiagnoseRequestedScopes_UnknownAndDisabled|TestExplainScopeRequestError_FormatsDetailedValidation|TestExplainScopeRequestError_IgnoresOtherErrors'
  • go test ./cmd/auth

Note: the full ./cmd/auth package currently still hits a pre-existing failure in TestAuthLoginRun_MissingRequestedScopeAlignsWithLoginSuccess related to strict mode / log file cleanup on this machine. The new #416-focused tests pass.

Related Issues

Closes #416

Summary by CodeRabbit

  • New Features

    • Improved authentication error diagnostics: when device authorization fails due to scope issues, users receive detailed messages listing unknown or not-enabled OAuth scopes, suggested corrections, and guidance to check app scopes.
  • Tests

    • Added tests covering scope diagnosis, formatted error messages, and fallback behaviors when app-scope lookup succeeds or fails.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 11, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 11, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2c27f675-16fb-4e9a-98f9-8ab4bb3f8f72

📥 Commits

Reviewing files that changed from the base of the PR and between 1644069 and ea800fe.

📒 Files selected for processing (3)
  • cmd/auth/login.go
  • cmd/auth/login_scope_validation.go
  • cmd/auth/login_scope_validation_test.go
✅ Files skipped from review due to trivial changes (1)
  • cmd/auth/login_scope_validation.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/auth/login.go

📝 Walkthrough

Walkthrough

Adds scope-diagnostic logic and tests that detect unknown or app-disabled OAuth scopes during device authorization errors and returns a detailed, user-facing auth error instead of the prior generic message.

Changes

Cohort / File(s) Summary
Login Error Handler
cmd/auth/login.go
On device authorization failure, call explainScopeRequestError(...) and return its formatted auth error when it provides diagnostics; otherwise keep existing generic error.
Scope Validation Logic
cmd/auth/login_scope_validation.go
New scope-diagnosis implementation: detects "invalid or malformed scope" errors, tokenizes requested scopes, compares against known scopes (registry + shortcut scopes), checks app-enabled scopes via loadAppInfo, generates fuzzy suggestions, and formats multi-line auth errors for unknown/disabled scopes.
Validation Tests
cmd/auth/login_scope_validation_test.go
New unit tests covering diagnosis of unknown/disabled scopes, suggestion generation, formatted error output, non-diagnostic passthrough, and app-info lookup failure guidance.

Sequence Diagram

sequenceDiagram
    participant LoginCmd as Login Command
    participant ScopeValidator as Scope Validator
    participant AppInfo as App Info Loader
    participant Registry as Scope Registry

    LoginCmd->>LoginCmd: RequestDeviceAuthorization(requestedScopes)
    LoginCmd-->>LoginCmd: receives error ("invalid or malformed scope")
    LoginCmd->>ScopeValidator: explainScopeRequestError(err, requestedScopes, config)
    alt error matches scope-validation pattern
        ScopeValidator->>AppInfo: loadAppInfo(config.AppID)
        AppInfo-->>ScopeValidator: enabled scopes or error
        ScopeValidator->>Registry: CollectAllScopesFromMeta("user")
        Registry-->>ScopeValidator: known scopes
        ScopeValidator->>ScopeValidator: diagnoseRequestedScopes(requestedScopes, known, enabled)
        ScopeValidator->>ScopeValidator: suggestScopes(...) and format message
        ScopeValidator-->>LoginCmd: *output.ExitError (auth) with diagnostics*
    else other error
        ScopeValidator-->>LoginCmd: nil (no special handling)
    end
    LoginCmd->>LoginCmd: return formatted auth error or fallback error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size/S

Suggested reviewers

  • liangshuo-1

Poem

🐰 I hopped through scopes at break of day,

Sniffed the unknown and chased errors away.
I nudge suggestions, three at most—hooray!
Now logins smile and troubles sway. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix(auth): explain invalid scopes in auth login' clearly and concisely describes the main change: improving error messages when invalid scopes are provided to auth login.
Description check ✅ Passed The PR description provides a clear summary, detailed changes, test plan with evidence of some tests running, and links the related issue #416.
Linked Issues check ✅ Passed The PR directly addresses issue #416 by adding scope diagnostics that identify unknown scopes, disabled scopes, and suggestions for malformed names—matching the requirement to provide detailed reasons when authorization fails.
Out of Scope Changes check ✅ Passed All changes are directly related to the objective: hooking diagnostics into device authorization failure, adding scope validation logic, and adding corresponding tests.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@github-actions github-actions bot added the size/L Large or sensitive change across domains or core paths label Apr 11, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 11, 2026

Greptile Summary

This PR adds scope-error diagnostics to auth login: when device authorization fails with an invalid-scope signal, the new explainScopeRequestError function inspects the requested scope list against the known registry and the app's enabled scopes, emitting per-scope messages with close suggestions. The hook in login.go is minimal and correct.

  • The fallback path (lines 47–55 of login_scope_validation.go) discards the original Lark API error, so users lose the raw message that triggered diagnostics — worth preserving alongside the app-info lookup failure.
  • Three of the four new tests implicitly require specific scopes (\"base:app:create\", \"base:view:write_only\") to be present in knownUserScopes() (the live registry), making them fragile under registry churn; the unit test for diagnoseRequestedScopes correctly avoids this by injecting a fixed known map directly.

Confidence Score: 5/5

Safe to merge; all remaining findings are P2 quality improvements that do not affect correctness.

The core logic for detecting and explaining invalid scopes is correct. The login.go change is minimal. Both P2 findings (dropping original error in fallback message, test coupling to live registry) are improvement suggestions that do not cause wrong behavior in production scenarios. No P0/P1 issues were found.

cmd/auth/login_scope_validation.go (fallback path drops original error); cmd/auth/login_scope_validation_test.go (three tests couple to live registry data)

Important Files Changed

Filename Overview
cmd/auth/login.go Adds a 3-line hook that calls explainScopeRequestError before falling through to the generic ErrAuth; the change is minimal and correctly short-circuits only on non-nil diagnostic returns.
cmd/auth/login_scope_validation.go New diagnostic module; logic for unknown/disabled scope detection and prefix-based suggestions is sound, but the fallback path drops the original request error and isInvalidScopeError's broader heuristic can false-positive on general auth messages that happen to mention scope + invalid.
cmd/auth/login_scope_validation_test.go Unit tests for diagnoseRequestedScopes are well-isolated; integration tests for explainScopeRequestError implicitly depend on specific scopes (e.g. base:app:create) existing in the live registry, making them fragile under registry changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["RequestDeviceAuthorization fails"] --> B["explainScopeRequestError called"]
    B --> C{"isInvalidScopeError?"}
    C -- No --> D["return nil\n(caller shows generic ErrAuth)"]
    C -- Yes --> E["loadAppInfo to get enabled scopes"]
    E --> F{"Info returned OK?"}
    F -- Yes --> G["enabled = app's user scopes map"]
    F -- No --> H["appInfoErr = err\nenabled = nil"]
    G --> I["diagnoseRequestedScopes\n(against known registry + enabled)"]
    H --> I
    I --> J{"Unknown or\nNotEnabled > 0?"}
    J -- Yes --> K["Build per-scope error lines\n(with suggestions)\nreturn ErrAuth"]
    J -- No --> L{"appInfoErr != nil?"}
    L -- Yes --> M["return ErrAuth:\n'could not be fully diagnosed'\n(original requestErr dropped)"]
    L -- No --> N["return nil\n(caller shows generic ErrAuth)"]
Loading

Reviews (3): Last reviewed commit: "fix(auth): tighten invalid-scope diagnos..." | Re-trigger Greptile

Copy link
Copy Markdown

@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

🧹 Nitpick comments (1)
cmd/auth/login_scope_validation_test.go (1)

46-71: Add one test that exercises the app-enabled-scope branch.

Current assertions validate unknown/suggestion formatting, but there’s no case proving NotEnabled diagnostics when app info fetch succeeds. Please add a mocked getAppInfo success path and assert the “scope not enabled for current app” line.

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

In `@cmd/auth/login_scope_validation_test.go` around lines 46 - 71, Add a new unit
test that covers the app-enabled-scope branch of explainScopeRequestError by
mocking getAppInfo to return a successful app info (so diagnostics of type
NotEnabled are produced) and asserting the returned error message contains the
"scope not enabled for current app" / "not enabled for this app" hint; locate
and update the test file with a new test (similar to
TestExplainScopeRequestError_FormatsDetailedValidation) that calls
explainScopeRequestError with a scope that will trigger NotEnabled diagnostics,
inject a TestFactory or mock that overrides getAppInfo to succeed, and add
assertions that the error string includes the NotEnabled message and any related
"lark-cli auth scopes" hint.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/auth/login_scope_validation.go`:
- Around line 33-44: The current logic skips disabled-scope detection when
getAppInfo(ctx, f, config.AppID) fails (enabled stays nil), which can cause
known-but-disabled scopes to be treated as valid; change the code so that when
getAppInfo returns an error or nil info you still initialize enabled as an empty
map (e.g., enabled = make(map[string]bool, 0)) before calling
diagnoseRequestedScopes(requestedScope, knownUserScopes(), enabled) so
diagnoseReportedScopes can correctly populate NotEnabled; optionally log the
getAppInfo error for diagnostics but do not let a lookup failure short-circuit
scope validation.

---

Nitpick comments:
In `@cmd/auth/login_scope_validation_test.go`:
- Around line 46-71: Add a new unit test that covers the app-enabled-scope
branch of explainScopeRequestError by mocking getAppInfo to return a successful
app info (so diagnostics of type NotEnabled are produced) and asserting the
returned error message contains the "scope not enabled for current app" / "not
enabled for this app" hint; locate and update the test file with a new test
(similar to TestExplainScopeRequestError_FormatsDetailedValidation) that calls
explainScopeRequestError with a scope that will trigger NotEnabled diagnostics,
inject a TestFactory or mock that overrides getAppInfo to succeed, and add
assertions that the error string includes the NotEnabled message and any related
"lark-cli auth scopes" hint.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 13d0b7aa-8497-4e0a-9ec6-d4f2cedee9a0

📥 Commits

Reviewing files that changed from the base of the PR and between 1ff2dc5 and 5c04149.

📒 Files selected for processing (3)
  • cmd/auth/login.go
  • cmd/auth/login_scope_validation.go
  • cmd/auth/login_scope_validation_test.go

Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
cmd/auth/login_scope_validation.go (1)

37-44: ⚠️ Potential issue | 🟡 Minor

Treat a nil app-info result as an inspection failure.

If loadAppInfo returns info == nil with err == nil, both enabled and appInfoErr stay nil. In that state, disabled-scope inspection is skipped and this helper can still fall back to the generic auth error instead of the detailed scope diagnostics.

💡 Proposed fix
 	if info, err := loadAppInfo(ctx, f, config.AppID); err == nil && info != nil {
 		enabled = make(map[string]bool, len(info.UserScopes))
 		for _, scope := range info.UserScopes {
 			enabled[scope] = true
 		}
-	} else {
+	} else if err != nil {
 		appInfoErr = err
+	} else {
+		appInfoErr = fmt.Errorf("enabled app scopes could not be inspected automatically")
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/auth/login_scope_validation.go` around lines 37 - 44, When calling
loadAppInfo, handle the case where err==nil but info==nil by treating it as a
failure: if info is nil set appInfoErr to a non-nil error (e.g.,
fmt.Errorf("loadAppInfo returned nil info for app %s", config.AppID)) so the
later disabled-scope inspection runs; keep the existing population of enabled
only when info != nil and err == nil, and ensure you reference loadAppInfo,
info, enabled and appInfoErr in the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@cmd/auth/login_scope_validation.go`:
- Around line 37-44: When calling loadAppInfo, handle the case where err==nil
but info==nil by treating it as a failure: if info is nil set appInfoErr to a
non-nil error (e.g., fmt.Errorf("loadAppInfo returned nil info for app %s",
config.AppID)) so the later disabled-scope inspection runs; keep the existing
population of enabled only when info != nil and err == nil, and ensure you
reference loadAppInfo, info, enabled and appInfoErr in the fix.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6203a25d-56d5-4629-9a2f-5581ce527cfc

📥 Commits

Reviewing files that changed from the base of the PR and between 5c04149 and 1644069.

📒 Files selected for processing (2)
  • cmd/auth/login_scope_validation.go
  • cmd/auth/login_scope_validation_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/auth/login_scope_validation_test.go

@cookier cookier force-pushed the fix/auth-login-invalid-scope-diagnostics branch from 1644069 to ea800fe Compare April 12, 2026 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

授权失败的时候希望能给详细的列表原因

2 participants