Skip to content

Commit

Permalink
Close change password page on success for web authgear#265
Browse files Browse the repository at this point in the history
  • Loading branch information
IniZio committed Feb 28, 2024
1 parent 98e2c2c commit ba4430b
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
57 changes: 57 additions & 0 deletions example/reactweb/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,17 @@ function Root() {
[]
);

const onClickChangePassword = useCallback(
(e: React.MouseEvent<HTMLElement>) => {
e.preventDefault();
e.stopPropagation();
authgear.startChangePassword({
redirectURI: window.location.origin + "/after-changing-password",
}).catch((err) => setError(err));
},
[]
);

const onClickSignOut = useCallback((e: React.MouseEvent<HTMLElement>) => {
e.preventDefault();
e.stopPropagation();
Expand Down Expand Up @@ -399,6 +410,13 @@ function Root() {
>
Open Settings
</button>
<button
className="button"
type="button"
onClick={onClickChangePassword}
>
Change Password
</button>
<button className="button" type="button" onClick={onClickSignOut}>
Sign out
</button>
Expand Down Expand Up @@ -539,6 +557,44 @@ function PromoteAnonymousUserRedirect() {
);
}

function ChangePasswordRedirect() {
const navigate = useNavigate();
const [error, setError] = useState(null);

useEffect(() => {
const sessionType = readSessionType();
const clientID = readClientID();
const endpoint = readEndpoint();
const isSSOEnabled = readIsSSOEnabled();
authgear
.configure({
clientID,
endpoint,
sessionType,
isSSOEnabled,
})
.then(
() => {
authgear.finishChangePassword().then(
(_) => {
navigate("/");
},
(err) => setError(err)
);
},
(err) => setError(err)
);
}, [navigate]);

return (
<div>
<p>Redirecting</p>
<ShowError error={error} />
<a href="/">Back to home</a>
</div>
);
}

function App() {
return (
<BrowserRouter>
Expand All @@ -550,6 +606,7 @@ function App() {
path="/promote-anonymous-user-redirect"
element={<PromoteAnonymousUserRedirect />}
/>
<Route path="/after-changing-password" element={<ChangePasswordRedirect />} />
</Routes>
</BrowserRouter>
);
Expand Down
3 changes: 3 additions & 0 deletions packages/authgear-core/src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ export class _BaseContainer<T extends _BaseAPIClient> {
if (options.xSettingsAction != null) {
query.append("x_settings_action", options.xSettingsAction);
}
if (options.xAuthgearSdkWebOnFinish != null) {
query.append("x_authgear_sdk_web_on_finish", options.xAuthgearSdkWebOnFinish);
}
if (!this.isSSOEnabled) {
// For backward compatibility
// If the developer updates the SDK but not the server
Expand Down
1 change: 1 addition & 0 deletions packages/authgear-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export interface _OIDCAuthenticationRequest {
suppressIDPSessionCookie?: boolean;
oauthProviderAlias?: string;
xSettingsAction?: "change_password";
xAuthgearSdkWebOnFinish?: "replace";
}

/**
Expand Down
71 changes: 71 additions & 0 deletions packages/authgear-web/src/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import {
SettingOptions,
AuthenticateResult,
ReauthenticateResult,
SettingsActionOptions,
SettingsAction,
} from "./types";

/**
Expand Down Expand Up @@ -328,6 +330,53 @@ export class WebContainer {
window.location.href = authorizeEndpoint;
}

/**
* Start settings action by redirecting to the authorization endpoint.
*
* @internal
*/
async startSettingsAction(action: SettingsAction, options: SettingsActionOptions): Promise<void> {
const idToken = this.getIDTokenHint();
if (idToken == null || !this.canReauthenticate()) {
throw new Error(
"You can only trigger settings action when authenticated"
);
}

if (this.sessionType === "refresh_token") {
const refreshToken = await this.tokenStorage.getRefreshToken(this.name);
if (!refreshToken) {
throw new AuthgearError("refresh token not found");
}
const appSessionToken = await this.baseContainer._getAppSessionToken(
refreshToken
);
const loginHint = `https://authgear.com/login_hint?type=app_session_token&app_session_token=${encodeURIComponent(
appSessionToken
)}`;

const endpoint = await this.baseContainer.authorizeEndpoint({
...options,
loginHint,
idTokenHint: idToken,
responseType: "urn:authgear:params:oauth:response-type:settings-action",
scope: ["openid", "https://authgear.com/scopes/full-access"],
xSettingsAction: action,
xAuthgearSdkWebOnFinish: "replace",
});
window.location.href = endpoint;
}
}

/**
* Start settings action "change_password" by redirecting to the authorization endpoint.
*
* @public
*/
async startChangePassword(options: SettingsActionOptions): Promise<void> {
await this.startSettingsAction(SettingsAction.ChangePassword, options);
}

/**
* Start reauthentication by redirecting to the authorization endpoint.
*/
Expand Down Expand Up @@ -400,6 +449,28 @@ export class WebContainer {
return this.baseContainer._finishReauthentication(window.location.href);
}

/**
* Finish settings action.
*
* It may reject with OAuthError.
*
* @internal
*/
async finishSettingsAction(): Promise<void> {
return this.baseContainer._finishSettingsAction(window.location.href);
}

/**
* Finish settings action "change_password".
*
* It may reject with OAuthError.
*
* @public
*/
async finishChangePassword(): Promise<void> {
return this.finishSettingsAction();
}

/**
* Finish promote anonymous user.
*
Expand Down
35 changes: 35 additions & 0 deletions packages/authgear-web/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,41 @@ export interface SettingOptions {
openInSameTab?: boolean;
}

/**
* Auth UI settings actions
*
* @public
*/
export enum SettingsAction {
/**
* Change password
*/
ChangePassword = "change_password",
}

/**
* Auth UI settings action options
*
* @public
*/
export interface SettingsActionOptions {
/**
* The value should be a valid Redirect URI to which the response will be sent after authentication.
* You must also add a Redirect URI in Authgear Poral via the Redirect URI section of your Authgear Application.
*/
redirectURI: string;
/**
* UI locale tags. You can use this parameter to set the display language for Auth UI.
*
* First, enable the language you want to change to in Authgear Portal (Your project \> UI Settings \> click on the settings icon beside Language.)
*
* For example, to change the language for Auth UI to Hong Kong,
* set the value for uiLocales to ["zh-HK"] after enabling "Chinese (Hong Kong)" in Authgear Portal.
*/
uiLocales?: string[];
}


/**
* Auth UI anonymous user promotion options
*
Expand Down

0 comments on commit ba4430b

Please sign in to comment.