saafe-redirection-flow 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/.github/workflows/build-and-deploy.yml +41 -0
  2. package/.gitlab-ci.yml +108 -0
  3. package/.releaserc.json +18 -0
  4. package/.storybook/main.ts +28 -0
  5. package/.storybook/preview.ts +16 -0
  6. package/.storybook/vitest.setup.ts +9 -0
  7. package/.vite/deps/@radix-ui_react-avatar.js +230 -0
  8. package/.vite/deps/@radix-ui_react-avatar.js.map +7 -0
  9. package/.vite/deps/@radix-ui_react-slot.js +12 -0
  10. package/.vite/deps/@radix-ui_react-slot.js.map +7 -0
  11. package/.vite/deps/_metadata.json +79 -0
  12. package/.vite/deps/chunk-5VGQBUCU.js +597 -0
  13. package/.vite/deps/chunk-5VGQBUCU.js.map +7 -0
  14. package/.vite/deps/chunk-DC5AMYBS.js +38 -0
  15. package/.vite/deps/chunk-DC5AMYBS.js.map +7 -0
  16. package/.vite/deps/chunk-HUIEPYH7.js +11265 -0
  17. package/.vite/deps/chunk-HUIEPYH7.js.map +7 -0
  18. package/.vite/deps/chunk-TKHB4QMX.js +281 -0
  19. package/.vite/deps/chunk-TKHB4QMX.js.map +7 -0
  20. package/.vite/deps/chunk-YLDSBLSF.js +1139 -0
  21. package/.vite/deps/chunk-YLDSBLSF.js.map +7 -0
  22. package/.vite/deps/class-variance-authority.js +63 -0
  23. package/.vite/deps/class-variance-authority.js.map +7 -0
  24. package/.vite/deps/lucide-react.js +36984 -0
  25. package/.vite/deps/lucide-react.js.map +7 -0
  26. package/.vite/deps/package.json +3 -0
  27. package/.vite/deps/react-dom_client.js +17917 -0
  28. package/.vite/deps/react-dom_client.js.map +7 -0
  29. package/.vite/deps/react-router-dom.js +452 -0
  30. package/.vite/deps/react-router-dom.js.map +7 -0
  31. package/.vite/deps/react-router.js +234 -0
  32. package/.vite/deps/react-router.js.map +7 -0
  33. package/.vite/deps/react.js +5 -0
  34. package/.vite/deps/react.js.map +7 -0
  35. package/.vite/deps/react_jsx-dev-runtime.js +470 -0
  36. package/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
  37. package/CHANGELOG.md +420 -0
  38. package/LICENSE +21 -0
  39. package/README.md +129 -0
  40. package/RELEASE_CHEATSHEET.md +93 -0
  41. package/RELEASE_NOTES.md +120 -0
  42. package/components.json +21 -0
  43. package/docs/DEPLOYMENT_WORKFLOW.md +262 -0
  44. package/docs/RELEASE_GUIDE.md +591 -0
  45. package/docs/architecture.md +432 -0
  46. package/docs/components.md +199 -0
  47. package/docs/index.md +69 -0
  48. package/docs/local-release-workflow.md +234 -0
  49. package/docs/routes.md +118 -0
  50. package/docs/sdk-integration.md +325 -0
  51. package/docs/semantic-release.md +124 -0
  52. package/docs/user-flow.md +206 -0
  53. package/eslint.config.js +28 -0
  54. package/index.html +19 -0
  55. package/install.sh +198 -0
  56. package/package.json +115 -0
  57. package/public/images/bank-logo.png +0 -0
  58. package/public/saafe-icon.svg +9 -0
  59. package/src/App.tsx +171 -0
  60. package/src/__tests__/url-parameters.test.ts +82 -0
  61. package/src/assets/brand/applestore.svg +13 -0
  62. package/src/assets/brand/playstore.svg +23 -0
  63. package/src/assets/brand/saafe-color-white-logo.svg +14 -0
  64. package/src/assets/brand/saafe-icon.svg +9 -0
  65. package/src/assets/brand/saafe-logo.svg +18 -0
  66. package/src/assets/icons/check-icon-dark.svg +27 -0
  67. package/src/assets/icons/check-icon.svg +23 -0
  68. package/src/components/ErrorBoundary.tsx +132 -0
  69. package/src/components/alert/alert.tsx +27 -0
  70. package/src/components/auth/AuthGuard.tsx +76 -0
  71. package/src/components/cards/BankCard.stories.tsx +69 -0
  72. package/src/components/cards/BankCard.tsx +227 -0
  73. package/src/components/cards/OuterCard.tsx +109 -0
  74. package/src/components/cards/WrapperCard.tsx +64 -0
  75. package/src/components/documents/PrivacyContent.tsx +1 -0
  76. package/src/components/dummyFooter.tsx +29 -0
  77. package/src/components/icons/github.tsx +12 -0
  78. package/src/components/language/LanguageSwitcher.tsx +44 -0
  79. package/src/components/layouts/FrostedLayout.stories.tsx +42 -0
  80. package/src/components/layouts/FrostedLayout.tsx +333 -0
  81. package/src/components/layouts/MobileLayout.tsx +403 -0
  82. package/src/components/mobile-background.tsx +136 -0
  83. package/src/components/mobileAppDownload.tsx +30 -0
  84. package/src/components/modal/ModalComp.tsx +27 -0
  85. package/src/components/mode-toggle.tsx +36 -0
  86. package/src/components/page-header.tsx +50 -0
  87. package/src/components/session/SessionTimeoutScreen.tsx +134 -0
  88. package/src/components/session/SessionTimer.tsx +173 -0
  89. package/src/components/step-navigation.tsx +87 -0
  90. package/src/components/title/AppBar.stories.tsx +50 -0
  91. package/src/components/title/AppBar.tsx +150 -0
  92. package/src/components/title/SectionTitle.tsx +31 -0
  93. package/src/components/ui/AnimatedButton.module.css +13 -0
  94. package/src/components/ui/alert.tsx +66 -0
  95. package/src/components/ui/animatedButton.tsx +111 -0
  96. package/src/components/ui/avatar.tsx +51 -0
  97. package/src/components/ui/badge.tsx +36 -0
  98. package/src/components/ui/bottom-sheet.tsx +122 -0
  99. package/src/components/ui/button.tsx +59 -0
  100. package/src/components/ui/calendar.tsx +86 -0
  101. package/src/components/ui/card.tsx +92 -0
  102. package/src/components/ui/checkbox.stories.tsx +49 -0
  103. package/src/components/ui/checkbox.tsx +67 -0
  104. package/src/components/ui/collapsible.tsx +45 -0
  105. package/src/components/ui/dialog.tsx +134 -0
  106. package/src/components/ui/document-link.tsx +26 -0
  107. package/src/components/ui/dot-stepper.tsx +57 -0
  108. package/src/components/ui/dropdown-menu.tsx +255 -0
  109. package/src/components/ui/form.tsx +165 -0
  110. package/src/components/ui/frosted-panel.stories.tsx +86 -0
  111. package/src/components/ui/frosted-panel.tsx +276 -0
  112. package/src/components/ui/input.tsx +39 -0
  113. package/src/components/ui/label.stories.tsx +67 -0
  114. package/src/components/ui/label.tsx +23 -0
  115. package/src/components/ui/mobile-footer.tsx +54 -0
  116. package/src/components/ui/modal.tsx +90 -0
  117. package/src/components/ui/otp-input.stories.tsx +62 -0
  118. package/src/components/ui/otp-input.tsx +221 -0
  119. package/src/components/ui/platform-specific-behavior.tsx +28 -0
  120. package/src/components/ui/popover.tsx +46 -0
  121. package/src/components/ui/progress.tsx +103 -0
  122. package/src/components/ui/radio-group.tsx +45 -0
  123. package/src/components/ui/scroll-area.tsx +56 -0
  124. package/src/components/ui/sdk-params-docs.tsx +53 -0
  125. package/src/components/ui/select.tsx +159 -0
  126. package/src/components/ui/separator.tsx +28 -0
  127. package/src/components/ui/sheet.tsx +137 -0
  128. package/src/components/ui/sidebar.tsx +724 -0
  129. package/src/components/ui/skeleton.stories.tsx +50 -0
  130. package/src/components/ui/skeleton.tsx +15 -0
  131. package/src/components/ui/sonner.tsx +23 -0
  132. package/src/components/ui/step.stories.tsx +132 -0
  133. package/src/components/ui/step.tsx +234 -0
  134. package/src/components/ui/stepper-progress.tsx +136 -0
  135. package/src/components/ui/stepper.tsx +259 -0
  136. package/src/components/ui/tabs.tsx +55 -0
  137. package/src/components/ui/tooltip.tsx +61 -0
  138. package/src/components/ui/url-decode-loader.tsx +36 -0
  139. package/src/components/ui/version-display.tsx +104 -0
  140. package/src/components/ui/web-footer.tsx +36 -0
  141. package/src/config/environments.ts +99 -0
  142. package/src/config/urls.ts +53 -0
  143. package/src/const/fiTypeCategoryMap.ts +19 -0
  144. package/src/contexts/LanguageContext.tsx +41 -0
  145. package/src/contexts/RTLContext.tsx +42 -0
  146. package/src/contexts/ThemeContext.tsx +93 -0
  147. package/src/hooks/use-account-discovery.ts +205 -0
  148. package/src/hooks/use-auth-query.ts +141 -0
  149. package/src/hooks/use-fip-query.ts +72 -0
  150. package/src/hooks/use-media-query.ts +32 -0
  151. package/src/hooks/use-mobile.ts +24 -0
  152. package/src/hooks/use-page-title.tsx +48 -0
  153. package/src/hooks/use-platform.ts +52 -0
  154. package/src/hooks/use-trusted-count.ts +21 -0
  155. package/src/hooks/use-url-decode.ts +90 -0
  156. package/src/hooks/useStep.ts +170 -0
  157. package/src/index.css +154 -0
  158. package/src/interfaces/app.interfaces.ts +39 -0
  159. package/src/interfaces/services.interfaces.ts +65 -0
  160. package/src/lib/i18n.ts +68 -0
  161. package/src/lib/utils.ts +6 -0
  162. package/src/locales/en/common.json +167 -0
  163. package/src/locales/hi/common.json +137 -0
  164. package/src/locales/kn/common.json +137 -0
  165. package/src/locales/ml/common.json +137 -0
  166. package/src/locales/ta/common.json +137 -0
  167. package/src/locales/te/common.json +137 -0
  168. package/src/locales/ur/common.json +138 -0
  169. package/src/main.tsx +46 -0
  170. package/src/pages/Login.tsx +363 -0
  171. package/src/pages/accounts/AccountsToProceed.tsx +396 -0
  172. package/src/pages/accounts/Discover.tsx +76 -0
  173. package/src/pages/accounts/DiscoverAccount.tsx +751 -0
  174. package/src/pages/accounts/LinkSelectedAccounts.tsx +638 -0
  175. package/src/pages/accounts/OldUser.tsx +329 -0
  176. package/src/pages/accounts/link-accounts.tsx +913 -0
  177. package/src/pages/consent/ReviewConsent.tsx +836 -0
  178. package/src/pages/consent/rejected.tsx +253 -0
  179. package/src/pages/consent/success.tsx +220 -0
  180. package/src/providers/query-provider.tsx +24 -0
  181. package/src/providers/toast-provider.tsx +26 -0
  182. package/src/services/api/account.service.ts +296 -0
  183. package/src/services/api/auth.service.ts +206 -0
  184. package/src/services/api/axios.ts +138 -0
  185. package/src/services/api/consent.service.ts +142 -0
  186. package/src/services/api/decode.service.ts +53 -0
  187. package/src/services/api/feedback.service.ts +34 -0
  188. package/src/services/api/fip.service.ts +187 -0
  189. package/src/services/api/index.ts +9 -0
  190. package/src/services/api/public.service.ts +18 -0
  191. package/src/services/api.ts +2 -0
  192. package/src/services/postMessage.service.ts +179 -0
  193. package/src/store/NavigationBlockContext.tsx +34 -0
  194. package/src/store/auth.store.ts +79 -0
  195. package/src/store/fip.store.ts +396 -0
  196. package/src/store/mandatoryConsent.store.ts +24 -0
  197. package/src/store/redirect.store.ts +73 -0
  198. package/src/store/step.store.ts +124 -0
  199. package/src/stories/Button.stories.ts +53 -0
  200. package/src/stories/Button.tsx +37 -0
  201. package/src/stories/Configure.mdx +364 -0
  202. package/src/stories/Header.stories.ts +33 -0
  203. package/src/stories/Header.tsx +56 -0
  204. package/src/stories/Page.stories.ts +32 -0
  205. package/src/stories/Page.tsx +73 -0
  206. package/src/stories/button.css +30 -0
  207. package/src/stories/header.css +32 -0
  208. package/src/stories/page.css +68 -0
  209. package/src/styles/rtl-utils.css +90 -0
  210. package/src/styles/rtl.css +105 -0
  211. package/src/utils/api-error.ts +26 -0
  212. package/src/utils/cn.ts +10 -0
  213. package/src/utils/error-callback.ts +116 -0
  214. package/src/utils/formatAccountNumber.ts +9 -0
  215. package/src/utils/handleIdentifiers.ts +90 -0
  216. package/src/utils/posthog.ts +67 -0
  217. package/src/utils/toast-helpers.ts +61 -0
  218. package/src/vite-env.d.ts +1 -0
  219. package/stage-aa-2506251021.zip +0 -0
  220. package/tsconfig.app.json +33 -0
  221. package/tsconfig.json +13 -0
  222. package/tsconfig.node.json +24 -0
  223. package/vite.config.ts +45 -0
  224. package/vitest.shims.d.ts +1 -0
  225. package/vitest.workspace.ts +46 -0
@@ -0,0 +1,234 @@
1
+ # Local Release Workflow Guide
2
+
3
+ This guide explains how to use the semantic release setup for local development and deployment without GitHub Actions.
4
+
5
+ ## Quick Start
6
+
7
+ ### 1. Check Current Status
8
+ ```bash
9
+ # Check current version
10
+ npm run version:check
11
+
12
+ # List environment files
13
+ npm run env:list
14
+
15
+ # Check environment variables
16
+ npm run env:check
17
+ ```
18
+
19
+ ### 2. Test Release (Dry Run)
20
+ ```bash
21
+ # Test what version would be released
22
+ npm run release:dry
23
+ ```
24
+
25
+ ### 3. Actual Release
26
+ ```bash
27
+ # Create actual release
28
+ npm run release
29
+ ```
30
+
31
+ ## Environment-Based Builds
32
+
33
+ ### Build for Specific Environments
34
+ ```bash
35
+ # Build for production
36
+ npm run build:production
37
+
38
+ # Build for staging
39
+ npm run build:stage
40
+
41
+ # Build for sandbox
42
+ npm run build:sandbox
43
+
44
+ # Build for all environments
45
+ npm run build:all
46
+ ```
47
+
48
+ ### Preview Builds
49
+ ```bash
50
+ # Preview production build
51
+ npm run preview:production
52
+
53
+ # Preview stage build
54
+ npm run preview:stage
55
+
56
+ # Preview sandbox build
57
+ npm run preview:sandbox
58
+ ```
59
+
60
+ ## Commit Convention
61
+
62
+ Use conventional commits for automatic version bumping:
63
+
64
+ ### Patch Releases (1.0.0 → 1.0.1)
65
+ ```bash
66
+ git commit -m "fix: resolve login issue"
67
+ git commit -m "fix(auth): handle token expiration"
68
+ ```
69
+
70
+ ### Minor Releases (1.0.0 → 1.1.0)
71
+ ```bash
72
+ git commit -m "feat: add new authentication flow"
73
+ git commit -m "feat(dashboard): implement account selection"
74
+ ```
75
+
76
+ ### Major Releases (1.0.0 → 2.0.0)
77
+ ```bash
78
+ git commit -m "feat!: redesign authentication system"
79
+ git commit -m "feat(api)!: change response format"
80
+ ```
81
+
82
+ ### Other Commit Types (No Release)
83
+ ```bash
84
+ git commit -m "docs: update readme"
85
+ git commit -m "refactor: improve code structure"
86
+ git commit -m "style: fix formatting"
87
+ git commit -m "test: add unit tests"
88
+ git commit -m "chore: update dependencies"
89
+ ```
90
+
91
+ ## Branch-Based Versioning
92
+
93
+ ### Main Branch (Production)
94
+ - Creates stable releases: `1.0.0`, `1.1.0`, `2.0.0`
95
+ - Used for production deployments
96
+
97
+ ### Stage Branch
98
+ - Creates pre-releases: `1.0.0-stage.1`, `1.0.0-stage.2`
99
+ - Used for staging environment testing
100
+
101
+ ### Sandbox Branch
102
+ - Creates pre-releases: `1.0.0-sandbox.1`, `1.0.0-sandbox.2`
103
+ - Used for sandbox environment testing
104
+
105
+ ### Develop Branch
106
+ - Creates pre-releases: `1.0.0-dev.1`, `1.0.0-dev.2`
107
+ - Used for development environment testing
108
+
109
+ ## Release Process
110
+
111
+ ### 1. Development Workflow
112
+ ```bash
113
+ # Switch to appropriate branch
114
+ git checkout sandbox
115
+
116
+ # Make changes with conventional commits
117
+ git add .
118
+ git commit -m "feat: add new feature"
119
+
120
+ # Test release
121
+ npm run release:dry
122
+
123
+ # Create release
124
+ npm run release
125
+ ```
126
+
127
+ ### 2. Build and Deploy
128
+ ```bash
129
+ # Build for the environment
130
+ npm run build:sandbox
131
+
132
+ # Deploy the dist/ folder to your hosting service
133
+ ```
134
+
135
+ ### 3. Promotion Workflow
136
+ ```bash
137
+ # Promote sandbox to stage
138
+ git checkout stage
139
+ git merge sandbox
140
+ npm run release
141
+
142
+ # Build for stage
143
+ npm run build:stage
144
+
145
+ # Promote stage to production
146
+ git checkout main
147
+ git merge stage
148
+ npm run release
149
+
150
+ # Build for production
151
+ npm run build:production
152
+ ```
153
+
154
+ ## What Semantic Release Does
155
+
156
+ ### Automatic Actions:
157
+ 1. **Analyzes commits** since last release
158
+ 2. **Determines version bump** based on commit types
159
+ 3. **Generates release notes** from commit messages
160
+ 4. **Updates package.json** version
161
+ 5. **Updates CHANGELOG.md** with new release notes
162
+ 6. **Creates git tag** for the new version
163
+ 7. **Commits changes** back to repository
164
+
165
+ ### Generated Files:
166
+ - `CHANGELOG.md` - Automatically updated with release notes
167
+ - `package.json` - Version field updated
168
+ - `package-lock.json` - Version field updated
169
+
170
+ ## Environment Configuration
171
+
172
+ ### Environment Variables Available:
173
+ - `VITE_API_BASE_URL` - API endpoint for current environment
174
+ - `VITE_IMAGE_BASE_URL` - Image CDN URL
175
+ - `VITE_APP_NAME` - Application name
176
+ - `VITE_PUBLIC_POSTHOG_KEY` - Analytics key
177
+ - `VITE_SESSION_TIMEOUT` - Session timeout duration
178
+
179
+ ### Environment Files:
180
+ - `.env.production` - Production settings
181
+ - `.env.stage` - Stage settings
182
+ - `.env.sandbox` - Sandbox settings
183
+ - `.env.development` - Development settings
184
+
185
+ ## Troubleshooting
186
+
187
+ ### No Release Created
188
+ - Check if commits follow conventional format
189
+ - Ensure you're on the correct branch
190
+ - Run `npm run release:dry` to see what would happen
191
+
192
+ ### Build Failures
193
+ - Check TypeScript errors: `npm run lint`
194
+ - Verify environment variables are set
195
+ - Ensure all dependencies are installed: `npm install`
196
+
197
+ ### Version Conflicts
198
+ - Always pull latest changes before releasing
199
+ - Use `git status` to check for uncommitted changes
200
+ - Resolve any merge conflicts before releasing
201
+
202
+ ## Useful Commands
203
+
204
+ ```bash
205
+ # Check what would be released
206
+ npm run release:dry
207
+
208
+ # Check current version
209
+ npm run version:check
210
+
211
+ # List all environment files
212
+ npm run env:list
213
+
214
+ # Check environment variables
215
+ npm run env:check
216
+
217
+ # Build all environments
218
+ npm run build:all
219
+
220
+ # Run development server
221
+ npm run dev
222
+
223
+ # Preview production build locally
224
+ npm run preview:production
225
+ ```
226
+
227
+ ## Best Practices
228
+
229
+ 1. **Always test with dry run** before actual release
230
+ 2. **Use descriptive commit messages** for better release notes
231
+ 3. **Build and test** before releasing
232
+ 4. **Use branch-specific environments** for testing
233
+ 5. **Keep environment files** updated with correct settings
234
+ 6. **Review generated CHANGELOG.md** after releases
package/docs/routes.md ADDED
@@ -0,0 +1,118 @@
1
+ # SAAFE Routes Documentation
2
+
3
+ This document provides information about the routes and pages available in the SAAFE Redirection Flow application.
4
+
5
+ ## Route Structure
6
+
7
+ The application uses React Router v7 for route management. The main route structure is defined in `App.tsx`.
8
+
9
+ ## Available Routes
10
+
11
+ ### Public Routes
12
+
13
+ | Route | Component | Description |
14
+ |-------|-----------|-------------|
15
+ | `/` | Redirect to `/login` | Redirects to the login page |
16
+ | `/login` | `Login` | Initial entry point for user authentication |
17
+
18
+ ### Protected Routes
19
+
20
+ These routes require authentication via the `AuthGuard` component:
21
+
22
+ | Route | Component | Description |
23
+ |-------|-----------|-------------|
24
+ | `/link-accounts` | Redirect to `/link-accounts/banks` | Default redirect for account linking |
25
+ | `/link-accounts/discovery` | `Discover` | Account discovery page |
26
+ | `/link-accounts/proceed` | `Discover` | Proceed with discovered accounts |
27
+ | `/link-accounts/link` | `Discover` | Link selected accounts |
28
+ | `/link-accounts/discover-account` | `Discover` | Discover specific account details |
29
+ | `/link-accounts/old-user` | `OldUser` | Page for returning users with existing linked accounts |
30
+ | `/link-accounts/:category` | `Discover` | Category-specific financial institution listing |
31
+ | `/review` | `ReviewConsent` | Review and confirm data sharing consent |
32
+ | `/success` | `Success` | Successful account linking confirmation |
33
+ | `/rejected` | `Rejected` | Consent rejection confirmation |
34
+
35
+ ## Page Components
36
+
37
+ ### Login Page
38
+
39
+ **Path:** `/login`
40
+ **Component:** `Login.tsx`
41
+
42
+ The initial entry point for users. This page:
43
+ - Decodes and validates URL parameters
44
+ - Authenticates the user with their financial institution
45
+ - Supports OTP verification if enabled
46
+ - Adapts UI based on the specified platform
47
+ - Handles theme preferences
48
+
49
+ ### Discover Page
50
+
51
+ **Path:** `/link-accounts/discovery` (and related paths)
52
+ **Component:** `Discover.tsx`
53
+
54
+ Multi-purpose page that handles various aspects of account discovery:
55
+ - Lists available financial institutions by category
56
+ - Discovers accounts associated with a user
57
+ - Allows selection of accounts to link
58
+ - Shows detailed account information
59
+
60
+ ### ReviewConsent Page
61
+
62
+ **Path:** `/review`
63
+ **Component:** `ReviewConsent.tsx`
64
+
65
+ Page for reviewing and providing consent for data sharing:
66
+ - Displays detailed information about what data will be shared
67
+ - Shows the third-party requestor details
68
+ - Explains the purpose of data sharing
69
+ - Provides clear accept/reject options
70
+
71
+ ### Success Page
72
+
73
+ **Path:** `/success`
74
+ **Component:** `Success.tsx`
75
+
76
+ Confirmation page shown after successful account linking:
77
+ - Displays success message and next steps
78
+ - Provides options to return to the originating application
79
+ - Shows linked account details (if configured)
80
+
81
+ ### Rejected Page
82
+
83
+ **Path:** `/rejected`
84
+ **Component:** `Rejected.tsx`
85
+
86
+ Confirmation page shown after rejecting consent:
87
+ - Confirms the user's rejection of data sharing
88
+ - Explains implications of rejection
89
+ - Provides options to return to the originating application
90
+
91
+ ### Old User Page
92
+
93
+ **Path:** `/link-accounts/old-user`
94
+ **Component:** `OldUser.tsx`
95
+
96
+ Special page for returning users with previously linked accounts:
97
+ - Shows existing linked accounts
98
+ - Provides options to add more accounts
99
+ - Allows unlinking of existing accounts
100
+
101
+ ## Navigation Flow
102
+
103
+ The typical user journey follows this flow:
104
+
105
+ 1. User arrives at `/login` with required URL parameters
106
+ 2. After successful authentication, user is directed to `/link-accounts/discovery`
107
+ 3. User selects accounts to link and proceeds to `/review`
108
+ 4. User reviews consent details and either:
109
+ - Accepts, leading to `/success`
110
+ - Rejects, leading to `/rejected`
111
+
112
+ ## Route Protection
113
+
114
+ All routes except `/login` are protected by the `AuthGuard` component, which:
115
+ - Verifies that the user is authenticated
116
+ - Redirects unauthenticated users to the login page
117
+ - Maintains session state across page navigation
118
+ - Handles session timeouts
@@ -0,0 +1,325 @@
1
+ # SAAFE SDK Integration Guide
2
+
3
+ This document provides detailed information on how to integrate the SAAFE Redirection Flow into your applications via the SDK.
4
+
5
+ ## Overview
6
+
7
+ The SAAFE Redirection Flow is designed to be embedded within mobile and web applications using a WebView (iOS, Android) or iframe (Web) approach. This allows your users to securely link their financial accounts without leaving your application.
8
+
9
+ ## Integration Methods
10
+
11
+ ### Mobile SDK Integration
12
+
13
+ #### iOS (Swift) WebView Integration
14
+
15
+ ```swift
16
+ import UIKit
17
+ import WebKit
18
+
19
+ class SAFERedirectionViewController: UIViewController, WKNavigationDelegate {
20
+
21
+ private var webView: WKWebView!
22
+ private let financialInstitutionId: String
23
+ private let encryptedRequest: String
24
+ private let requestDate: String
25
+
26
+ init(financialInstitutionId: String, encryptedRequest: String, requestDate: String) {
27
+ self.financialInstitutionId = financialInstitutionId
28
+ self.encryptedRequest = encryptedRequest
29
+ self.requestDate = requestDate
30
+ super.init(nibName: nil, bundle: nil)
31
+ }
32
+
33
+ required init?(coder: NSCoder) {
34
+ fatalError("init(coder:) has not been implemented")
35
+ }
36
+
37
+ override func viewDidLoad() {
38
+ super.viewDidLoad()
39
+
40
+ setupWebView()
41
+ loadSAAFERedirection()
42
+ }
43
+
44
+ private func setupWebView() {
45
+ let configuration = WKWebViewConfiguration()
46
+ webView = WKWebView(frame: view.bounds, configuration: configuration)
47
+ webView.navigationDelegate = self
48
+ webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
49
+ view.addSubview(webView)
50
+ }
51
+
52
+ private func loadSAAFERedirection() {
53
+ let baseUrl = "https://saafe-app.com/login"
54
+ var urlComponents = URLComponents(string: baseUrl)!
55
+
56
+ urlComponents.queryItems = [
57
+ URLQueryItem(name: "fi", value: financialInstitutionId),
58
+ URLQueryItem(name: "ecreq", value: encryptedRequest),
59
+ URLQueryItem(name: "reqdate", value: requestDate),
60
+ URLQueryItem(name: "platform", value: "ios"),
61
+ URLQueryItem(name: "theme", value: "system")
62
+ ]
63
+
64
+ if let url = urlComponents.url {
65
+ let request = URLRequest(url: url)
66
+ webView.load(request)
67
+ }
68
+ }
69
+
70
+ // MARK: - WKNavigationDelegate
71
+
72
+ func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
73
+ // Handle successful page load
74
+ }
75
+
76
+ func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
77
+ // Intercept navigation if needed
78
+
79
+ // Example: Detect success/rejection callbacks
80
+ if let url = navigationAction.request.url?.absoluteString {
81
+ if url.contains("/success") {
82
+ // Handle success scenario
83
+ self.dismiss(animated: true, completion: nil)
84
+ decisionHandler(.cancel)
85
+ return
86
+ } else if url.contains("/rejected") {
87
+ // Handle rejection scenario
88
+ self.dismiss(animated: true, completion: nil)
89
+ decisionHandler(.cancel)
90
+ return
91
+ }
92
+ }
93
+
94
+ decisionHandler(.allow)
95
+ }
96
+ }
97
+ ```
98
+
99
+ #### Android (Kotlin) WebView Integration
100
+
101
+ ```kotlin
102
+ import android.os.Bundle
103
+ import android.webkit.WebView
104
+ import android.webkit.WebViewClient
105
+ import androidx.appcompat.app.AppCompatActivity
106
+ import java.net.URLEncoder
107
+
108
+ class SAFERedirectionActivity : AppCompatActivity() {
109
+
110
+ private lateinit var webView: WebView
111
+
112
+ override fun onCreate(savedInstanceState: Bundle?) {
113
+ super.onCreate(savedInstanceState)
114
+
115
+ // Get parameters from intent
116
+ val financialInstitutionId = intent.getStringExtra("fi") ?: ""
117
+ val encryptedRequest = intent.getStringExtra("ecreq") ?: ""
118
+ val requestDate = intent.getStringExtra("reqdate") ?: ""
119
+
120
+ // Set up WebView
121
+ webView = WebView(this)
122
+ webView.settings.javaScriptEnabled = true
123
+ webView.settings.domStorageEnabled = true
124
+
125
+ webView.webViewClient = object : WebViewClient() {
126
+ override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
127
+ // Detect success/rejection URLs
128
+ url?.let {
129
+ when {
130
+ it.contains("/success") -> {
131
+ // Handle success
132
+ finish()
133
+ return true
134
+ }
135
+ it.contains("/rejected") -> {
136
+ // Handle rejection
137
+ finish()
138
+ return true
139
+ }
140
+ }
141
+ }
142
+ return false
143
+ }
144
+ }
145
+
146
+ setContentView(webView)
147
+
148
+ // Load SAAFE Redirection Flow
149
+ val baseUrl = "https://saafe-app.com/login"
150
+ val urlParams = "?fi=$financialInstitutionId&ecreq=$encryptedRequest&reqdate=$requestDate&platform=android&theme=system"
151
+ webView.loadUrl(baseUrl + urlParams)
152
+ }
153
+
154
+ override fun onBackPressed() {
155
+ if (webView.canGoBack()) {
156
+ webView.goBack()
157
+ } else {
158
+ // Show confirmation dialog before exiting
159
+ // This is important as closing mid-flow can cause issues
160
+ // Implementation of confirmation dialog omitted for brevity
161
+ }
162
+ }
163
+ }
164
+ ```
165
+
166
+ ### Web Integration
167
+
168
+ #### React Application Integration
169
+
170
+ ```tsx
171
+ import React, { useEffect, useRef } from 'react';
172
+
173
+ interface SAFERedirectionProps {
174
+ financialInstitutionId: string;
175
+ encryptedRequest: string;
176
+ requestDate: string;
177
+ onSuccess?: () => void;
178
+ onRejection?: () => void;
179
+ theme?: 'light' | 'dark' | 'system';
180
+ }
181
+
182
+ const SAFERedirection: React.FC<SAFERedirectionProps> = ({
183
+ financialInstitutionId,
184
+ encryptedRequest,
185
+ requestDate,
186
+ onSuccess,
187
+ onRejection,
188
+ theme = 'system'
189
+ }) => {
190
+ const iframeRef = useRef<HTMLIFrameElement>(null);
191
+
192
+ useEffect(() => {
193
+ const handleMessage = (event: MessageEvent) => {
194
+ // Verify origin for security
195
+ if (event.origin !== 'https://saafe-app.com') return;
196
+
197
+ // Process messages from the iframe
198
+ if (event.data.type === 'saafe:success') {
199
+ onSuccess?.();
200
+ } else if (event.data.type === 'saafe:rejection') {
201
+ onRejection?.();
202
+ }
203
+ };
204
+
205
+ window.addEventListener('message', handleMessage);
206
+ return () => window.removeEventListener('message', handleMessage);
207
+ }, [onSuccess, onRejection]);
208
+
209
+ const safeUrl = `https://saafe-app.com/login?fi=${encodeURIComponent(financialInstitutionId)}&ecreq=${encodeURIComponent(encryptedRequest)}&reqdate=${encodeURIComponent(requestDate)}&platform=web&theme=${theme}`;
210
+
211
+ return (
212
+ <iframe
213
+ ref={iframeRef}
214
+ src={safeUrl}
215
+ style={{ width: '100%', height: '600px', border: 'none' }}
216
+ title="SAAFE Account Linking"
217
+ allow="camera; microphone"
218
+ />
219
+ );
220
+ };
221
+
222
+ export default SAFERedirection;
223
+ ```
224
+
225
+ ## URL Parameters Reference
226
+
227
+ | Parameter | Description | Valid Values | Required |
228
+ |-----------|-------------|-------------|----------|
229
+ | fi | Financial Institution ID | String | Yes |
230
+ | ecreq | Encrypted Request | String | Yes |
231
+ | reqdate | Request Date | String | Yes |
232
+ | profile | User Profile | String | No |
233
+ | platform | Client Platform | ios, android, react-native, flutter, web | No |
234
+ | theme | Application Theme | light, dark, system | No |
235
+
236
+ ### Detailed Parameter Information
237
+
238
+ #### Financial Institution ID (fi)
239
+
240
+ Unique identifier for the financial institution being accessed. This is provided by the SAAFE platform.
241
+
242
+ #### Encrypted Request (ecreq)
243
+
244
+ A JWT-encoded request payload that contains:
245
+ - User identification information
246
+ - Request scope (what data is being requested)
247
+ - Expiration time
248
+ - Signature
249
+
250
+ The encryption ensures that request parameters cannot be tampered with.
251
+
252
+ #### Request Date (reqdate)
253
+
254
+ ISO8601 formatted date-time string that indicates when the request was initiated. Used for security validation.
255
+
256
+ #### Platform (platform)
257
+
258
+ Identifies the client platform for optimized display and behavior:
259
+ - **ios**: iOS-specific optimizations (status bar handling, iOS-style UI)
260
+ - **android**: Android optimizations
261
+ - **react-native**: React Native WebView optimizations
262
+ - **flutter**: Flutter WebView optimizations
263
+ - **web**: Standard web experience
264
+
265
+ #### Theme (theme)
266
+
267
+ Controls the visual theme:
268
+ - **light**: Forces light theme
269
+ - **dark**: Forces dark theme
270
+ - **system**: Uses device theme preference (default)
271
+
272
+ ## Security Considerations
273
+
274
+ ### Cross-Origin Restrictions
275
+
276
+ When embedding the SAAFE Redirection Flow in a web application via an iframe, be aware of potential cross-origin restrictions. The application handles document displays to avoid cross-origin issues.
277
+
278
+ ### Navigation Flow Protection
279
+
280
+ The SAAFE Redirection Flow includes navigation protection to warn users before exiting a flow in progress. This helps prevent accidental cancellations.
281
+
282
+ ### Secure Communication
283
+
284
+ For mobile WebViews, use the provided URL interception patterns to securely communicate the flow outcome back to your application.
285
+
286
+ ## Callback Handling
287
+
288
+ ### Success Callback
289
+
290
+ When an account linking flow completes successfully, the application navigates to the `/success` route. For iframe integrations, a message is posted to the parent window. For WebViews, you can intercept this URL to handle success in your native application.
291
+
292
+ ### Rejection Callback
293
+
294
+ If the user rejects the consent, the application navigates to the `/rejected` route. Similar to the success case, messages are posted for iframes and the URL can be intercepted in WebViews.
295
+
296
+ ## Styling and Customization
297
+
298
+ ### Custom Styling
299
+
300
+ You can provide custom styling parameters via the URL:
301
+ - Primary button color
302
+ - Background colors
303
+ - Font styles
304
+
305
+ These are applied via CSS variables at runtime.
306
+
307
+ ## Testing
308
+
309
+ To test your integration, you can use the following test credentials:
310
+
311
+ - Financial Institution ID: `test_fi`
312
+ - Encrypted Request: `test_encrypted_request`
313
+ - Request Date: Current timestamp
314
+
315
+ ## Troubleshooting
316
+
317
+ ### Common Issues
318
+
319
+ 1. **Blank Screen**: Ensure all required URL parameters are provided and correctly encoded.
320
+ 2. **Navigation Issues**: If the flow doesn't complete, check your URL interception logic in WebViews.
321
+ 3. **Cross-Origin Errors**: For web iframe integration, ensure your domain is whitelisted.
322
+
323
+ ### Support
324
+
325
+ For further assistance, contact the SAAFE support team at support@saafe-platform.com.