fix(auth): add user billing dependency spans (#1948)
This commit is contained in:
@@ -599,8 +599,56 @@ class AccessController {
|
||||
return { ok: true, actor: session.user, session: publicSession(session), authMethod: AUTH_METHOD_WEB_SESSION };
|
||||
}
|
||||
|
||||
async authenticateUserBillingToken(secret) {
|
||||
const result = await this.userBilling.introspect(secret);
|
||||
async withAuthOtelDependencySpan(name, otelContext, parentSpanId, attributes, fn, classifyResult = null) {
|
||||
const spanId = otelContext ? newOtelSpanId() : "";
|
||||
const startedAtMs = Date.now();
|
||||
let statusCode = 0;
|
||||
let errorCode = "";
|
||||
try {
|
||||
const result = await fn();
|
||||
const classified = typeof classifyResult === "function" ? classifyResult(result) : null;
|
||||
statusCode = Number(classified?.statusCode ?? 0);
|
||||
errorCode = textOr(classified?.errorCode, "");
|
||||
return result;
|
||||
} catch (error) {
|
||||
statusCode = Number(error?.statusCode ?? error?.status ?? 503);
|
||||
errorCode = textOr(error?.code, `${name.replace(/[^A-Za-z0-9]+/g, "_")}_exception`);
|
||||
throw error;
|
||||
} finally {
|
||||
if (otelContext) {
|
||||
void emitAuthOtelSpan(name, otelContext, this.env, {
|
||||
spanId,
|
||||
parentSpanId: parentSpanId || otelContext.rootSpanId,
|
||||
kind: 3,
|
||||
startTimeMs: startedAtMs,
|
||||
endTimeMs: Date.now(),
|
||||
status: errorCode ? "error" : "ok",
|
||||
error: errorCode ? new Error(errorCode) : null,
|
||||
attributes: {
|
||||
...attributes,
|
||||
...(statusCode > 0 ? { "http.status_code": statusCode } : {}),
|
||||
...(errorCode ? { "error.code": errorCode } : {}),
|
||||
"auth.trace_visible": true,
|
||||
"auth.values_redacted": true
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async authenticateUserBillingToken(secret, otel = null) {
|
||||
const otelContext = otel?.context ?? null;
|
||||
const parentSpanId = textOr(otel?.parentSpanId, "");
|
||||
const result = await this.withAuthOtelDependencySpan("auth.user_billing.introspect", otelContext, parentSpanId, {
|
||||
"http.method": "POST",
|
||||
"http.route": "/internal/auth/introspect",
|
||||
"server.address": "hwlab-user-billing",
|
||||
"user_billing.service_id": "hwlab-user-billing",
|
||||
"user_billing.operation": "introspect"
|
||||
}, () => this.userBilling.introspect(secret), (item) => ({
|
||||
statusCode: Number(item?.status ?? 0),
|
||||
errorCode: item?.ok ? "" : textOr(item?.error?.code, "user_billing_introspect_failed")
|
||||
}));
|
||||
if (!result.ok) {
|
||||
return errorPayload(result.error?.code ?? "user_billing_introspect_failed", result.error?.message ?? "user-billing introspection failed", result.status ?? 503);
|
||||
}
|
||||
@@ -609,7 +657,11 @@ class AccessController {
|
||||
}
|
||||
const principal = result.body.principal;
|
||||
const actor = userBillingActor(principal);
|
||||
const synced = await this.store.upsertExternalUser?.({ ...actor, authProvider: "user-billing", email: principal.email, now: this.now() }) ?? actor;
|
||||
const synced = await this.withAuthOtelDependencySpan("auth.local.upsert_external_user", otelContext, parentSpanId, {
|
||||
"db.system": "postgresql",
|
||||
"db.sql.table": "users",
|
||||
"auth.operation": "upsert_external_user"
|
||||
}, async () => await this.store.upsertExternalUser?.({ ...actor, authProvider: "user-billing", email: principal.email, now: this.now() }) ?? actor);
|
||||
const authMethod = principal.authType === "session" ? AUTH_METHOD_USER_BILLING_SESSION : AUTH_METHOD_USER_BILLING_API_KEY;
|
||||
return {
|
||||
ok: true,
|
||||
@@ -944,11 +996,16 @@ class AccessController {
|
||||
};
|
||||
}
|
||||
const upstreamToken = textOr(login.body.token, "");
|
||||
const auth = await this.authenticateUserBillingToken(upstreamToken);
|
||||
const auth = await this.authenticateUserBillingToken(upstreamToken, otelContext ? { context: otelContext, parentSpanId: spanId } : null);
|
||||
if (!auth.ok) {
|
||||
thrownCode = textOr(auth?.error?.code, "user_billing_introspect_failed");
|
||||
return { ok: false, status: auth.status, error: auth.error };
|
||||
}
|
||||
const localSession = await this.issueWebSessionForActor(auth.actor);
|
||||
const localSession = await this.withAuthOtelDependencySpan("auth.local.issue_web_session", otelContext, spanId, {
|
||||
"db.system": "postgresql",
|
||||
"db.sql.table": "sessions",
|
||||
"auth.operation": "issue_web_session"
|
||||
}, () => this.issueWebSessionForActor(auth.actor));
|
||||
const localAuth = {
|
||||
ok: true,
|
||||
actor: auth.actor,
|
||||
|
||||
Reference in New Issue
Block a user