You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The dashboard UI automatically hides the revoke button for non-revocable keys.
557
557
558
+
### Public Keys (Viewable Tokens)
559
+
560
+
#### The Problem: Non-Revocable Key Lockout
561
+
562
+
Non-revocable keys create a potential UX nightmare: if a user creates a publishable key, doesn't copy it immediately, and closes the pageāthey're locked out. The token is gone forever (we only store the hash), and they can't delete the key to create a new one (it's non-revocable). They're stuck with a useless key slot they can never use or remove.
563
+
564
+
This is especially problematic when combined with `limit: 1`, which restricts users to a single publishable key per environment. A user who loses their token would be permanently locked out of creating publishable keys.
565
+
566
+
#### The Solution: Storing Public Keys
567
+
568
+
For publishable keysāwhich are *designed* to be embedded in client-side code and distributed appsāthere's no security benefit to hiding the token. These keys are meant to be public! Stripe, for example, lets you view your publishable key anytime in the dashboard.
569
+
570
+
The `public: true` option stores the plaintext token in metadata so users can view it again:
571
+
572
+
```ruby
573
+
config.key_types = {
574
+
publishable: {
575
+
prefix:"pk",
576
+
permissions:%w[read validate],
577
+
revocable:false,
578
+
public:true, # Store token for later viewing
579
+
limit:1
580
+
},
581
+
secret: {
582
+
prefix:"sk",
583
+
permissions::all
584
+
# public: false (default) - NEVER store secret keys!
585
+
}
586
+
}
587
+
```
588
+
589
+
#### Security: Why This is Safe
590
+
591
+
> [!IMPORTANT]
592
+
> The `public` option only works when BOTH conditions are met:
593
+
> -`public: true` is set in the key type configuration
594
+
> -`revocable: false` is set (non-revocable keys only)
595
+
596
+
This double-check is a deliberate safety measure:
597
+
598
+
1.**Secret keys are NEVER stored** ā Even if you accidentally set `public: true` on a secret key type, the gem checks for `revocable: false` as well. Secret keys are revocable by default, so they're protected.
599
+
600
+
2.**Revocable keys are NEVER stored** ā If a key can be revoked, users can always delete it and create a new one. There's no lockout risk, so no need to store the token.
601
+
602
+
3.**Only truly public keys are stored** ā Publishable keys with limited permissions, designed for client-side embedding, are the only keys that get stored. These tokens provide no security benefit when hiddenāthey're meant to be distributed.
603
+
604
+
> [!WARNING]
605
+
> ā ļø **Never set `public: true` on secret keys or any key type with sensitive permissions.** The gem prevents this by requiring `revocable: false`, but you should also never configure it that way.
606
+
607
+
When a key is public, the dashboard shows a "Show" button to reveal the full token:
608
+
609
+
```ruby
610
+
pk = user.create_api_key!(key_type::publishable)
611
+
pk.public_key_type? # => true
612
+
pk.viewable_token # => "pk_test_abc123..." (the full token)
613
+
614
+
sk = user.create_api_key!(key_type::secret)
615
+
sk.public_key_type? # => false
616
+
sk.viewable_token # => nil (not stored)
617
+
```
618
+
558
619
### Environment Isolation
559
620
560
621
With `strict_environment_isolation = true`, keys can only authenticate in their matching environment:
Copy file name to clipboardExpand all lines: app/views/api_keys/keys/_show_token.html.erb
+5-1Lines changed: 5 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,11 @@
3
3
4
4
<h2>Save your key</h2>
5
5
6
-
<p>Please save your secret key in a safe place since <strong>you won't be able to view it again</strong>. Keep it secure, as anyone with your API key can make requests on your behalf. If you do lose it, you'll need to generate a new one.</p>
6
+
<%ifapi_key.public_key_type?%>
7
+
<p>Here's your <%=api_key.key_type.humanize.downcase%> key. This key is designed to be embedded in client-side applications. You can view it again anytime from your dashboard.</p>
8
+
<%else%>
9
+
<p>Please save your API key in a safe place since <strong>you won't be able to view it again</strong>. Keep it secure, as anyone with your API key can make requests on your behalf. If you lose it, you'll need to generate a new one.</p>
0 commit comments