Skip to content

RFE-9481: Add copy-to-clipboard on OAuth token display page#243

Draft
hjaiswal12 wants to merge 1 commit into
openshift:masterfrom
hjaiswal12:RFE-9481-copy-to-clipboard
Draft

RFE-9481: Add copy-to-clipboard on OAuth token display page#243
hjaiswal12 wants to merge 1 commit into
openshift:masterfrom
hjaiswal12:RFE-9481-copy-to-clipboard

Conversation

@hjaiswal12

@hjaiswal12 hjaiswal12 commented Jun 30, 2026

Copy link
Copy Markdown

Summary

Adds Copy to clipboard buttons on the OAuth token display page (/oauth/token/display) for:

  • API token
  • oc login --token=... --server=... command
  • curl example for direct API use

Motivation

Users currently must manually select and copy text after Display Token. This adds one-click copy while keeping the existing security flow.

Security

  • Display Token POST + CSRF flow is unchanged (required for CVE mitigation).
  • Copy happens only on explicit button click (no auto-copy on page load).
  • Copy text is passed via HTML-escaped data-copy-text attributes (not inline JS string interpolation).

Test plan

  • go test ./pkg/server/tokenrequest/...
  • Manual cluster validation (skipped by author; recommend reviewer verify on a dev cluster)

Files changed

  • pkg/server/tokenrequest/tokenrequest.go — copy UI + helpers
  • pkg/server/tokenrequest/tokenrequest_test.go — template, escaping, CSRF tests

Summary by CodeRabbit

  • New Features

    • Added copyable commands alongside the access token display, including an oc login command and a direct curl request.
    • Improved the token screen with clipboard copy controls for easier reuse.
  • Bug Fixes

    • Updated copy behavior to handle special characters safely and avoid malformed copied content.
    • Added validation so invalid requests and unsupported methods return the appropriate errors.
  • Tests

    • Added coverage for command generation, token rendering, copy controls, escaping, and request validation.

Add copy buttons for the API token, oc login command, and curl example
after the existing Display Token step. Copy text is exposed via escaped
data attributes and copied only on explicit user click.

Co-authored-by: Cursor <cursoragent@cursor.com>
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 30, 2026
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 30, 2026
@openshift-ci-robot

openshift-ci-robot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

@hjaiswal12: This pull request references RFE-9481 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the feature request to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

Adds Copy to clipboard buttons on the OAuth token display page (/oauth/token/display) for:

  • API token
  • oc login --token=... --server=... command
  • curl example for direct API use

Motivation

Users currently must manually select and copy text after Display Token. This adds one-click copy while keeping the existing security flow.

Security

  • Display Token POST + CSRF flow is unchanged (required for CVE mitigation).
  • Copy happens only on explicit button click (no auto-copy on page load).
  • Copy text is passed via HTML-escaped data-copy-text attributes (not inline JS string interpolation).

Test plan

  • go test ./pkg/server/tokenrequest/...
  • Manual cluster validation (skipped by author; recommend reviewer verify on a dev cluster)

Files changed

  • pkg/server/tokenrequest/tokenrequest.go — copy UI + helpers
  • pkg/server/tokenrequest/tokenrequest_test.go — template, escaping, CSRF tests

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Walkthrough

Adds formatOcLoginCommand and formatCurlCommand helpers to tokenrequest.go, extends tokenData with OcLoginCommand and CurlCommand fields, updates the HTML template and embedded CSS/JS to render copy-to-clipboard buttons for all three values, and adds a new test file covering the formatters, template rendering, and HTTP handler edge cases.

Changes

Token page copy-to-clipboard commands

Layer / File(s) Summary
Command formatters, tokenData fields, and template/asset updates
pkg/server/tokenrequest/tokenrequest.go
Adds formatOcLoginCommand and formatCurlCommand helpers (trimming trailing slashes for the curl URL), extends tokenData with OcLoginCommand/CurlCommand fields, adds copyToClipboardScript with clipboard API and fallback, updates CSS for copy buttons, and updates tokenTemplate HTML to render copy buttons for the API token and the two new command strings.
Test suite for formatters, rendering, and HTTP handlers
pkg/server/tokenrequest/tokenrequest_test.go
New test file covering exact output of formatOcLoginCommand and formatCurlCommand, renderToken copy control presence and data-copy-text values, HTML escaping of special characters in copy attributes, error-state omission of copy controls, renderForm unchanged behavior, displayTokenPost CSRF rejection (400), and displayToken method rejection (405).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding copy-to-clipboard controls on the OAuth token display page.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed The added tests use static Go Test... names only; no Ginkgo titles, t.Run names, or dynamic identifiers were found.
Test Structure And Quality ✅ Passed PASS: The added tests are plain unit tests, not Ginkgo; they avoid cluster ops/timeouts, use t.Fatalf with clear messages, and follow existing package style.
Microshift Test Compatibility ✅ Passed Added tests are plain Go unit tests (testing/httptest), not Ginkgo e2e specs, and they use no MicroShift-unsupported OpenShift APIs.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; tokenrequest_test.go uses Go's testing package and the PR only changes OAuth token UI/unit tests.
Topology-Aware Scheduling Compatibility ✅ Passed Changes only affect the OAuth token display page and tests; no manifests, controllers, or scheduling constraints were added.
Ote Binary Stdout Contract ✅ Passed No main/init/TestMain/BeforeSuite/RunSpecs code or stdout prints were added; the only logging is handler-level klog in existing request code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The PR adds only standard Go unit tests in pkg/server/tokenrequest/tokenrequest_test.go; no Ginkgo/e2e tests, IPv4-only logic, or external connectivity are present.
No-Weak-Crypto ✅ Passed No weak crypto, custom crypto, or secret/token comparisons were added; changes are limited to UI copy helpers and tests.
Container-Privileges ✅ Passed No container/K8s manifest changes or privilege flags were introduced; the PR only touches tokenrequest Go code and tests.
No-Sensitive-Data-In-Logs ✅ Passed No new sensitive-data logging was added; the PR only adds copy UI/helpers, and tests cover escaping and CSRF behavior.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@openshift-ci openshift-ci Bot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Jun 30, 2026
@openshift-ci

openshift-ci Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Hi @hjaiswal12. Thanks for your PR.

I'm waiting for a openshift member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci

openshift-ci Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: hjaiswal12
Once this PR has been reviewed and has the lgtm label, please assign rh-roman for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/server/tokenrequest/tokenrequest.go`:
- Around line 302-314: The rendered command examples in tokenTemplate are
drifting from the copied text because the curl example is rebuilt from
PublicMasterURL instead of using the preformatted CurlCommand, while the login
example already uses OcLoginCommand. Update the template to render the same
command strings used for the copy buttons so the visible examples always match
the copied content, and verify the curl output stays normalized when
PublicMasterURL has a trailing slash.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: eeddc6b0-ed6c-463c-b36d-0ecbf080a1af

📥 Commits

Reviewing files that changed from the base of the PR and between 96045f0 and fe5691a.

📒 Files selected for processing (2)
  • pkg/server/tokenrequest/tokenrequest.go
  • pkg/server/tokenrequest/tokenrequest_test.go

Comment on lines 302 to 314
var tokenTemplate = template.Must(template.New("tokenTemplate").Parse(
cssStyle + `
{{ if .Error }}
{{ .Error }}
{{ else }}
<h2>Your API token is</h2>
<h2 class="copy-heading">Your API token is <button type="button" class="copy-button" data-copy-text="{{.AccessToken}}" aria-label="Copy to clipboard">Copy to clipboard</button></h2>
<code>{{.AccessToken}}</code>

<h2>Log in with this token</h2>
<h2 class="copy-heading">Log in with this token <button type="button" class="copy-button" data-copy-text="{{.OcLoginCommand}}" aria-label="Copy to clipboard">Copy to clipboard</button></h2>
<pre>oc login <span class="nowrap">--token={{.AccessToken}}</span> <span class="nowrap">--server={{.PublicMasterURL}}</span></pre>

<h3>Use this token directly against the API</h3>
<h3 class="copy-heading">Use this token directly against the API <button type="button" class="copy-button" data-copy-text="{{.CurlCommand}}" aria-label="Copy to clipboard">Copy to clipboard</button></h3>
<pre>curl <span class="nowrap">-H "Authorization: Bearer {{.AccessToken}}"</span> <span class="nowrap">"{{.PublicMasterURL}}/apis/user.openshift.io/v1/users/~"</span></pre>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the rendered command examples identical to the copied text.

formatCurlCommand() normalizes a trailing slash, but Line 314 rebuilds the visible curl example from PublicMasterURL instead of CurlCommand. If the configured server URL ends with /, the button copies the normalized command while the on-page example shows //apis/.... Rendering the preformatted fields here avoids that drift for both commands.

Suggested fix
-  <pre>oc login <span class="nowrap">--token={{.AccessToken}}</span> <span class="nowrap">--server={{.PublicMasterURL}}</span></pre>
+  <pre>{{.OcLoginCommand}}</pre>
 
   <h3 class="copy-heading">Use this token directly against the API <button type="button" class="copy-button" data-copy-text="{{.CurlCommand}}" aria-label="Copy to clipboard">Copy to clipboard</button></h3>
-  <pre>curl <span class="nowrap">-H "Authorization: Bearer {{.AccessToken}}"</span> <span class="nowrap">"{{.PublicMasterURL}}/apis/user.openshift.io/v1/users/~"</span></pre>
+  <pre>{{.CurlCommand}}</pre>
📝 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.

Suggested change
var tokenTemplate = template.Must(template.New("tokenTemplate").Parse(
cssStyle + `
{{ if .Error }}
{{ .Error }}
{{ else }}
<h2>Your API token is</h2>
<h2 class="copy-heading">Your API token is <button type="button" class="copy-button" data-copy-text="{{.AccessToken}}" aria-label="Copy to clipboard">Copy to clipboard</button></h2>
<code>{{.AccessToken}}</code>
<h2>Log in with this token</h2>
<h2 class="copy-heading">Log in with this token <button type="button" class="copy-button" data-copy-text="{{.OcLoginCommand}}" aria-label="Copy to clipboard">Copy to clipboard</button></h2>
<pre>oc login <span class="nowrap">--token={{.AccessToken}}</span> <span class="nowrap">--server={{.PublicMasterURL}}</span></pre>
<h3>Use this token directly against the API</h3>
<h3 class="copy-heading">Use this token directly against the API <button type="button" class="copy-button" data-copy-text="{{.CurlCommand}}" aria-label="Copy to clipboard">Copy to clipboard</button></h3>
<pre>curl <span class="nowrap">-H "Authorization: Bearer {{.AccessToken}}"</span> <span class="nowrap">"{{.PublicMasterURL}}/apis/user.openshift.io/v1/users/~"</span></pre>
var tokenTemplate = template.Must(template.New("tokenTemplate").Parse(
cssStyle + `
{{ if .Error }}
{{ .Error }}
{{ else }}
<h2 class="copy-heading">Your API token is <button type="button" class="copy-button" data-copy-text="{{.AccessToken}}" aria-label="Copy to clipboard">Copy to clipboard</button></h2>
<code>{{.AccessToken}}</code>
<h2 class="copy-heading">Log in with this token <button type="button" class="copy-button" data-copy-text="{{.OcLoginCommand}}" aria-label="Copy to clipboard">Copy to clipboard</button></h2>
<pre>{{.OcLoginCommand}}</pre>
<h3 class="copy-heading">Use this token directly against the API <button type="button" class="copy-button" data-copy-text="{{.CurlCommand}}" aria-label="Copy to clipboard">Copy to clipboard</button></h3>
<pre>{{.CurlCommand}}</pre>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/server/tokenrequest/tokenrequest.go` around lines 302 - 314, The rendered
command examples in tokenTemplate are drifting from the copied text because the
curl example is rebuilt from PublicMasterURL instead of using the preformatted
CurlCommand, while the login example already uses OcLoginCommand. Update the
template to render the same command strings used for the copy buttons so the
visible examples always match the copied content, and verify the curl output
stays normalized when PublicMasterURL has a trailing slash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants