feat(site): add query param support to OAuth2 app creation page (#21821)

## Summary

Adds support for pre-filling the OAuth2 application creation form via
URL query parameters.

## Query Parameters

| Parameter | Description |
|-----------|-------------|
| `name` | Pre-fills the "Application name" field |
| `callback_url` | Pre-fills the "Callback URL" field |
| `icon` | Pre-fills the "Application icon" field |

## Example

```
/deployment/oauth2-provider/apps/add?name=MyApp&callback_url=https://example.com/callback&icon=/icon/github.svg
```

This allows external tools or documentation to link directly to the
OAuth2 app creation page with pre-populated values.

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
This commit is contained in:
blinkagent[bot]
2026-02-02 03:56:38 +00:00
committed by GitHub
co-authored by blink-so[bot]
parent b052a79929
commit 6ac77f2236
3 changed files with 25 additions and 4 deletions
@@ -2,15 +2,22 @@ import { postApp } from "api/queries/oauth2";
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
import type { FC } from "react";
import { useMutation, useQueryClient } from "react-query";
import { useNavigate } from "react-router";
import { useNavigate, useSearchParams } from "react-router";
import { pageTitle } from "utils/page";
import { CreateOAuth2AppPageView } from "./CreateOAuth2AppPageView";
const CreateOAuth2AppPage: FC = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const queryClient = useQueryClient();
const postAppMutation = useMutation(postApp(queryClient));
const defaultValues = {
name: searchParams.get("name") ?? "",
callback_url: searchParams.get("callback_url") ?? "",
icon: searchParams.get("icon") ?? "",
};
return (
<>
<title>{pageTitle("New OAuth2 Application")}</title>
@@ -18,6 +25,7 @@ const CreateOAuth2AppPage: FC = () => {
<CreateOAuth2AppPageView
isUpdating={postAppMutation.isPending}
error={postAppMutation.error}
defaultValues={defaultValues}
createApp={async (req) => {
try {
const app = await postAppMutation.mutateAsync(req);
@@ -16,12 +16,18 @@ type CreateOAuth2AppProps = {
isUpdating: boolean;
createApp: (req: TypesGen.PostOAuth2ProviderAppRequest) => void;
error?: unknown;
defaultValues?: {
name: string;
callback_url: string;
icon: string;
};
};
export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
isUpdating,
createApp,
error,
defaultValues,
}) => {
return (
<>
@@ -51,6 +57,7 @@ export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
onSubmit={createApp}
isUpdating={isUpdating}
error={error}
defaultValues={defaultValues}
/>
</Stack>
</>
@@ -16,6 +16,11 @@ type OAuth2AppFormProps = {
error?: unknown;
isUpdating: boolean;
actions?: ReactNode;
defaultValues?: {
name: string;
callback_url: string;
icon: string;
};
};
export const OAuth2AppForm: FC<OAuth2AppFormProps> = ({
@@ -24,6 +29,7 @@ export const OAuth2AppForm: FC<OAuth2AppFormProps> = ({
error,
isUpdating,
actions,
defaultValues,
}) => {
const apiValidationErrors = isApiValidationError(error)
? mapApiErrorToFieldErrors(error.response.data)
@@ -46,7 +52,7 @@ export const OAuth2AppForm: FC<OAuth2AppFormProps> = ({
<TextField
name="name"
label="Application name"
defaultValue={app?.name}
defaultValue={app?.name ?? defaultValues?.name}
error={Boolean(apiValidationErrors?.name)}
helperText={
apiValidationErrors?.name || "The name of your Coder app."
@@ -57,7 +63,7 @@ export const OAuth2AppForm: FC<OAuth2AppFormProps> = ({
<TextField
name="callback_url"
label="Callback URL"
defaultValue={app?.callback_url}
defaultValue={app?.callback_url ?? defaultValues?.callback_url}
error={Boolean(apiValidationErrors?.callback_url)}
helperText={
apiValidationErrors?.callback_url ||
@@ -68,7 +74,7 @@ export const OAuth2AppForm: FC<OAuth2AppFormProps> = ({
<TextField
name="icon"
label="Application icon"
defaultValue={app?.icon}
defaultValue={app?.icon ?? defaultValues?.icon}
error={Boolean(apiValidationErrors?.icon)}
helperText={
apiValidationErrors?.icon || "A full or relative URL to an icon."