|
| 1 | +# SDK - Settings Actions |
| 2 | + |
| 3 | +> [!WARNING] |
| 4 | +> **ARCHIVED DOCUMENT: For Historical Record Only.** This design was **not** adopted. Do **not** follow these specifications for current work. The **approved design** is documented in [here](./sdk-settings-actions.md). |
| 5 | +
|
| 6 | +This document specifies the API design of settings actions. |
| 7 | + |
| 8 | +- [Add / Change / Remove Email](#add--change--remove-email) |
| 9 | +- [Add / Change / Remove Phone](#add--change--remove-phone) |
| 10 | +- [Add / Change / Remove Username](#add--change--remove-username) |
| 11 | +- [Setup / Change Password](#setup--change-password) |
| 12 | +- [Manage MFA](#manage-mfa) |
| 13 | +- [Setup / Change / Remove MFA Phone](#setup--change--remove-MFA-phone) |
| 14 | +- [Setup / Change / Remove MFA Email](#setup--change--remove-MFA-email) |
| 15 | +- [Setup / Change / Remove MFA Password](#setup--change--remove-MFA-password) |
| 16 | +- [Setup / Manage MFA TOTP](#setup--manage-mfa-totp) |
| 17 | +- [Setup / View Recovery Code](#setup--view-recovery-code) |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +- [Full UserInfo Design](#full-userinfo-design) |
| 22 | +- [Security Considerations](#security-considerations) |
| 23 | + |
| 24 | +## Add / Change / Remove Email |
| 25 | + |
| 26 | +### Intention |
| 27 | + |
| 28 | +App developers might want custom button to trigger the UI in native App which manage the user's Email. |
| 29 | + |
| 30 | +### SDK Design |
| 31 | + |
| 32 | +- Add Email |
| 33 | + |
| 34 | +```typescript |
| 35 | +await authgear.addEmail({ redirectURI: "com.example://complete" }); |
| 36 | +``` |
| 37 | + |
| 38 | +- Change Email |
| 39 | + |
| 40 | +```typescript |
| 41 | +await authgear.changeEmail("user@example.com", { |
| 42 | + redirectURI: "com.example://complete", |
| 43 | +}); |
| 44 | +``` |
| 45 | + |
| 46 | +- Display Email |
| 47 | + |
| 48 | +```typescript |
| 49 | +const userInfo = await authgear.fetchUserInfo(); |
| 50 | +const email = userInfo.email; |
| 51 | +``` |
| 52 | + |
| 53 | +## Add / Change / Remove Phone |
| 54 | + |
| 55 | +### Intention |
| 56 | + |
| 57 | +App developers might want custom button to trigger the UI in native App which manage the user's Phone. |
| 58 | + |
| 59 | +### SDK Design |
| 60 | + |
| 61 | +- Add Phone |
| 62 | + |
| 63 | +```typescript |
| 64 | +await authgear.addPhone({ redirectURI: "com.example://complete" }); |
| 65 | +``` |
| 66 | + |
| 67 | +- Change Phone |
| 68 | + |
| 69 | +```typescript |
| 70 | +await authgear.changePhone("+85212341234", { |
| 71 | + redirectURI: "com.example://complete", |
| 72 | +}); |
| 73 | +``` |
| 74 | + |
| 75 | +- Display Phone |
| 76 | + |
| 77 | +```typescript |
| 78 | +const userInfo = await authgear.fetchUserInfo(); |
| 79 | +const phone = userInfo.phoneNumber; |
| 80 | +``` |
| 81 | + |
| 82 | +## Add / Change / Remove Username |
| 83 | + |
| 84 | +### Intention |
| 85 | + |
| 86 | +App developers might want custom button to trigger the UI in native App which manage the user's Username. |
| 87 | + |
| 88 | +### SDK Design |
| 89 | + |
| 90 | +- Add Username |
| 91 | + |
| 92 | +```typescript |
| 93 | +await authgear.addUsername("example", { |
| 94 | + redirectURI: "com.example://complete", |
| 95 | +}); |
| 96 | +``` |
| 97 | + |
| 98 | +- Change Username |
| 99 | + |
| 100 | +```typescript |
| 101 | +await authgear.changeUsername("example", { |
| 102 | + redirectURI: "com.example://complete", |
| 103 | +}); |
| 104 | +``` |
| 105 | + |
| 106 | +- Display Username |
| 107 | + |
| 108 | +```typescript |
| 109 | +const userInfo = await authgear.fetchUserInfo(); |
| 110 | +const username = userInfo.preferredUsername; |
| 111 | +``` |
| 112 | + |
| 113 | +## Setup / Change Password |
| 114 | + |
| 115 | +### Intention |
| 116 | + |
| 117 | +App developers might want a custom button to trigger the UI in native App which manages the user's password. |
| 118 | + |
| 119 | +### SDK Design |
| 120 | + |
| 121 | +- Display Password Status |
| 122 | + |
| 123 | +```typescript |
| 124 | +const userInfo = await authgear.fetchUserInfo(); |
| 125 | +const passwordEnabled = userInfo.passwordEnabled; |
| 126 | +``` |
| 127 | + |
| 128 | +- Setup Password |
| 129 | + |
| 130 | +```typescript |
| 131 | +await authgear.setupPassword({ redirectURI: "com.example://complete" }); |
| 132 | +``` |
| 133 | + |
| 134 | +- Change Password |
| 135 | + |
| 136 | +```typescript |
| 137 | +await authgear.changePassword({ redirectURI: "com.example://complete" }); |
| 138 | +``` |
| 139 | + |
| 140 | +- Remove Password |
| 141 | + |
| 142 | +This is not supported. |
| 143 | + |
| 144 | +## Manage MFA |
| 145 | + |
| 146 | +### Intention |
| 147 | + |
| 148 | +App developers might want custom button to trigger the UI in native App which manages the user's MFAs. |
| 149 | + |
| 150 | +### SDK Design |
| 151 | + |
| 152 | +- Display MFA Status |
| 153 | + |
| 154 | +```typescript |
| 155 | +const userInfo = await authgear.fetchUserInfo(); |
| 156 | +const isMFAEnabled = userInfo.mfa.enabled; |
| 157 | +``` |
| 158 | + |
| 159 | +- Manage MFA |
| 160 | + |
| 161 | +```typescript |
| 162 | +await authgear.manageMFA({ redirectURI: "com.example://complete" }); |
| 163 | +``` |
| 164 | + |
| 165 | +## Setup / Change / Remove MFA Phone |
| 166 | + |
| 167 | +### Intention |
| 168 | + |
| 169 | +App developers might want to display user's MFA phone number, or add button to trigger the UI in native App which manages the user's MFA phone number. |
| 170 | + |
| 171 | +### SDK Design |
| 172 | + |
| 173 | +- Setup MFA Phone |
| 174 | + |
| 175 | +```typescript |
| 176 | +await authgear.setupMFAPhone({ redirectURI: "com.example://complete" }); |
| 177 | +``` |
| 178 | + |
| 179 | +- Change MFA Phone |
| 180 | + |
| 181 | +```typescript |
| 182 | +const userInfo = await authgear.fetchUserInfo(); |
| 183 | +const phone = userInfo.mfa.phoneNumbers[0]; |
| 184 | +await authgear.changeMFAPhone(phone, { redirectURI: "com.example://complete" }); |
| 185 | +``` |
| 186 | + |
| 187 | +- Remove MFA Phone |
| 188 | + |
| 189 | +```typescript |
| 190 | +const userInfo = await authgear.fetchUserInfo(); |
| 191 | +const phone = userInfo.mfa.phoneNumbers[0]; |
| 192 | +await authgear.removeMFAPhone(phone, { redirectURI: "com.example://complete" }); |
| 193 | +``` |
| 194 | + |
| 195 | +## Setup / Change / Remove MFA Email |
| 196 | + |
| 197 | +### Intention |
| 198 | + |
| 199 | +App developers might want to display user's MFA email address, or add button to trigger the UI in native App which manages the user's MFA email address. |
| 200 | + |
| 201 | +### SDK Design |
| 202 | + |
| 203 | +- Setup MFA Email |
| 204 | + |
| 205 | +```typescript |
| 206 | +await authgear.setupMFAEmail({ redirectURI: "com.example://complete" }); |
| 207 | +``` |
| 208 | + |
| 209 | +- Change MFA Email |
| 210 | + |
| 211 | +```typescript |
| 212 | +const userInfo = await authgear.fetchUserInfo(); |
| 213 | +const email = userInfo.mfa.emails[0]; |
| 214 | +await authgear.changeMFAEmail(email, { redirectURI: "com.example://complete" }); |
| 215 | +``` |
| 216 | + |
| 217 | +- Remove MFA Email |
| 218 | + |
| 219 | +```typescript |
| 220 | +const userInfo = await authgear.fetchUserInfo(); |
| 221 | +const email = userInfo.mfa.emails[0]; |
| 222 | +await authgear.removeMFAEmail(email, { redirectURI: "com.example://complete" }); |
| 223 | +``` |
| 224 | + |
| 225 | +## Setup / Change / Remove MFA Password |
| 226 | + |
| 227 | +### Intention |
| 228 | + |
| 229 | +App developers might want custom button to trigger the UI in native App which manages the user's MFA password. |
| 230 | + |
| 231 | +### SDK Design |
| 232 | + |
| 233 | +- Display MFA Password Status |
| 234 | + |
| 235 | +```typescript |
| 236 | +const userInfo = await authgear.fetchUserInfo(); |
| 237 | +const isMFAPasswordEnabled = userInfo.mfa.passwordEnabled; |
| 238 | +``` |
| 239 | + |
| 240 | +- Setup MFA Password |
| 241 | + |
| 242 | +```typescript |
| 243 | +await authgear.setupMFAPassword({ redirectURI: "com.example://complete" }); |
| 244 | +``` |
| 245 | + |
| 246 | +- Change MFA Password |
| 247 | + |
| 248 | +```typescript |
| 249 | +await authgear.changeMFAPassword({ redirectURI: "com.example://complete" }); |
| 250 | +``` |
| 251 | + |
| 252 | +- Remove MFA Password |
| 253 | + |
| 254 | +```typescript |
| 255 | +await authgear.removeMFAPassword({ redirectURI: "com.example://complete" }); |
| 256 | +``` |
| 257 | + |
| 258 | +## Setup / Manage MFA TOTP |
| 259 | + |
| 260 | +### Intention |
| 261 | + |
| 262 | +App developers might want to offer custom buttons to trigger the UI in native App which manages the user's MFA TOTPs. |
| 263 | + |
| 264 | +### SDK Design |
| 265 | + |
| 266 | +- Display MFA TOTP Status |
| 267 | + |
| 268 | +```typescript |
| 269 | +const userInfo = await authgear.fetchUserInfo(); |
| 270 | +const totpEnabled = userInfo.mfa.totpEnabled; |
| 271 | +``` |
| 272 | + |
| 273 | +- Setup MFA TOTP |
| 274 | + |
| 275 | +```typescript |
| 276 | +await authgear.setupMFATOTP({ redirectURI: "com.example://complete" }); |
| 277 | +``` |
| 278 | + |
| 279 | +- Manage MFA TOTP |
| 280 | + |
| 281 | +```typescript |
| 282 | +await authgear.manageMFATOTP({ redirectURI: "com.example://complete" }); |
| 283 | +``` |
| 284 | + |
| 285 | +## Setup / View Recovery Code |
| 286 | + |
| 287 | +### Intention |
| 288 | + |
| 289 | +App developers might want to offer custom buttons to trigger the UI in native App which manages the user's recovery code. |
| 290 | + |
| 291 | +### SDK Design |
| 292 | + |
| 293 | +- Display Recovery Code Status |
| 294 | + |
| 295 | +```typescript |
| 296 | +const userInfo = await authgear.fetchUserInfo(); |
| 297 | +const recoveryCodeEnabled = userInfo.mfa.recoveryCodeEnabled; |
| 298 | +``` |
| 299 | + |
| 300 | +- Setup MFA Recovery Code |
| 301 | + |
| 302 | +```typescript |
| 303 | +await authgear.setupRecoveryCode({ redirectURI: "com.example://complete" }); |
| 304 | +``` |
| 305 | + |
| 306 | +- View existing Recovery Codes |
| 307 | + |
| 308 | +```typescript |
| 309 | +await authgear.viewRecoveryCode({ redirectURI: "com.example://complete" }); |
| 310 | +``` |
| 311 | + |
| 312 | +## Full UserInfo Design |
| 313 | + |
| 314 | +- SDK Object |
| 315 | + |
| 316 | +```typescript |
| 317 | +interface UserInfo { |
| 318 | + sub: string; |
| 319 | + email: string; |
| 320 | + phoneNumber: string; |
| 321 | + preferredUsername: string; |
| 322 | + passwordEnabled: boolean; |
| 323 | + mfa: { |
| 324 | + enabled: boolean; |
| 325 | + emails: []string; |
| 326 | + phoneNumbers: []string; |
| 327 | + passwordEnabled: boolean; |
| 328 | + totpEnabled: boolean; |
| 329 | + recoveryCodeEnabled: boolean; |
| 330 | + } |
| 331 | +} |
| 332 | +``` |
| 333 | + |
| 334 | +- OIDC userinfo endpoint |
| 335 | + |
| 336 | +```jsonc |
| 337 | +{ |
| 338 | + "sub": "00000000-0000-0000-0000-000000000000", |
| 339 | + "email": "user@example.com", |
| 340 | + "phone_number": "+85211111111", |
| 341 | + "preferred_username": "example", |
| 342 | + "https://authgear.com/claims/user/password_enabled": true, |
| 343 | + "https://authgear.com/claims/user/mfa_enabled": true, |
| 344 | + "https://authgear.com/claims/user/mfa_emails": ["mfa@example.com"], |
| 345 | + "https://authgear.com/claims/user/mfa_phone_numbers": ["+85212222222"], |
| 346 | + "https://authgear.com/claims/user/mfa_password_enabled": true, |
| 347 | + "https://authgear.com/claims/user/mfa_totp_enabled": true, |
| 348 | + "https://authgear.com/claims/user/recovery_code_enabled": true |
| 349 | +} |
| 350 | +``` |
| 351 | + |
| 352 | +## Security Considerations |
| 353 | + |
| 354 | +- We will expose user's password status together with MFA emails and phone numbers in userinfo endpoint, therefore client apps will be able to know them. If the client app is malicious, they may use the information to attack an authgear user. |
| 355 | +- We can hide these fields in Third-Party Clients (by checking the scope `https://authgear.com/scopes/full-access`) to mitigate the risk. |
0 commit comments