very wip draft auth spec support
This commit is contained in:
parent
46d3d844f8
commit
befadc0042
5 changed files with 53 additions and 11 deletions
|
|
@ -125,8 +125,9 @@ const App = () => {
|
||||||
isInitiatingAuth: false,
|
isInitiatingAuth: false,
|
||||||
oauthTokens: null,
|
oauthTokens: null,
|
||||||
loading: true,
|
loading: true,
|
||||||
oauthStep: "metadata_discovery",
|
oauthStep: "resource_metadata_discovery",
|
||||||
oauthMetadata: null,
|
oauthMetadata: null,
|
||||||
|
resourceMetadata: null,
|
||||||
oauthClientInfo: null,
|
oauthClientInfo: null,
|
||||||
authorizationUrl: null,
|
authorizationUrl: null,
|
||||||
authorizationCode: "",
|
authorizationCode: "",
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,7 @@ const AuthDebugger = ({
|
||||||
serverAuthProvider.clear();
|
serverAuthProvider.clear();
|
||||||
updateAuthState({
|
updateAuthState({
|
||||||
oauthTokens: null,
|
oauthTokens: null,
|
||||||
oauthStep: "metadata_discovery",
|
oauthStep: "resource_metadata_discovery",
|
||||||
latestError: null,
|
latestError: null,
|
||||||
oauthClientInfo: null,
|
oauthClientInfo: null,
|
||||||
authorizationCode: "",
|
authorizationCode: "",
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,16 @@ export const OAuthFlowProgress = ({
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const steps: Array<OAuthStep> = [
|
||||||
|
"resource_metadata_discovery",
|
||||||
|
"metadata_discovery",
|
||||||
|
"client_registration",
|
||||||
|
"authorization_redirect",
|
||||||
|
"authorization_code",
|
||||||
|
"token_request",
|
||||||
|
"complete",
|
||||||
|
];
|
||||||
|
|
||||||
const currentStepIdx = steps.findIndex((s) => s === authState.oauthStep);
|
const currentStepIdx = steps.findIndex((s) => s === authState.oauthStep);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -124,6 +134,21 @@ export const OAuthFlowProgress = ({
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
<OAuthStepDetails
|
||||||
|
label="Resource Metadata Discovery"
|
||||||
|
{...getStepProps("resource_metadata_discovery")}
|
||||||
|
>
|
||||||
|
{authState.resourceMetadata && (
|
||||||
|
<details className="text-xs mt-2">
|
||||||
|
<summary className="cursor-pointer text-muted-foreground font-medium">
|
||||||
|
Retrieved OAuth Resource Metadata from {(new URL('/.well-known/oauth-protected-resource', serverUrl)).href}
|
||||||
|
</summary>
|
||||||
|
<pre className="mt-2 p-2 bg-muted rounded-md overflow-auto max-h-[300px]">
|
||||||
|
{JSON.stringify(authState.resourceMetadata, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
)}
|
||||||
|
</OAuthStepDetails>
|
||||||
<OAuthStepDetails
|
<OAuthStepDetails
|
||||||
label="Metadata Discovery"
|
label="Metadata Discovery"
|
||||||
{...getStepProps("metadata_discovery")}
|
{...getStepProps("metadata_discovery")}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
|
|
||||||
// OAuth flow steps
|
// OAuth flow steps
|
||||||
export type OAuthStep =
|
export type OAuthStep =
|
||||||
|
| "resource_metadata_discovery"
|
||||||
| "metadata_discovery"
|
| "metadata_discovery"
|
||||||
| "client_registration"
|
| "client_registration"
|
||||||
| "authorization_redirect"
|
| "authorization_redirect"
|
||||||
|
|
@ -28,6 +29,8 @@ export interface AuthDebuggerState {
|
||||||
oauthTokens: OAuthTokens | null;
|
oauthTokens: OAuthTokens | null;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
oauthStep: OAuthStep;
|
oauthStep: OAuthStep;
|
||||||
|
// TODO: use sdk type
|
||||||
|
resourceMetadata: object | null;
|
||||||
oauthMetadata: OAuthMetadata | null;
|
oauthMetadata: OAuthMetadata | null;
|
||||||
oauthClientInfo: OAuthClientInformationFull | OAuthClientInformation | null;
|
oauthClientInfo: OAuthClientInformationFull | OAuthClientInformation | null;
|
||||||
authorizationUrl: string | null;
|
authorizationUrl: string | null;
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,34 @@ export interface StateMachineContext {
|
||||||
export interface StateTransition {
|
export interface StateTransition {
|
||||||
canTransition: (context: StateMachineContext) => Promise<boolean>;
|
canTransition: (context: StateMachineContext) => Promise<boolean>;
|
||||||
execute: (context: StateMachineContext) => Promise<void>;
|
execute: (context: StateMachineContext) => Promise<void>;
|
||||||
nextStep: OAuthStep;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// State machine transitions
|
// State machine transitions
|
||||||
export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
metadata_discovery: {
|
resource_metadata_discovery: {
|
||||||
canTransition: async () => true,
|
canTransition: async () => true,
|
||||||
execute: async (context) => {
|
execute: async (context) => {
|
||||||
const metadata = await discoverOAuthMetadata(context.serverUrl);
|
// TODO: use sdk
|
||||||
|
const url = new URL("/.well-known/oauth-protected-resource", context.serverUrl);
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
const resourceMetadata = await response.json();
|
||||||
|
context.updateState({
|
||||||
|
resourceMetadata: resourceMetadata,
|
||||||
|
oauthStep: "metadata_discovery",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
metadata_discovery: {
|
||||||
|
canTransition: async (context) => !!context.state.resourceMetadata,
|
||||||
|
execute: async (context) => {
|
||||||
|
// TODO: use sdk
|
||||||
|
let authServerUrl = context.serverUrl;
|
||||||
|
if (context.state.resourceMetadata?.authorization_servers?.[0]) {
|
||||||
|
authServerUrl = context.state.resourceMetadata.authorization_servers[0];
|
||||||
|
}
|
||||||
|
const metadata = await discoverOAuthMetadata(authServerUrl);
|
||||||
if (!metadata) {
|
if (!metadata) {
|
||||||
throw new Error("Failed to discover OAuth metadata");
|
throw new Error("Failed to discover OAuth metadata");
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +56,6 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
oauthStep: "client_registration",
|
oauthStep: "client_registration",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
nextStep: "client_registration",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
client_registration: {
|
client_registration: {
|
||||||
|
|
@ -62,7 +80,6 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
oauthStep: "authorization_redirect",
|
oauthStep: "authorization_redirect",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
nextStep: "authorization_redirect",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
authorization_redirect: {
|
authorization_redirect: {
|
||||||
|
|
@ -93,7 +110,6 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
oauthStep: "authorization_code",
|
oauthStep: "authorization_code",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
nextStep: "authorization_code",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
authorization_code: {
|
authorization_code: {
|
||||||
|
|
@ -114,7 +130,6 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
oauthStep: "token_request",
|
oauthStep: "token_request",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
nextStep: "token_request",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
token_request: {
|
token_request: {
|
||||||
|
|
@ -144,7 +159,6 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
oauthStep: "complete",
|
oauthStep: "complete",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
nextStep: "complete",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
complete: {
|
complete: {
|
||||||
|
|
@ -152,7 +166,6 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
|
||||||
execute: async () => {
|
execute: async () => {
|
||||||
// No-op for complete state
|
// No-op for complete state
|
||||||
},
|
},
|
||||||
nextStep: "complete",
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue