|
| 1 | +# Settings Action: Connect OAuth — JS Web SDK Implementation Plan |
| 2 | + |
| 3 | +> Source repo: `authgear-sdk-js`. Companion plan: `connect-oauth-server.md`. |
| 4 | +> Platform: **authgear-web**. |
| 5 | +
|
| 6 | +## Goal |
| 7 | + |
| 8 | +Expose `startLinkOAuth(options)` / `finishLinkOAuth()` on the public `WebContainer`, mirroring the pattern of every other settings-action pair (e.g. `startAddEmail` / `finishAddEmail`). |
| 9 | + |
| 10 | +## Public API (target) |
| 11 | + |
| 12 | +`oauthProviderAlias` is **required**. The server rejects requests without it. |
| 13 | + |
| 14 | +```ts |
| 15 | +// Start — redirects the browser to Authgear, which redirects to the OAuth provider |
| 16 | +await authgear.startLinkOAuth({ |
| 17 | + redirectURI: "https://myapp.com/oauth-callback", |
| 18 | + oauthProviderAlias: "google", // required |
| 19 | +}); |
| 20 | + |
| 21 | +// Finish — called on the redirectURI page after the round-trip |
| 22 | +await authgear.finishLinkOAuth(); |
| 23 | +``` |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## File-by-file changes |
| 28 | + |
| 29 | +### 1. `packages/authgear-core/src/types.ts` |
| 30 | + |
| 31 | +**1a. Extend the `SettingsAction` enum.** Add a new member after `ChangeUsername` (the current last entry): |
| 32 | + |
| 33 | +```ts |
| 34 | +/** |
| 35 | + * Connect an OAuth provider in Authgear settings page. |
| 36 | + */ |
| 37 | +LinkOAuth = "link_oauth", |
| 38 | +``` |
| 39 | + |
| 40 | +**1b. Extend the `xSettingsAction` union in `_OIDCAuthenticationRequest`.** Append `"link_oauth"`: |
| 41 | + |
| 42 | +```ts |
| 43 | +xSettingsAction?: |
| 44 | + | "change_password" |
| 45 | + | "delete_account" |
| 46 | + | "add_email" |
| 47 | + | "add_phone" |
| 48 | + | "add_username" |
| 49 | + | "change_email" |
| 50 | + | "change_phone" |
| 51 | + | "change_username" |
| 52 | + | "link_oauth"; |
| 53 | +``` |
| 54 | + |
| 55 | +`oauthProviderAlias?: string` is **already** on `_OIDCAuthenticationRequest` — no new field needed. `startSettingsAction` spreads `...options` into `authorizeEndpoint`, so adding `oauthProviderAlias` to `_InternalSettingsActionOptions` (step 2) is sufficient to forward it. |
| 56 | + |
| 57 | +--- |
| 58 | + |
| 59 | +### 2. `packages/authgear-web/src/types.ts` |
| 60 | + |
| 61 | +**2a. Add `LinkOAuthOptions`.** Place after `ChangeUsernameOptions`: |
| 62 | + |
| 63 | +```ts |
| 64 | +/** |
| 65 | + * Options for connecting an OAuth provider via settings action. |
| 66 | + * @public |
| 67 | + */ |
| 68 | +export interface LinkOAuthOptions extends SettingsActionOptions { |
| 69 | + /** |
| 70 | + * The alias of the OAuth provider to link, |
| 71 | + * as configured in Authgear Portal under Social / Enterprise Login. |
| 72 | + * This field is required. |
| 73 | + */ |
| 74 | + oauthProviderAlias: string; |
| 75 | +} |
| 76 | +``` |
| 77 | + |
| 78 | +**2b. Add `oauthProviderAlias?` to `_InternalSettingsActionOptions`:** |
| 79 | + |
| 80 | +```ts |
| 81 | +export interface _InternalSettingsActionOptions extends SettingsActionOptions { |
| 82 | + qLoginID?: string; |
| 83 | + oauthProviderAlias?: string; |
| 84 | +} |
| 85 | +``` |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +### 3. `packages/authgear-web/src/container.ts` |
| 90 | + |
| 91 | +No change to `startSettingsAction` — it already spreads `...options` into `authorizeEndpoint`, so `oauthProviderAlias` flows through automatically once it is on `_InternalSettingsActionOptions`. |
| 92 | + |
| 93 | +**3a. Add `startLinkOAuth`.** Place after `startChangeUsername`: |
| 94 | + |
| 95 | +```ts |
| 96 | +/** |
| 97 | + * Start settings action "link_oauth" by redirecting to the authorization endpoint. |
| 98 | + * @public |
| 99 | + */ |
| 100 | +async startLinkOAuth(options: LinkOAuthOptions): Promise<void> { |
| 101 | + await this.startSettingsAction(SettingsAction.LinkOAuth, options); |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +**3b. Add `finishLinkOAuth`.** Place after `finishChangeUsername`: |
| 106 | + |
| 107 | +```ts |
| 108 | +/** |
| 109 | + * Finish settings action "link_oauth". |
| 110 | + * @public |
| 111 | + */ |
| 112 | +async finishLinkOAuth(): Promise<void> { |
| 113 | + return this.finishSettingsAction(); |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +`finishSettingsAction` delegates to `this.baseContainer._finishSettingsAction(window.location.href)`, identical to all other finish methods except `finishDeleteAccount`. |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +### 4. Public exports |
| 122 | + |
| 123 | +Add `LinkOAuthOptions` to `packages/authgear-web/src/index.ts` if types are explicitly re-exported there. `WebContainer` is already re-exported so the new methods come along automatically. |
| 124 | + |
| 125 | +--- |
| 126 | + |
| 127 | +## Verification |
| 128 | + |
| 129 | +- **Type-check:** `npx tsc --noEmit` in `packages/authgear-core` and `packages/authgear-web`. |
| 130 | +- **Build:** `npm run build` in `packages/authgear-web`. |
| 131 | +- **API Extractor:** new `startLinkOAuth`, `finishLinkOAuth`, and `LinkOAuthOptions` should appear in the public API report. |
| 132 | +- **Manual:** complete the round trip against a local `authgear-server` with the server-side changes applied. |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +## Checklist |
| 137 | + |
| 138 | +- [ ] `SettingsAction.LinkOAuth` in `authgear-core/src/types.ts` |
| 139 | +- [ ] `"link_oauth"` in the `xSettingsAction` union |
| 140 | +- [ ] `LinkOAuthOptions` in `authgear-web/src/types.ts` |
| 141 | +- [ ] `oauthProviderAlias?` on `_InternalSettingsActionOptions` |
| 142 | +- [ ] `startLinkOAuth` / `finishLinkOAuth` on `WebContainer` |
| 143 | +- [ ] `LinkOAuthOptions` exported from the package entry point |
| 144 | +- [ ] TypeScript build / typecheck pass |
| 145 | +- [ ] API Extractor report regenerated and reviewed |
0 commit comments