Skip to content

Commit a476a76

Browse files
committed
Clarify secret revocation timing and add types for the regenerate mutation
Motivation: The documentation of token secret regeneration claims the old secret is revoked immediately, but the revocation may take a short time to be propagated to the authorization cache. The new webapp mutation and the secret modal state were also untyped. Modifications: - Reword the Javadoc and the authentication documentation to note that the propagation of the revocation to the authorization cache may take a short time. - Type the regenerate mutation response and the secret modal state with `AppIdentityDto`. Result: - The documentation matches the actual revocation timing and the regenerate flow is type-checked.
1 parent 8cd8286 commit a476a76

5 files changed

Lines changed: 13 additions & 8 deletions

File tree

server/src/main/java/com/linecorp/centraldogma/server/internal/api/sysadmin/AppIdentityRegistryService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ public CompletableFuture<AppIdentity> updateAppIdentity(ServiceRequestContext ct
251251
/**
252252
* POST /appIdentities/{appId}/secret
253253
*
254-
* <p>Regenerates the secret of the token of the specified {@code appId}. The old secret is revoked
255-
* immediately and the token with a newly-generated secret is returned.
254+
* <p>Regenerates the secret of the token of the specified {@code appId} and returns the token with
255+
* a newly-generated secret. The old secret is revoked in the same commit, but it may take a short
256+
* time for the revocation to be propagated to the authorization cache.
256257
*/
257258
@Post("/appIdentities/{appId}/secret")
258259
public CompletableFuture<Token> regenerateTokenSecret(ServiceRequestContext ctx,

server/src/main/java/com/linecorp/centraldogma/server/metadata/MetadataService.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,15 +1167,17 @@ public CompletableFuture<Revision> deactivateToken(Author author, String appId)
11671167

11681168
/**
11691169
* Regenerates the secret of the {@link Token} of the specified {@code appId} and returns the
1170-
* {@link Token} with the newly-generated secret. The old secret is revoked immediately.
1170+
* {@link Token} with the newly-generated secret. The old secret is revoked in the same commit,
1171+
* but it may take a short time for the revocation to be propagated to the authorization cache.
11711172
*/
11721173
public CompletableFuture<Token> regenerateTokenSecret(Author author, String appId) {
11731174
return appIdentityService.regenerateTokenSecret(author, appId);
11741175
}
11751176

11761177
/**
11771178
* Regenerates the secret of the {@link Token} of the specified {@code appId} and returns the
1178-
* {@link Token} with the newly-generated secret. The old secret is revoked immediately.
1179+
* {@link Token} with the newly-generated secret. The old secret is revoked in the same commit,
1180+
* but it may take a short time for the revocation to be propagated to the authorization cache.
11791181
* The regeneration fails with a {@link ChangeConflictException} if the token's creation metadata
11801182
* does not match {@code expectedCreation}, which prevents rotating a token that was recreated
11811183
* with the same application ID after the caller was authorized.

site/src/sphinx/auth.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,9 @@ creator and the system administrator are allowed to deactivate, remove and/or re
370370

371371
If the secret of a token is leaked, the token creator or a system administrator can regenerate the secret
372372
with the ``Regenerate secret`` button of the web UI or ``POST /api/v1/appIdentities/{appId}/secret``.
373-
The old secret is revoked immediately and a newly-generated secret is issued to the same application ID,
374-
so the roles and permissions granted to the token are preserved.
373+
The old secret is revoked and a newly-generated secret is issued to the same application ID, so the roles
374+
and permissions granted to the token are preserved. Note that it may take a short time for the revocation
375+
to be propagated to the authorization cache of each server.
375376

376377
There are two levels of a token, which are ``System Admin`` and ``User``. ``System Admin`` level token can be
377378
created by only the system administrators. A client who sends a request with the token is allowed to access

webapp/src/dogma/features/api/apiSlice.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ export const apiSlice = createApi({
367367
}),
368368
invalidatesTags: ['AppIdentity'],
369369
}),
370-
regenerateAppIdentitySecret: builder.mutation({
370+
regenerateAppIdentitySecret: builder.mutation<AppIdentityDto, { appId: string }>({
371371
query: ({ appId }) => ({
372372
url: `/api/v1/appIdentities/${appId}/secret`,
373373
method: 'POST',

webapp/src/dogma/features/app-identity/RegenerateAppIdentitySecret.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
useDisclosure,
1313
} from '@chakra-ui/react';
1414
import { apiSlice, useRegenerateAppIdentitySecretMutation } from 'dogma/features/api/apiSlice';
15+
import { AppIdentityDto } from 'dogma/features/app-identity/AppIdentity';
1516
import { DisplaySecretModal } from 'dogma/features/app-identity/DisplaySecretModal';
1617
import { newNotification } from 'dogma/features/notification/notificationSlice';
1718
import ErrorMessageParser from 'dogma/features/services/ErrorMessageParser';
@@ -28,7 +29,7 @@ export const RegenerateAppIdentitySecret = ({ appId, hidden }: { appId: string;
2829
} = useDisclosure();
2930
const dispatch = useAppDispatch();
3031
const [regenerateSecret, { isLoading, reset }] = useRegenerateAppIdentitySecretMutation();
31-
const [appIdentityDetail, setAppIdentityDetail] = useState(null);
32+
const [appIdentityDetail, setAppIdentityDetail] = useState<AppIdentityDto | null>(null);
3233
const mounted = useRef(true);
3334
const invalidationPending = useRef(false);
3435
useEffect(() => {

0 commit comments

Comments
 (0)