Skip to content

Commit

Permalink
Merge pull request #67 from kinde-oss/feat/error-handle
Browse files Browse the repository at this point in the history
Add auth server error handling
  • Loading branch information
DanielRivers authored Jun 6, 2024
2 parents 1a6b7bb + fbd0f1a commit 6045762
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 12 deletions.
45 changes: 36 additions & 9 deletions src/createKindeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type {
KindeUser,
OrgOptions,
RedirectOptions,
ErrorProps
GetTokenOptions
} from './types';

Expand All @@ -50,6 +51,7 @@ const createKindeClient = async (
redirect_uri,
logout_uri = redirect_uri,
on_redirect_callback,
on_error_callback,
scope = 'openid profile email offline',
proxy_redirect_uri,
_framework,
Expand Down Expand Up @@ -266,21 +268,42 @@ const createKindeClient = async (
};
};

const clearUrlParams = () => {
const url = new URL(window.location.toString());
url.search = '';
window.history.pushState({}, '', url);
};

const handleRedirectToApp = async (q: URLSearchParams) => {
const code = q.get('code')!;
const state = q.get('state');
const error = q.get('error');

if (error) {
console.error(`Error returned from authorization server: ${error}`);
}

const stringState = sessionStorage.getItem(`${SESSION_PREFIX}-${state}`);

// Verify state
if (!stringState) {
console.error('Invalid state');
} else {
if (error) {
const error = q.get('error');
const errorDescription = q.get('error_description');
clearUrlParams();
sessionStorage.removeItem(`${SESSION_PREFIX}-${state}`);

const {appState} = JSON.parse(stringState);
if (on_error_callback) {
on_error_callback({
error,
errorDescription,
state,
appState
} as ErrorProps);
} else {
window.location.href = appState.kindeOriginUrl;
}
return false;
}
const {appState, codeVerifier} = JSON.parse(stringState);
// Exchange authorisation code for an access token
try {
Expand All @@ -306,12 +329,10 @@ const createKindeClient = async (

setStore(data);
// Remove auth code from address bar
const url = new URL(window.location.toString());
url.search = '';
clearUrlParams();
sessionStorage.removeItem(`${SESSION_PREFIX}-${state}`);

const user = getUser();
window.history.pushState({}, '', url);

if (on_redirect_callback) {
on_redirect_callback(user, appState);
Expand All @@ -325,13 +346,18 @@ const createKindeClient = async (

const redirectToKinde = async (options: RedirectOptions) => {
const {
app_state,
app_state = {},
prompt,
is_create_org,
org_name = '',
org_code,
authUrlParams = {}
} = options;

if (!app_state.kindeOriginUrl) {
app_state.kindeOriginUrl = window.location.href;
}

const {state, code_challenge, url} = await setupChallenge(
config.authorization_endpoint,
app_state
Expand Down Expand Up @@ -466,7 +492,8 @@ const createKindeClient = async (
const isKindeRedirect = (searchParams: URLSearchParams) => {
// Check if the search params hve the code parameter
const hasOauthCode = searchParams.has('code');
if (!hasOauthCode) return false;
const hasError = searchParams.has('error');
if (!hasOauthCode && !hasError) return false;
// Also check if redirect_uri matches current url
const {protocol, host, pathname} = window.location;

Expand Down
17 changes: 14 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,25 @@ export type KindeState = {
token_type: string;
};

export type ErrorProps = {
error: string;
errorDescription: string;
state: string;
appState: Record<string, unknown>;
};

export type KindeClientOptions = {
audience?: string;
client_id?: string;
redirect_uri: string;
domain: string;
is_dangerously_use_local_storage?: boolean;
logout_uri?: string;
on_redirect_callback?: (user: KindeUser, appState?: object) => void;
on_error_callback?: (props: ErrorProps) => void;
on_redirect_callback?: (
user: KindeUser,
appState?: Record<string, unknown>
) => void;
scope?: string;
proxy_redirect_uri?: string;
_framework?: string;
Expand Down Expand Up @@ -79,12 +90,12 @@ export type KindeOrganizations = {

export type OrgOptions = {
org_name?: string;
app_state?: object;
app_state?: Record<string, unknown>;
};

export type AuthOptions = {
org_code?: string;
app_state?: object;
app_state?: Record<string, unknown>;
authUrlParams?: object;
};

Expand Down

0 comments on commit 6045762

Please sign in to comment.