Merge pull request #684 from 2underscores/dcr-fallback-fix
Fix: Pre-registered Client ID as fallback to DCR
This commit is contained in:
commit
a30e0d1fda
2 changed files with 106 additions and 5 deletions
|
|
@ -442,6 +442,103 @@ describe("AuthDebugger", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Client Registration behavior", () => {
|
||||||
|
it("uses preregistered (static) client information without calling DCR", async () => {
|
||||||
|
const preregClientInfo = {
|
||||||
|
client_id: "static_client_id",
|
||||||
|
client_secret: "static_client_secret",
|
||||||
|
redirect_uris: ["http://localhost:3000/oauth/callback/debug"],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return preregistered client info for the server-specific key
|
||||||
|
sessionStorageMock.getItem.mockImplementation((key) => {
|
||||||
|
if (
|
||||||
|
key ===
|
||||||
|
`[${defaultProps.serverUrl}] ${SESSION_KEYS.PREREGISTERED_CLIENT_INFORMATION}`
|
||||||
|
) {
|
||||||
|
return JSON.stringify(preregClientInfo);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateAuthState = jest.fn();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
renderAuthDebugger({
|
||||||
|
updateAuthState,
|
||||||
|
authState: {
|
||||||
|
...defaultAuthState,
|
||||||
|
isInitiatingAuth: false,
|
||||||
|
oauthStep: "client_registration",
|
||||||
|
oauthMetadata: mockOAuthMetadata as unknown as OAuthMetadata,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Proceed from client_registration → authorization_redirect
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByText("Continue"));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Should NOT attempt dynamic client registration
|
||||||
|
expect(mockRegisterClient).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
// Should advance with the preregistered client info
|
||||||
|
expect(updateAuthState).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
oauthClientInfo: expect.objectContaining({
|
||||||
|
client_id: "static_client_id",
|
||||||
|
}),
|
||||||
|
oauthStep: "authorization_redirect",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to DCR when no static client information is available", async () => {
|
||||||
|
// No preregistered or dynamic client info present in session storage
|
||||||
|
sessionStorageMock.getItem.mockImplementation(() => null);
|
||||||
|
|
||||||
|
// DCR returns a new client
|
||||||
|
mockRegisterClient.mockResolvedValueOnce(mockOAuthClientInfo);
|
||||||
|
|
||||||
|
const updateAuthState = jest.fn();
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
renderAuthDebugger({
|
||||||
|
updateAuthState,
|
||||||
|
authState: {
|
||||||
|
...defaultAuthState,
|
||||||
|
isInitiatingAuth: false,
|
||||||
|
oauthStep: "client_registration",
|
||||||
|
oauthMetadata: mockOAuthMetadata as unknown as OAuthMetadata,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
fireEvent.click(screen.getByText("Continue"));
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockRegisterClient).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
// Should save and advance with the DCR client info
|
||||||
|
expect(updateAuthState).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
oauthClientInfo: expect.objectContaining({
|
||||||
|
client_id: "test_client_id",
|
||||||
|
}),
|
||||||
|
oauthStep: "authorization_redirect",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify the dynamically registered client info was persisted
|
||||||
|
expect(sessionStorage.setItem).toHaveBeenCalledWith(
|
||||||
|
`[${defaultProps.serverUrl}] ${SESSION_KEYS.CLIENT_INFORMATION}`,
|
||||||
|
expect.any(String),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("OAuth State Persistence", () => {
|
describe("OAuth State Persistence", () => {
|
||||||
it("should store auth state to sessionStorage before redirect in Quick OAuth Flow", async () => {
|
it("should store auth state to sessionStorage before redirect in Quick OAuth Flow", async () => {
|
||||||
const updateAuthState = jest.fn();
|
const updateAuthState = jest.fn();
|
||||||
|
|
|
||||||
|
|
@ -89,12 +89,16 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
clientMetadata.scope = scopesSupported.join(" ");
|
clientMetadata.scope = scopesSupported.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
const fullInformation = await registerClient(context.serverUrl, {
|
// Try Static client first, with DCR as fallback
|
||||||
metadata,
|
let fullInformation = await context.provider.clientInformation();
|
||||||
clientMetadata,
|
if (!fullInformation) {
|
||||||
});
|
fullInformation = await registerClient(context.serverUrl, {
|
||||||
|
metadata,
|
||||||
|
clientMetadata,
|
||||||
|
});
|
||||||
|
context.provider.saveClientInformation(fullInformation);
|
||||||
|
}
|
||||||
|
|
||||||
context.provider.saveClientInformation(fullInformation);
|
|
||||||
context.updateState({
|
context.updateState({
|
||||||
oauthClientInfo: fullInformation,
|
oauthClientInfo: fullInformation,
|
||||||
oauthStep: "authorization_redirect",
|
oauthStep: "authorization_redirect",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue