Skip to content

Commit 18d42d5

Browse files
feat: add flutter example
feat: bootstrap flutter app
1 parent c9f0888 commit 18d42d5

134 files changed

Lines changed: 5625 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

examples/flutter_app/.gitignore

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.build/
9+
.buildlog/
10+
.history
11+
.svn/
12+
.swiftpm/
13+
migrate_working_dir/
14+
15+
# IntelliJ related
16+
*.iml
17+
*.ipr
18+
*.iws
19+
.idea/
20+
21+
# The .vscode folder contains launch configuration and tasks you configure in
22+
# VS Code which you may wish to be included in version control, so this line
23+
# is commented out by default.
24+
#.vscode/
25+
26+
# Flutter/Dart/Pub related
27+
**/doc/api/
28+
.dart_tool/
29+
.flutter-plugins
30+
.flutter-plugins-dependencies
31+
.packages
32+
.pub-cache/
33+
.pub/
34+
/build/
35+
**/build/
36+
37+
# Android related
38+
**/gradle-wrapper.jar
39+
**/android/.gradle
40+
**/android/captures/
41+
**/android/gradlew
42+
**/android/gradlew.bat
43+
**/android/local.properties
44+
**/android/**/GeneratedPluginRegistrant.*
45+
46+
# iOS/XCode related
47+
**/ios/**/*.mode1v3
48+
**/ios/**/*.mode2v3
49+
**/ios/**/*.moved-aside
50+
**/ios/**/*.pbxuser
51+
**/ios/**/*.perspectivev3
52+
**/ios/**/*sync/
53+
**/ios/**/.sconsign.dblite
54+
**/ios/**/.tags*
55+
**/ios/**/.vagrant/
56+
**/ios/**/DerivedData/
57+
**/ios/**/Icon?
58+
**/ios/**/Pods/
59+
**/ios/**/.symlinks/
60+
**/ios/**/profile
61+
**/ios/**/xcuserdata
62+
**/ios/.generated/
63+
**/ios/Flutter/App.framework
64+
**/ios/Flutter/Flutter.framework
65+
**/ios/Flutter/Generated.xcconfig
66+
**/ios/Flutter/app.flx
67+
**/ios/Flutter/app.zip
68+
**/ios/Flutter/flutter_assets/
69+
**/ios/Flutter/flutter_export_environment.sh
70+
**/ios/ServiceDefinitions.json
71+
**/ios/Runner/GeneratedPluginRegistrant.*
72+
73+
# Web related
74+
**/web/**/lib/generated_plugin_registrant.dart
75+
76+
# Service account files
77+
svc-keyfile.json
78+
79+
# Lockfiles
80+
Podfile.lock
81+
pubspec.lock
82+
yarn.lock
83+
84+
# Exceptions to above rules.
85+
!**/ios/**/default.mode1v3
86+
!**/ios/**/default.mode2v3
87+
!**/ios/**/default.pbxuser
88+
!**/ios/**/default.perspectivev3
89+
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

examples/flutter_app/.metadata

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: "be698c48a6750c8cb8e61c740ca9991bb947aba2"
8+
channel: "stable"
9+
10+
project_type: app
11+
12+
# Tracks metadata for the flutter migrate command
13+
migration:
14+
platforms:
15+
- platform: root
16+
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
17+
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
18+
- platform: android
19+
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
20+
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
21+
- platform: ios
22+
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
23+
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
24+
- platform: linux
25+
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
26+
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
27+
- platform: macos
28+
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
29+
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
30+
- platform: web
31+
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
32+
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
33+
- platform: windows
34+
create_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
35+
base_revision: be698c48a6750c8cb8e61c740ca9991bb947aba2
36+
37+
# User provided section
38+
39+
# List of Local paths (relative to this file) that should be
40+
# ignored by the migrate tool.
41+
#
42+
# Files that are not part of the templates will be ignored by default.
43+
unmanaged_files:
44+
- 'lib/main.dart'
45+
- 'ios/Runner.xcodeproj/project.pbxproj'

examples/flutter_app/README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Flutter OpenID Connect Example
2+
3+
A Flutter mobile app demonstrating the **Authorization Code Flow with PKCE** using OpenID Connect. This example mirrors the architecture of the [react-spa](../react-spa) example, translated to Flutter idioms.
4+
5+
## Prerequisites
6+
7+
- Flutter SDK >= 3.8.0
8+
- An OpenID Connect provider (defaults to [CerberAuth testid](https://testid.cerberauth.com))
9+
10+
## Setup
11+
12+
### 1. Install dependencies
13+
14+
```bash
15+
flutter pub get
16+
```
17+
18+
### 2. Configure environment
19+
20+
Edit `assets/.env`:
21+
22+
```dotenv
23+
OIDC_ISSUER=https://testid.cerberauth.com
24+
OIDC_CLIENT_ID=c6c0c0ec-09e0-448e-a856-3e596c3bdd9d
25+
OIDC_REDIRECT_URL=com.example.flutterapp://callback
26+
OIDC_POST_LOGOUT_REDIRECT_URL=com.example.flutterapp://
27+
```
28+
29+
### 3. Register the redirect URI
30+
31+
Register `com.example.flutterapp://callback` as a redirect URI in your OIDC provider's client configuration.
32+
33+
### 4. Run the app
34+
35+
```bash
36+
# Android
37+
flutter run
38+
39+
# iOS (requires macOS with Xcode)
40+
flutter run -d ios
41+
```
42+
43+
## Configuration
44+
45+
| Variable | Description |
46+
|---|---|
47+
| `OIDC_ISSUER` | Base URL of your OIDC provider |
48+
| `OIDC_CLIENT_ID` | Client ID registered with the provider |
49+
| `OIDC_REDIRECT_URL` | Custom scheme redirect URI for the app |
50+
| `OIDC_POST_LOGOUT_REDIRECT_URL` | URI to return to after logout |
51+
52+
## Architecture
53+
54+
This example mirrors the react-spa pattern mapping:
55+
56+
| React SPA | Flutter |
57+
|---|---|
58+
| `AuthProvider.tsx` + `context.ts` | `lib/auth/auth_state.dart` (ChangeNotifier) |
59+
| `useAuth.ts` hook | `lib/auth/auth_service.dart` |
60+
| `AuthProvider` wrapping app | `ChangeNotifierProvider` + `ProxyProvider` in `main.dart` |
61+
| `home.tsx` | `lib/screens/home_screen.dart` |
62+
| `Button.tsx` | `lib/widgets/app_button.dart` |
63+
| Vite `.env` | `assets/.env` via `flutter_dotenv` |
64+
65+
### Key files
66+
67+
- **`lib/auth/auth_state.dart`** — Holds all authentication state; notifies the widget tree on changes
68+
- **`lib/auth/auth_service.dart`** — Implements `initialize()`, `login()`, and `logout()` using `flutter_appauth`
69+
- **`lib/screens/home_screen.dart`** — Main screen; shows login button or user profile depending on auth state
70+
- **`lib/widgets/app_button.dart`** — Reusable styled button component
71+
72+
## Running Tests
73+
74+
```bash
75+
flutter test
76+
```
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# This file configures the analyzer, which statically analyzes Dart code to
2+
# check for errors, warnings, and lints.
3+
#
4+
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5+
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6+
# invoked from the command line by running `flutter analyze`.
7+
8+
# The following line activates a set of recommended lints for Flutter apps,
9+
# packages, and plugins designed to encourage good coding practices.
10+
include: package:flutter_lints/flutter.yaml
11+
12+
linter:
13+
# The lint rules applied to this project can be customized in the
14+
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
15+
# included above or to enable additional rules. A list of all available lints
16+
# and their documentation is published at https://dart.dev/lints.
17+
#
18+
# Instead of disabling a lint rule for the entire project in the
19+
# section below, it can also be suppressed for a single line of code
20+
# or a specific dart file by using the `// ignore: name_of_lint` and
21+
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
22+
# producing the lint.
23+
rules:
24+
# avoid_print: false # Uncomment to disable the `avoid_print` rule
25+
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
26+
27+
# Additional information about this file can be found at
28+
# https://dart.dev/guides/language/analysis-options
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
gradle-wrapper.jar
2+
/.gradle
3+
/captures/
4+
/gradlew
5+
/gradlew.bat
6+
/local.properties
7+
GeneratedPluginRegistrant.java
8+
.cxx/
9+
10+
# Remember to never publicly share your keystore.
11+
# See https://flutter.dev/to/reference-keystore
12+
key.properties
13+
**/*.keystore
14+
**/*.jks
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
plugins {
2+
id("com.android.application")
3+
id("kotlin-android")
4+
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5+
id("dev.flutter.flutter-gradle-plugin")
6+
}
7+
8+
android {
9+
namespace = "com.example.flutter_app"
10+
compileSdk = flutter.compileSdkVersion
11+
ndkVersion = flutter.ndkVersion
12+
13+
compileOptions {
14+
sourceCompatibility = JavaVersion.VERSION_11
15+
targetCompatibility = JavaVersion.VERSION_11
16+
}
17+
18+
kotlinOptions {
19+
jvmTarget = JavaVersion.VERSION_11.toString()
20+
}
21+
22+
defaultConfig {
23+
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24+
applicationId = "com.example.flutter_app"
25+
// You can update the following values to match your application needs.
26+
// For more information, see: https://flutter.dev/to/review-gradle-config.
27+
minSdk = flutter.minSdkVersion
28+
targetSdk = flutter.targetSdkVersion
29+
versionCode = flutter.versionCode
30+
versionName = flutter.versionName
31+
}
32+
33+
buildTypes {
34+
release {
35+
// TODO: Add your own signing config for the release build.
36+
// Signing with the debug keys for now, so `flutter run --release` works.
37+
signingConfig = signingConfigs.getByName("debug")
38+
}
39+
}
40+
}
41+
42+
flutter {
43+
source = "../.."
44+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<!-- The INTERNET permission is required for development. Specifically,
3+
the Flutter tool needs it to communicate with the running application
4+
to allow setting breakpoints, to provide hot reload, etc.
5+
-->
6+
<uses-permission android:name="android.permission.INTERNET"/>
7+
</manifest>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<uses-permission android:name="android.permission.INTERNET"/>
3+
<application
4+
android:label="flutter_app"
5+
android:name="${applicationName}"
6+
android:icon="@mipmap/ic_launcher">
7+
<activity
8+
android:name=".MainActivity"
9+
android:exported="true"
10+
android:launchMode="singleTop"
11+
android:taskAffinity=""
12+
android:theme="@style/LaunchTheme"
13+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
14+
android:hardwareAccelerated="true"
15+
android:windowSoftInputMode="adjustResize">
16+
<!-- Specifies an Android theme to apply to this Activity as soon as
17+
the Android process has started. This theme is visible to the user
18+
while the Flutter UI initializes. After that, this theme continues
19+
to determine the Window background behind the Flutter UI. -->
20+
<meta-data
21+
android:name="io.flutter.embedding.android.NormalTheme"
22+
android:resource="@style/NormalTheme"
23+
/>
24+
<intent-filter>
25+
<action android:name="android.intent.action.MAIN"/>
26+
<category android:name="android.intent.category.LAUNCHER"/>
27+
</intent-filter>
28+
<intent-filter android:label="flutter_appauth">
29+
<action android:name="android.intent.action.VIEW" />
30+
<category android:name="android.intent.category.DEFAULT" />
31+
<category android:name="android.intent.category.BROWSABLE" />
32+
<data android:scheme="com.example.flutterapp" android:host="callback" />
33+
</intent-filter>
34+
</activity>
35+
<!-- Don't delete the meta-data below.
36+
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
37+
<meta-data
38+
android:name="flutterEmbedding"
39+
android:value="2" />
40+
</application>
41+
<!-- Required to query activities that can process text, see:
42+
https://developer.android.com/training/package-visibility and
43+
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
44+
45+
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
46+
<queries>
47+
<intent>
48+
<action android:name="android.intent.action.PROCESS_TEXT"/>
49+
<data android:mimeType="text/plain"/>
50+
</intent>
51+
</queries>
52+
</manifest>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.example.flutter_app
2+
3+
import io.flutter.embedding.android.FlutterActivity
4+
5+
class MainActivity : FlutterActivity()
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Modify this file to customize your launch splash screen -->
3+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:drawable="?android:colorBackground" />
5+
6+
<!-- You can insert your own image assets here -->
7+
<!-- <item>
8+
<bitmap
9+
android:gravity="center"
10+
android:src="@mipmap/launch_image" />
11+
</item> -->
12+
</layer-list>

0 commit comments

Comments
 (0)