Skip to content
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

add more verbose logs for auth #25

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/browser/sync/authentication_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ export class AuthenticationManager {
// in that we pause the WebSocket so that mutations
// don't retry with bad auth.
private async tryToReauthenticate(serverMessage: AuthError) {
this._logVerbose(
`trying to reauthenticate: ${JSON.stringify(serverMessage)}`,
);
// We only retry once, to avoid infinite retries
if (
// No way to fetch another token, kaboom
Expand Down Expand Up @@ -374,9 +377,13 @@ export class AuthenticationManager {
},
) {
const originalConfigVersion = ++this.configVersion;
this._logVerbose("fetching auth token");
const token = await fetchToken(fetchArgs);
if (this.configVersion !== originalConfigVersion) {
// This is a stale config
this._logVerbose(
`stale config version, expected ${originalConfigVersion}`,
);
return { isFromOutdatedConfig: true };
}
return { isFromOutdatedConfig: false, value: token };
Expand All @@ -386,6 +393,7 @@ export class AuthenticationManager {
this.resetAuthState();
// Bump this in case we are mid-token-fetch when we get stopped
this.configVersion++;
this._logVerbose(`config version bumped`);
}

private setAndReportAuthFailed(
Expand All @@ -400,6 +408,17 @@ export class AuthenticationManager {
}

private setAuthState(newAuth: AuthState) {
const authStateForLog =
newAuth.state === "waitingForServerConfirmationOfFreshToken"
? {
...newAuth,
token: `...${newAuth.token.slice(-5)}`,
}
: newAuth;
this._logVerbose(
`setting auth state to ${JSON.stringify(authStateForLog)}`,
);

if (this.authState.state === "waitingForScheduledRefetch") {
clearTimeout(this.authState.refetchTokenTimeoutId);

Expand Down
44 changes: 36 additions & 8 deletions src/browser/sync/web_socket_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@ export class WebSocketManager {
this.connect();
}

private setSocketState(state: Socket) {
this.socket = state;
this._logVerbose(
`socket state changed: ${this.socket.state}, paused: ${
"paused" in this.socket ? this.socket.paused : undefined
}`,
);
}

private connect() {
if (this.socket.state === "terminated") {
return;
Expand All @@ -173,11 +182,11 @@ export class WebSocketManager {

const ws = new this.webSocketConstructor(this.uri);
this._logVerbose("constructed WebSocket");
this.socket = {
this.setSocketState({
state: "connecting",
ws,
paused: "no",
};
});

// Kick off server inactivity timer before WebSocket connection is established
// so we can detect cases where handshake fails.
Expand All @@ -190,11 +199,11 @@ export class WebSocketManager {
if (this.socket.state !== "connecting") {
throw new Error("onopen called with socket not in connecting state");
}
this.socket = {
this.setSocketState({
state: "ready",
ws,
paused: this.socket.paused === "yes" ? "uninitialized" : "no",
};
});
this.resetServerInactivityTimeout();
if (this.socket.paused === "no") {
this.onOpen({
Expand Down Expand Up @@ -259,8 +268,14 @@ export class WebSocketManager {
* @returns Whether the message (might have been) sent.
*/
sendMessage(message: ClientMessage) {
this._logVerbose(`sending message with type ${message.type}`);

const messageForLog = {
type: message.type,
...(message.type === "Authenticate" && message.tokenType === "User"
? {
value: `...${message.value.slice(-5)}`,
}
: {}),
};
if (this.socket.state === "ready" && this.socket.paused === "no") {
const encodedMessage = encodeClientMessage(message);
const request = JSON.stringify(encodedMessage);
Expand All @@ -273,8 +288,19 @@ export class WebSocketManager {
this.closeAndReconnect("FailedToSendMessage");
}
// We are not sure if this was sent or not.
this._logVerbose(
`sent message with type ${message.type}: ${JSON.stringify(
messageForLog,
)}`,
);
return true;
}
this._logVerbose(
`message not sent (socket state: ${this.socket.state}, paused: ${"paused" in this.socket ? this.socket.paused : undefined}): ${JSON.stringify(
messageForLog,
)}`,
);

return false;
}

Expand Down Expand Up @@ -305,7 +331,9 @@ export class WebSocketManager {
* This should be used when we hit an error and would like to restart the session.
*/
private closeAndReconnect(closeReason: string) {
this._logVerbose(`begin closeAndReconnect with reason ${closeReason}`);
this._logVerbose(
`begin closeAndReconnect with reason ${closeReason}, socket state: ${this.socket.state}`,
);
switch (this.socket.state) {
case "disconnected":
case "terminated":
Expand Down Expand Up @@ -388,7 +416,7 @@ export class WebSocketManager {
case "connecting":
case "ready": {
const result = this.close();
this.socket = { state: "terminated" };
this.setSocketState({ state: "terminated" });
return result;
}
default: {
Expand Down
2 changes: 2 additions & 0 deletions src/react-auth0/ConvexProviderWithAuth0.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import React from "react";
import { ReactNode, useCallback, useMemo } from "react";
import { AuthTokenFetcher } from "../browser/sync/client.js";
import { ConvexProviderWithAuth } from "../react/ConvexAuthState.js";
import { Logger } from "../browser/logging.js";

// Until we can import from our own entry points (requires TypeScript 4.7),
// just describe the interface enough to help users pass the right type.
type IConvexReactClient = {
setAuth(fetchToken: AuthTokenFetcher): void;
clearAuth(): void;
logger: Logger;
};

/**
Expand Down
2 changes: 2 additions & 0 deletions src/react-clerk/ConvexProviderWithClerk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import React from "react";
import { ReactNode, useCallback, useMemo } from "react";
import { AuthTokenFetcher } from "../browser/sync/client.js";
import { ConvexProviderWithAuth } from "../react/ConvexAuthState.js";
import { Logger } from "../browser/logging.js";

// Until we can import from our own entry points (requires TypeScript 4.7),
// just describe the interface enough to help users pass the right type.
type IConvexReactClient = {
setAuth(fetchToken: AuthTokenFetcher): void;
clearAuth(): void;
logger: Logger;
};

// https://clerk.com/docs/reference/clerk-react/useauth
Expand Down
25 changes: 25 additions & 0 deletions src/react/ConvexAuthState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React, {
} from "react";
import { AuthTokenFetcher } from "../browser/sync/client.js";
import { ConvexProvider } from "./client.js";
import { Logger } from "../browser/logging.js";

// Until we can import from our own entry points (requires TypeScript 4.7),
// just describe the interface enough to help users pass the right type.
Expand All @@ -16,6 +17,7 @@ type IConvexReactClient = {
onChange: (isAuthenticated: boolean) => void,
): void;
clearAuth(): void;
logger: Logger;
};

/**
Expand Down Expand Up @@ -113,6 +115,29 @@ export function ConvexProviderWithAuth({
setIsConvexAuthenticated(false);
}

useEffect(() => {
client.logger.logVerbose(
"auth state changed",
JSON.stringify(
{
authProviderLoading,
authProviderAuthenticated,
isConvexAuthenticated,
isLoading: isConvexAuthenticated === null,
isAuthenticated:
authProviderAuthenticated && (isConvexAuthenticated ?? false),
},
null,
2,
),
);
}, [
authProviderLoading,
authProviderAuthenticated,
isConvexAuthenticated,
client.logger,
]);

return (
<ConvexAuthContext.Provider
value={{
Expand Down