ui feat fixes

This commit is contained in:
Ishaan Jaffer 2026-02-09 15:49:50 -08:00
parent 4f12a0f517
commit 9ff9134cf1
4 changed files with 390 additions and 247 deletions

View file

@ -0,0 +1,151 @@
import React from "react";
import { Form, Select, Tooltip } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { Button, TextInput } from "@tremor/react";
import { OAUTH_FLOW } from "./types";
interface OAuthFlowStatus {
startOAuthFlow: () => void;
status: string;
error: string | null;
tokenResponse: { access_token?: string; expires_in?: number } | null;
}
interface OAuthFormFieldsProps {
isM2M: boolean;
isEditing?: boolean;
oauthFlow?: OAuthFlowStatus;
initialFlowType?: string;
}
const fieldClassName = "rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500";
const FieldLabel: React.FC<{ label: string; tooltip: string }> = ({ label, tooltip }) => (
<span className="text-sm font-medium text-gray-700 flex items-center">
{label}
<Tooltip title={tooltip}>
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
);
const OAuthFormFields: React.FC<OAuthFormFieldsProps> = ({
isM2M,
isEditing = false,
oauthFlow,
initialFlowType,
}) => {
const placeholderSuffix = isEditing ? " (leave blank to keep existing)" : "";
return (
<>
<Form.Item
label={<span className="text-sm font-medium text-gray-700">OAuth Flow Type</span>}
name="oauth_flow_type"
{...(initialFlowType ? { initialValue: initialFlowType } : {})}
>
<Select className="rounded-lg" size="large">
<Select.Option value={OAUTH_FLOW.INTERACTIVE}>Interactive (PKCE)</Select.Option>
<Select.Option value={OAUTH_FLOW.M2M}>Machine-to-Machine (M2M)</Select.Option>
</Select>
</Form.Item>
{isM2M ? (
<>
<Form.Item
label={<FieldLabel label="Client ID" tooltip="OAuth2 client ID for the client_credentials grant." />}
name={["credentials", "client_id"]}
rules={[{ required: true, message: "Client ID is required for M2M OAuth" }]}
>
<TextInput type="password" placeholder={`Enter OAuth client ID${placeholderSuffix}`} className={fieldClassName} />
</Form.Item>
<Form.Item
label={<FieldLabel label="Client Secret" tooltip="OAuth2 client secret for the client_credentials grant." />}
name={["credentials", "client_secret"]}
rules={[{ required: true, message: "Client Secret is required for M2M OAuth" }]}
>
<TextInput type="password" placeholder={`Enter OAuth client secret${placeholderSuffix}`} className={fieldClassName} />
</Form.Item>
<Form.Item
label={<FieldLabel label="Token URL" tooltip="Token endpoint URL for the client_credentials grant." />}
name="token_url"
rules={[{ required: true, message: "Token URL is required for M2M OAuth" }]}
>
<TextInput placeholder="https://auth.example.com/oauth/token" className={fieldClassName} />
</Form.Item>
<Form.Item
label={<FieldLabel label="Scopes (optional)" tooltip="Optional scopes to request with the client_credentials grant." />}
name={["credentials", "scopes"]}
>
<Select mode="tags" tokenSeparators={[","]} placeholder="Add scopes" className="rounded-lg" size="large" />
</Form.Item>
</>
) : (
<>
<Form.Item
label={<FieldLabel label="OAuth Client ID (optional)" tooltip="Provide only if your MCP server cannot handle dynamic client registration." />}
name={["credentials", "client_id"]}
>
<TextInput type="password" placeholder={`Enter OAuth client ID${placeholderSuffix}`} className={fieldClassName} />
</Form.Item>
<Form.Item
label={<FieldLabel label="OAuth Client Secret (optional)" tooltip="Provide only if your MCP server cannot handle dynamic client registration." />}
name={["credentials", "client_secret"]}
>
<TextInput type="password" placeholder={`Enter OAuth client secret${placeholderSuffix}`} className={fieldClassName} />
</Form.Item>
<Form.Item
label={<FieldLabel label="OAuth Scopes (optional)" tooltip="Optional scopes requested during token exchange. Separate multiple scopes with enter or commas." />}
name={["credentials", "scopes"]}
>
<Select mode="tags" tokenSeparators={[","]} placeholder="Add scopes" className="rounded-lg" size="large" />
</Form.Item>
<Form.Item
label={<FieldLabel label="Authorization URL Override (optional)" tooltip="Optional override for the authorization endpoint." />}
name="authorization_url"
>
<TextInput placeholder="https://example.com/oauth/authorize" className={fieldClassName} />
</Form.Item>
<Form.Item
label={<FieldLabel label="Token URL Override (optional)" tooltip="Optional override for the token endpoint." />}
name="token_url"
>
<TextInput placeholder="https://example.com/oauth/token" className={fieldClassName} />
</Form.Item>
<Form.Item
label={<FieldLabel label="Registration URL Override (optional)" tooltip="Optional override for the dynamic client registration endpoint." />}
name="registration_url"
>
<TextInput placeholder="https://example.com/oauth/register" className={fieldClassName} />
</Form.Item>
{oauthFlow && (
<div className="rounded-lg border border-dashed border-gray-300 p-4 space-y-2">
<p className="text-sm text-gray-600">
Use OAuth to fetch a fresh access token and temporarily save it in the session as the authentication value.
</p>
<Button
variant="secondary"
onClick={oauthFlow.startOAuthFlow}
disabled={oauthFlow.status === "authorizing" || oauthFlow.status === "exchanging"}
>
{oauthFlow.status === "authorizing"
? "Waiting for authorization..."
: oauthFlow.status === "exchanging"
? "Exchanging authorization code..."
: "Authorize & Fetch Token"}
</Button>
{oauthFlow.error && <p className="text-sm text-red-500">{oauthFlow.error}</p>}
{oauthFlow.status === "success" && oauthFlow.tokenResponse?.access_token && (
<p className="text-sm text-green-600">
Token fetched. Expires in {oauthFlow.tokenResponse.expires_in ?? "?"} seconds.
</p>
)}
</div>
)}
</>
)}
</>
);
};
export default OAuthFormFields;

View file

@ -3,7 +3,8 @@ import { Modal, Tooltip, Form, Select, Input } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { Button, TextInput } from "@tremor/react";
import { createMCPServer } from "../networking";
import { AUTH_TYPE, MCPServer, MCPServerCostInfo } from "./types";
import { AUTH_TYPE, OAUTH_FLOW, MCPServer, MCPServerCostInfo } from "./types";
import OAuthFormFields from "./OAuthFormFields";
import MCPServerCostConfig from "./mcp_server_cost_config";
import MCPConnectionStatus from "./mcp_connection_status";
import MCPToolConfiguration from "./mcp_tool_configuration";
@ -52,6 +53,8 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
const authType = formValues.auth_type as string | undefined;
const shouldShowAuthValueField = authType ? AUTH_TYPES_REQUIRING_AUTH_VALUE.includes(authType) : false;
const isOAuthAuthType = authType === AUTH_TYPE.OAUTH2;
const isM2MFlow = isOAuthAuthType && formValues.oauth_flow_type === OAUTH_FLOW.M2M;
const isInteractiveFlow = isOAuthAuthType && formValues.oauth_flow_type !== OAUTH_FLOW.M2M;
const persistCreateUiState = () => {
if (typeof window === "undefined") {
@ -561,131 +564,16 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
)}
{transportType !== "stdio" && isOAuthAuthType && (
<>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client ID (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_id"]}
>
<TextInput
type="password"
placeholder="Enter OAuth client ID"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client Secret (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_secret"]}
>
<TextInput
type="password"
placeholder="Enter OAuth client secret"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Scopes (optional)
<Tooltip title="Optional scopes requested during token exchange. Separate multiple scopes with enter or commas.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "scopes"]}
>
<Select
mode="tags"
tokenSeparators={[","]}
placeholder="Add scopes"
className="rounded-lg"
size="large"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Authorization URL Override (optional)
<Tooltip title="Optional override for the authorization endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="authorization_url"
>
<TextInput
placeholder="https://example.com/oauth/authorize"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Token URL Override (optional)
<Tooltip title="Optional override for the token endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="token_url"
>
<TextInput
placeholder="https://example.com/oauth/token"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Registration URL Override (optional)
<Tooltip title="Optional orverride for the dynamic client registration endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="registration_url"
>
<TextInput
placeholder="https://example.com/oauth/register"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<div className="rounded-lg border border-dashed border-gray-300 p-4 space-y-2">
<p className="text-sm text-gray-600">
Use OAuth to fetch a fresh access token and temporarily save it in the session as the authentication value.
</p>
<Button
variant="secondary"
onClick={startOAuthFlow}
disabled={oauthStatus === "authorizing" || oauthStatus === "exchanging"}
>
{oauthStatus === "authorizing"
? "Waiting for authorization..."
: oauthStatus === "exchanging"
? "Exchanging authorization code..."
: "Authorize & Fetch Token"}
</Button>
{oauthError && <p className="text-sm text-red-500">{oauthError}</p>}
{oauthStatus === "success" && oauthTokenResponse?.access_token && (
<p className="text-sm text-green-600">
Token fetched. Expires in {oauthTokenResponse.expires_in ?? "?"} seconds.
</p>
)}
</div>
</>
<OAuthFormFields
isM2M={isM2MFlow}
initialFlowType={OAUTH_FLOW.INTERACTIVE}
oauthFlow={{
startOAuthFlow,
status: oauthStatus,
error: oauthError,
tokenResponse: oauthTokenResponse,
}}
/>
)}
{/* Stdio Configuration - only show for stdio transport */}

View file

@ -2,7 +2,8 @@ import React, { useState, useEffect } from "react";
import { Form, Select, Button as AntdButton, Tooltip } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { Button, TextInput, TabGroup, TabList, Tab, TabPanels, TabPanel } from "@tremor/react";
import { AUTH_TYPE, MCPServer, MCPServerCostInfo } from "./types";
import { AUTH_TYPE, OAUTH_FLOW, MCPServer, MCPServerCostInfo } from "./types";
import OAuthFormFields from "./OAuthFormFields";
import { updateMCPServer, testMCPToolsListRequest } from "../networking";
import MCPServerCostConfig from "./mcp_server_cost_config";
import MCPPermissionManagement from "./MCPPermissionManagement";
@ -41,7 +42,10 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
const authType = Form.useWatch("auth_type", form) as string | undefined;
const shouldShowAuthValueField = authType ? AUTH_TYPES_REQUIRING_AUTH_VALUE.includes(authType) : false;
const isOAuthAuthType = authType === AUTH_TYPE.OAUTH2;
const oauthFlowTypeValue = Form.useWatch("oauth_flow_type", form) as string | undefined;
const isM2MFlow = isOAuthAuthType && oauthFlowTypeValue === OAUTH_FLOW.M2M;
const isInteractiveFlow = isOAuthAuthType && oauthFlowTypeValue !== OAUTH_FLOW.M2M;
const [oauthAccessToken, setOauthAccessToken] = useState<string | null>(null);
const persistEditUiState = () => {
@ -128,6 +132,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
() => ({
...mcpServer,
static_headers: initialStaticHeaders,
oauth_flow_type: mcpServer.token_url ? OAUTH_FLOW.M2M : OAUTH_FLOW.INTERACTIVE,
}),
[mcpServer, initialStaticHeaders],
);
@ -214,7 +219,8 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
return;
}
if (mcpServer.auth_type === AUTH_TYPE.OAUTH2 && !oauthAccessToken) {
const isM2M = mcpServer.auth_type === AUTH_TYPE.OAUTH2 && !!mcpServer.token_url;
if (mcpServer.auth_type === AUTH_TYPE.OAUTH2 && !isM2M && !oauthAccessToken) {
return;
}
@ -454,126 +460,219 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
{isOAuthAuthType && (
<>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client ID (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_id"]}
label={<span className="text-sm font-medium text-gray-700">OAuth Flow Type</span>}
name="oauth_flow_type"
>
<TextInput
type="password"
placeholder="Enter OAuth client ID (leave blank to keep existing)"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
<Select className="rounded-lg" size="large">
<Select.Option value={OAUTH_FLOW.INTERACTIVE}>Interactive (PKCE)</Select.Option>
<Select.Option value={OAUTH_FLOW.M2M}>Machine-to-Machine (M2M)</Select.Option>
</Select>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client Secret (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_secret"]}
>
<TextInput
type="password"
placeholder="Enter OAuth client secret (leave blank to keep existing)"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Scopes (optional)
<Tooltip title="Add scopes to override the default scope list used for this MCP server.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "scopes"]}
>
<Select
mode="tags"
tokenSeparators={[","]}
placeholder="Add scopes"
className="rounded-lg"
size="large"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Authorization URL Override (optional)
<Tooltip title="Optional override for the authorization endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="authorization_url"
>
<TextInput
placeholder="https://example.com/oauth/authorize"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Token URL Override (optional)
<Tooltip title="Optional override for the token endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="token_url"
>
<TextInput
placeholder="https://example.com/oauth/token"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Registration URL Override (optional)
<Tooltip title="Optional override for the dynamic client registration endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="registration_url"
>
<TextInput
placeholder="https://example.com/oauth/register"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<div className="rounded-lg border border-dashed border-gray-300 p-4 space-y-2">
<p className="text-sm text-gray-600">Use OAuth to fetch a fresh access token and temporarily save it in the session as the authentication value.</p>
<Button
variant="secondary"
onClick={startOAuthFlow}
disabled={oauthStatus === "authorizing" || oauthStatus === "exchanging"}
>
{oauthStatus === "authorizing"
? "Waiting for authorization..."
: oauthStatus === "exchanging"
? "Exchanging authorization code..."
: "Authorize & Fetch Token"}
</Button>
{oauthError && <p className="text-sm text-red-500">{oauthError}</p>}
{oauthStatus === "success" && oauthTokenResponse?.access_token && (
<p className="text-sm text-green-600">
Token fetched. Expires in {oauthTokenResponse.expires_in ?? "?"} seconds.
</p>
)}
</div>
{/* M2M fields: client_id, client_secret, token_url required; scopes optional */}
{isM2MFlow && (
<>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Client ID
<Tooltip title="OAuth2 client ID for the client_credentials grant.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_id"]}
rules={[{ required: true, message: "Client ID is required for M2M OAuth" }]}
>
<TextInput
type="password"
placeholder="Enter OAuth client ID (leave blank to keep existing)"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Client Secret
<Tooltip title="OAuth2 client secret for the client_credentials grant.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_secret"]}
rules={[{ required: true, message: "Client Secret is required for M2M OAuth" }]}
>
<TextInput
type="password"
placeholder="Enter OAuth client secret (leave blank to keep existing)"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Token URL
<Tooltip title="Token endpoint URL for the client_credentials grant.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="token_url"
rules={[{ required: true, message: "Token URL is required for M2M OAuth" }]}
>
<TextInput
placeholder="https://auth.example.com/oauth/token"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Scopes (optional)
<Tooltip title="Optional scopes to request with the client_credentials grant.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "scopes"]}
>
<Select
mode="tags"
tokenSeparators={[","]}
placeholder="Add scopes"
className="rounded-lg"
size="large"
/>
</Form.Item>
</>
)}
{/* Interactive (PKCE) fields: all optional, plus authorize button */}
{isInteractiveFlow && (
<>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client ID (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_id"]}
>
<TextInput
type="password"
placeholder="Enter OAuth client ID (leave blank to keep existing)"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Client Secret (optional)
<Tooltip title="Provide only if your MCP server cannot handle dynamic client registration.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "client_secret"]}
>
<TextInput
type="password"
placeholder="Enter OAuth client secret (leave blank to keep existing)"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
OAuth Scopes (optional)
<Tooltip title="Add scopes to override the default scope list used for this MCP server.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name={["credentials", "scopes"]}
>
<Select
mode="tags"
tokenSeparators={[","]}
placeholder="Add scopes"
className="rounded-lg"
size="large"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Authorization URL Override (optional)
<Tooltip title="Optional override for the authorization endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="authorization_url"
>
<TextInput
placeholder="https://example.com/oauth/authorize"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Token URL Override (optional)
<Tooltip title="Optional override for the token endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="token_url"
>
<TextInput
placeholder="https://example.com/oauth/token"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<Form.Item
label={
<span className="text-sm font-medium text-gray-700 flex items-center">
Registration URL Override (optional)
<Tooltip title="Optional override for the dynamic client registration endpoint.">
<InfoCircleOutlined className="ml-2 text-blue-400 hover:text-blue-600 cursor-help" />
</Tooltip>
</span>
}
name="registration_url"
>
<TextInput
placeholder="https://example.com/oauth/register"
className="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500"
/>
</Form.Item>
<div className="rounded-lg border border-dashed border-gray-300 p-4 space-y-2">
<p className="text-sm text-gray-600">Use OAuth to fetch a fresh access token and temporarily save it in the session as the authentication value.</p>
<Button
variant="secondary"
onClick={startOAuthFlow}
disabled={oauthStatus === "authorizing" || oauthStatus === "exchanging"}
>
{oauthStatus === "authorizing"
? "Waiting for authorization..."
: oauthStatus === "exchanging"
? "Exchanging authorization code..."
: "Authorize & Fetch Token"}
</Button>
{oauthError && <p className="text-sm text-red-500">{oauthError}</p>}
{oauthStatus === "success" && oauthTokenResponse?.access_token && (
<p className="text-sm text-green-600">
Token fetched. Expires in {oauthTokenResponse.expires_in ?? "?"} seconds.
</p>
)}
</div>
</>
)}
</>
)}

View file

@ -13,6 +13,11 @@ export const AUTH_TYPE = {
OAUTH2: "oauth2",
};
export const OAUTH_FLOW = {
INTERACTIVE: "interactive",
M2M: "m2m",
};
export const TRANSPORT = {
SSE: "sse",
HTTP: "http",