-
Notifications
You must be signed in to change notification settings - Fork 17.3k
feat(api-keys): add API key authentication via FAB SecurityManager #37973
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
Merged
aminghadersohi
merged 59 commits into
apache:master
from
aminghadersohi:amin/ch99414/api-key-auth
Mar 24, 2026
Merged
Changes from all commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
a89eac2
feat(api-keys): add API key authentication via FAB SecurityManager
aminghadersohi e5448fc
fix: also pin FAB in development.txt to feature branch
aminghadersohi fa5f121
fix: correct frontend imports and add ApiKeyApi to CSRF exempt test
aminghadersohi 77308c1
fix: address review feedback from automated code review
aminghadersohi 5f4ae3c
style: prettier formatting for ApiKeyList imports
aminghadersohi 41d1cec
fix: wire ApiKeyList component into UserInfo page
aminghadersohi 7e9f03a
fix(auth): reload API key user with eager relationships
aminghadersohi af5d584
fix: pin FAB dependency to commit hash for reproducible builds
aminghadersohi cebd84d
fix: update FAB pin to latest commit with O(1) lookup and review fixes
aminghadersohi 43827d1
fix: update FAB pin to include black formatting fix
aminghadersohi 2cb3b40
fix: update FAB pin to include HMAC lookup hash fix
aminghadersohi a66803c
fix: update FAB pin to include lint and CodeQL fixes
aminghadersohi 7407e53
fix: update FAB pin to BLAKE2b lookup hash commit
aminghadersohi 8ea1686
fix: update FAB pin to scrypt lookup hash commit
aminghadersohi d729fd3
feat: update FAB dependency to 5.2.0 release
aminghadersohi 69ada07
fix: wrap 'API Keys' string with t() for translation
aminghadersohi 2a6e07f
chore: trigger CI re-run for flaky jest shard
aminghadersohi 149d05a
ci: retrigger CI for flaky jest shard 7
aminghadersohi d7270d6
chore: trigger CI re-run for flaky jest shard
aminghadersohi 91485d4
fix: address review feedback on API key PR
aminghadersohi c7e80ce
ci: retrigger CI after cancelled runs
aminghadersohi 94d1944
refactor: rename prefix variable for clarity in auth error message
aminghadersohi c8511a1
ci: retrigger CI for flaky jest timeout tests
aminghadersohi 7c78f55
ci: retrigger for flaky FileHandler test timeout
aminghadersohi 9e4f29c
chore: retrigger CI
aminghadersohi ad94587
fix(api-keys): update imports to use new @apache-superset/core subpat…
aminghadersohi 5ee00dd
fix: gate API keys behind feature flag and address review feedback
aminghadersohi 2c5fa82
chore: update auto-generated feature-flags.json
aminghadersohi 8788940
fix: restore standalone FAB_API_KEY_ENABLED config and fix CI failures
aminghadersohi 4f9f96f
fix: resolve migration down_revision conflict and move has_request_co…
aminghadersohi a4bd8de
fix(api-keys): simplify useCallback/useEffect pattern in ApiKeyList
aminghadersohi d654e39
chore: re-trigger CI after flaky jest timeouts
aminghadersohi e4bf843
fix(api-keys): add downgrade guard and remove duplicate fetch
aminghadersohi 0be74aa
fix(api-keys): address review feedback on migration, auth, and tests
aminghadersohi 85b6f6d
fix(api-keys): address bot review comments on feature flag, race cond…
aminghadersohi 9837e57
fix(api-keys): fix error swallowing, post-create modal, status badge,…
kgabryje 5527485
test(api-keys): add unit tests for API key auth path in get_user_from…
kgabryje ea8e4ee
fix(api-keys): fix ruff PT001 and formatting in test_auth_api_key
aminghadersohi e7bc8e6
fix(api-keys): fix test fixtures for CI compatibility
aminghadersohi 5a1f1ea
ci: retrigger CI (flaky FileHandler jest timeout)
aminghadersohi 0c90d7c
fix(api-keys): fix setTimeout cleanup and migration index creation
aminghadersohi 153916e
ci: retrigger CI (flaky FileHandler jest timeout)
aminghadersohi 6b1f9f6
fix(api-keys): prevent accidental dismissal of one-time secret modal
aminghadersohi e2785a2
chore: re-trigger CI after flaky FiltersConfigModal jest timeout
aminghadersohi 05c90aa
chore: trigger CI re-run for flaky jest shard
aminghadersohi 328acfb
ci: retrigger CI for flaky jest shard 7
aminghadersohi 979c25e
chore: trigger CI re-run for flaky jest shard
aminghadersohi 6d9b516
ci: retrigger CI after cancelled runs
aminghadersohi dc8eaf9
ci: retrigger CI for flaky jest timeout tests
aminghadersohi dc4cb85
ci: retrigger for flaky FileHandler test timeout
aminghadersohi 1614d80
chore: retrigger CI
aminghadersohi 33d4ce0
chore: re-trigger CI after flaky jest timeouts
aminghadersohi a38f323
ci: retrigger CI (flaky FileHandler jest timeout)
aminghadersohi b51f7fb
ci: retrigger CI (flaky FileHandler jest timeout)
aminghadersohi 89859b8
chore: re-trigger CI after flaky FiltersConfigModal jest timeout
aminghadersohi 0359dad
fix(mcp): address review feedback for API key auth
aminghadersohi b04a415
fix(migration): add SIP-59 compliance notes and explicit FK name
aminghadersohi 9f1b5d1
Revert "fix(migration): add SIP-59 compliance notes and explicit FK n…
aminghadersohi 8b6074b
fix(migration): remove redundant ab_api_key Alembic migration
aminghadersohi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
175 changes: 175 additions & 0 deletions
175
superset-frontend/src/features/apiKeys/ApiKeyCreateModal.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| /** | ||
| * Licensed to the Apache Software Foundation (ASF) under one | ||
| * or more contributor license agreements. See the NOTICE file | ||
| * distributed with this work for additional information | ||
| * regarding copyright ownership. The ASF licenses this file | ||
| * to you 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 | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, | ||
| * software distributed under the License is distributed on an | ||
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| * KIND, either express or implied. See the License for the | ||
| * specific language governing permissions and limitations | ||
| * under the License. | ||
| */ | ||
| import { useEffect, useRef, useState } from 'react'; | ||
| import { SupersetClient } from '@superset-ui/core'; | ||
| import { t } from '@apache-superset/core/translation'; | ||
| import { css, useTheme } from '@apache-superset/core/theme'; | ||
| import { Alert } from '@apache-superset/core/components'; | ||
| import { | ||
| FormModal, | ||
| FormItem, | ||
| Input, | ||
| Button, | ||
| Modal, | ||
| } from '@superset-ui/core/components'; | ||
| import { useToasts } from 'src/components/MessageToasts/withToasts'; | ||
|
|
||
| interface ApiKeyCreateModalProps { | ||
| show: boolean; | ||
| onHide: () => void; | ||
| onSuccess: () => void; | ||
| } | ||
|
|
||
| interface FormValues { | ||
| name: string; | ||
| } | ||
|
|
||
| export function ApiKeyCreateModal({ | ||
| show, | ||
| onHide, | ||
| onSuccess, | ||
| }: ApiKeyCreateModalProps) { | ||
| const theme = useTheme(); | ||
| const { addDangerToast, addSuccessToast } = useToasts(); | ||
| const [createdKey, setCreatedKey] = useState<string | null>(null); | ||
| const [copied, setCopied] = useState(false); | ||
| const copyTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null); | ||
|
|
||
| useEffect( | ||
| () => () => { | ||
| if (copyTimerRef.current) { | ||
| clearTimeout(copyTimerRef.current); | ||
| } | ||
| }, | ||
| [], | ||
| ); | ||
|
|
||
| const handleFormSubmit = async (values: FormValues) => { | ||
| try { | ||
| const response = await SupersetClient.post({ | ||
| endpoint: '/api/v1/security/api_keys/', | ||
| jsonPayload: values, | ||
| }); | ||
| const key = response.json?.result?.key; | ||
| if (!key) { | ||
| throw new Error('API response did not include a key'); | ||
| } | ||
| setCreatedKey(key); | ||
| addSuccessToast(t('API key created successfully')); | ||
| } catch (error) { | ||
| addDangerToast(t('Failed to create API key')); | ||
| throw error; | ||
| } | ||
| }; | ||
|
|
||
| const handleCopyKey = async () => { | ||
| if (!createdKey) { | ||
| return; | ||
| } | ||
| try { | ||
| await navigator.clipboard.writeText(createdKey); | ||
| setCopied(true); | ||
| if (copyTimerRef.current) { | ||
| clearTimeout(copyTimerRef.current); | ||
| } | ||
| copyTimerRef.current = setTimeout(() => setCopied(false), 2000); | ||
| } catch { | ||
| addDangerToast(t('Failed to copy API key to clipboard')); | ||
| } | ||
| }; | ||
|
|
||
| const handleClose = () => { | ||
| if (createdKey) { | ||
| onSuccess(); | ||
| } | ||
| setCreatedKey(null); | ||
| setCopied(false); | ||
| onHide(); | ||
| }; | ||
|
|
||
| if (createdKey) { | ||
| return ( | ||
| <Modal | ||
| show={show} | ||
| onHide={handleClose} | ||
| title={t('API Key Created')} | ||
| maskClosable={false} | ||
| closable={false} | ||
| footer={ | ||
| <Button type="primary" onClick={handleClose}> | ||
| {t('Done')} | ||
| </Button> | ||
| } | ||
| > | ||
| <Alert | ||
| type="warning" | ||
| message={t('Save this API key securely')} | ||
| description={t( | ||
| 'This is the only time you will see this key. Store it securely.', | ||
| )} | ||
| showIcon | ||
| css={css` | ||
| margin-bottom: ${theme.sizeUnit * 4}px; | ||
| `} | ||
| /> | ||
| <div | ||
| css={css` | ||
| display: flex; | ||
| gap: ${theme.sizeUnit * 2}px; | ||
| align-items: center; | ||
| `} | ||
| > | ||
| <Input | ||
| value={createdKey} | ||
| readOnly | ||
| css={css` | ||
| flex: 1; | ||
| font-family: monospace; | ||
| `} | ||
| /> | ||
| <Button onClick={handleCopyKey}> | ||
| {copied ? t('Copied!') : t('Copy')} | ||
| </Button> | ||
| </div> | ||
| </Modal> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <FormModal | ||
| show={show} | ||
| onHide={handleClose} | ||
| title={t('Create API Key')} | ||
| onSave={() => {}} | ||
| formSubmitHandler={handleFormSubmit} | ||
| requiredFields={['name']} | ||
| > | ||
| <FormItem | ||
| name="name" | ||
| label={t('Name')} | ||
| rules={[{ required: true, message: t('API key name is required') }]} | ||
| > | ||
| <Input | ||
| name="name" | ||
| placeholder={t('e.g., CI/CD Pipeline, Analytics Script')} | ||
| /> | ||
| </FormItem> | ||
| </FormModal> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: The one-time secret modal can be dismissed by clicking outside or using the close icon, which can cause users to permanently lose the API key before copying it. Since the key is intentionally shown only once, make this confirmation step non-dismissible except through the explicit
Doneaction. [logic error]Severity Level: Major⚠️
Steps of Reproduction ✅
Prompt for AI Agent 🤖
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 61c8685 — added
maskClosable={false}andclosable={false}to the one-time secret modal so it can only be dismissed via the Done button.