├── openidconnect ├── example │ ├── linux │ │ ├── .gitignore │ │ ├── main.cc │ │ ├── flutter │ │ │ ├── generated_plugin_registrant.h │ │ │ ├── generated_plugin_registrant.cc │ │ │ ├── generated_plugins.cmake │ │ │ └── CMakeLists.txt │ │ ├── my_application.h │ │ ├── my_application.cc │ │ └── CMakeLists.txt │ ├── ios │ │ ├── Runner │ │ │ ├── Runner-Bridging-Header.h │ │ │ ├── Assets.xcassets │ │ │ │ ├── LaunchImage.imageset │ │ │ │ │ ├── LaunchImage.png │ │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ │ ├── README.md │ │ │ │ │ └── Contents.json │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ │ └── Contents.json │ │ │ ├── AppDelegate.swift │ │ │ ├── Base.lproj │ │ │ │ ├── Main.storyboard │ │ │ │ └── LaunchScreen.storyboard │ │ │ └── Info.plist │ │ ├── Flutter │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ └── AppFrameworkInfo.plist │ │ ├── Runner.xcodeproj │ │ │ ├── project.xcworkspace │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata │ │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ ├── Runner.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── .gitignore │ │ └── Podfile │ ├── android │ │ ├── gradle.properties │ │ ├── app │ │ │ ├── src │ │ │ │ ├── main │ │ │ │ │ ├── res │ │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ │ ├── drawable │ │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ │ ├── values │ │ │ │ │ │ │ └── styles.xml │ │ │ │ │ │ └── values-night │ │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── kotlin │ │ │ │ │ │ └── com │ │ │ │ │ │ │ └── example │ │ │ │ │ │ │ ├── example │ │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ │ │ │ └── openidconnect_example │ │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ ├── debug │ │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── profile │ │ │ │ │ └── AndroidManifest.xml │ │ │ └── build.gradle │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ └── gradle-wrapper.properties │ │ ├── .gitignore │ │ ├── settings.gradle │ │ └── build.gradle │ ├── macos │ │ ├── .gitignore │ │ ├── Runner │ │ │ ├── Configs │ │ │ │ ├── Debug.xcconfig │ │ │ │ ├── Release.xcconfig │ │ │ │ ├── Warnings.xcconfig │ │ │ │ └── AppInfo.xcconfig │ │ │ ├── Assets.xcassets │ │ │ │ └── AppIcon.appiconset │ │ │ │ │ ├── app_icon_16.png │ │ │ │ │ ├── app_icon_32.png │ │ │ │ │ ├── app_icon_64.png │ │ │ │ │ ├── app_icon_1024.png │ │ │ │ │ ├── app_icon_128.png │ │ │ │ │ ├── app_icon_256.png │ │ │ │ │ ├── app_icon_512.png │ │ │ │ │ └── Contents.json │ │ │ ├── AppDelegate.swift │ │ │ ├── Release.entitlements │ │ │ ├── DebugProfile.entitlements │ │ │ ├── MainFlutterWindow.swift │ │ │ └── Info.plist │ │ ├── Flutter │ │ │ ├── Flutter-Debug.xcconfig │ │ │ ├── Flutter-Release.xcconfig │ │ │ └── GeneratedPluginRegistrant.swift │ │ ├── Runner.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── Runner.xcodeproj │ │ │ ├── project.xcworkspace │ │ │ │ └── xcshareddata │ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ └── Podfile │ ├── web │ │ ├── favicon.png │ │ ├── icons │ │ │ ├── Icon-192.png │ │ │ └── Icon-512.png │ │ ├── manifest.json │ │ ├── callback.html │ │ └── index.html │ ├── windows │ │ ├── runner │ │ │ ├── resources │ │ │ │ └── app_icon.ico │ │ │ ├── resource.h │ │ │ ├── CMakeLists.txt │ │ │ ├── utils.h │ │ │ ├── runner.exe.manifest │ │ │ ├── run_loop.h │ │ │ ├── flutter_window.h │ │ │ ├── main.cpp │ │ │ ├── utils.cpp │ │ │ ├── flutter_window.cpp │ │ │ ├── run_loop.cpp │ │ │ ├── Runner.rc │ │ │ └── win32_window.h │ │ ├── .gitignore │ │ ├── flutter │ │ │ ├── generated_plugin_registrant.h │ │ │ ├── generated_plugin_registrant.cc │ │ │ ├── generated_plugins.cmake │ │ │ └── CMakeLists.txt │ │ └── CMakeLists.txt │ ├── lib │ │ ├── client.dart │ │ ├── credentials.dart │ │ ├── main.dart │ │ ├── choose.dart │ │ ├── identity_view.dart │ │ ├── redirectloop_result_page.dart │ │ ├── device.dart │ │ └── interactive.dart │ ├── .metadata │ ├── README.md │ ├── pubspec.yaml │ ├── analysis_options.yaml │ ├── .gitignore │ └── test │ │ └── widget_test.dart ├── .metadata ├── lib │ ├── src │ │ ├── models │ │ │ ├── responses │ │ │ │ ├── token_response.dart │ │ │ │ ├── device_code_response.dart │ │ │ │ └── authorization_response.dart │ │ │ ├── requests │ │ │ │ ├── user_info_request.dart │ │ │ │ ├── user_registration_request.dart │ │ │ │ ├── refresh_request.dart │ │ │ │ ├── logout_request.dart │ │ │ │ ├── password_authorization_request.dart │ │ │ │ ├── logout_token_request.dart │ │ │ │ ├── interactive_logout_request.dart │ │ │ │ ├── device_authorization_request.dart │ │ │ │ ├── token_request.dart │ │ │ │ ├── revoke_token_request.dart │ │ │ │ └── interactive_authorization_request.dart │ │ │ ├── event.dart │ │ │ └── identity.dart │ │ ├── android_ios.dart │ │ └── helpers.dart │ └── .gitignore ├── analysis_options.yaml ├── pubspec.yaml ├── test │ └── openidconnect_test.dart ├── .gitignore └── README.md ├── .vscode ├── settings.json └── launch.json ├── openidconnect_windows ├── CHANGELOG.md ├── test │ └── openidconnect_windows_test.dart ├── .metadata ├── README.md ├── .gitignore ├── pubspec.yaml ├── analysis_options.yaml └── lib │ └── openidconnect_windows.dart ├── openidconnect_web ├── test │ └── openidconnect_web_test.dart ├── .metadata ├── README.md ├── analysis_options.yaml ├── CHANGELOG.md ├── callback.html ├── .gitignore ├── pubspec.yaml └── lib │ └── openidconnect_web.dart ├── openidconnect_platform_interface ├── README.md ├── lib │ ├── src │ │ ├── exceptions │ │ │ ├── logout_exception.dart │ │ │ ├── revoke_exception.dart │ │ │ ├── user_info_exception.dart │ │ │ ├── authentication_exception.dart │ │ │ ├── http_response_exception.dart │ │ │ └── openidconnect_exception.dart │ │ └── method_channel_openidconnect.dart │ └── openidconnect_platform_interface.dart ├── .metadata ├── test │ ├── openidconnect_platform_mock.dart │ └── openidconnect_platform_interface_test.dart ├── pubspec.yaml ├── analysis_options.yaml ├── CHANGELOG.md └── .gitignore ├── .gitignore └── README.md /openidconnect/example/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.configureOnOpen": false 3 | } 4 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /openidconnect/example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /openidconnect/example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/xcuserdata/ 7 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /openidconnect/example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/web/favicon.png -------------------------------------------------------------------------------- /openidconnect_windows/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [0.0.6] - December 10th, 2021 2 | 3 | - Initial release for windows. This uses webview_windows for web view support. 4 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /openidconnect/example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /openidconnect/example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /openidconnect_web/test/openidconnect_web_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | TestWidgetsFlutterBinding.ensureInitialized(); 5 | } 6 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /openidconnect_windows/test/openidconnect_windows_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | TestWidgetsFlutterBinding.ensureInitialized(); 5 | } 6 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/README.md: -------------------------------------------------------------------------------- 1 | # openidconnect_platform_interface 2 | 3 | Platform interface for the openidconnect library for flutter. For usage instructions please see https://pub.dev/openidconnect. 4 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /openidconnect/example/lib/client.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ClientPage extends StatelessWidget { 4 | @override 5 | Widget build(BuildContext context) { 6 | throw UnimplementedError(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /openidconnect/example/linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/src/exceptions/logout_exception.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect_platform_interface; 2 | 3 | class LogoutException extends OpenIdConnectException { 4 | LogoutException([String? errorMessage]) : super(errorMessage); 5 | } 6 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/src/exceptions/revoke_exception.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect_platform_interface; 2 | 3 | class RevokeException extends OpenIdConnectException { 4 | RevokeException([String? errorMessage]) : super(errorMessage); 5 | } 6 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/kotlin/com/example/openidconnect_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.openidconnect_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/4D-Technologies/openidconnect_flutter/HEAD/openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/src/exceptions/user_info_exception.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect_platform_interface; 2 | 3 | class UserInfoException extends OpenIdConnectException { 4 | UserInfoException([String? errorMessage]) : super(errorMessage); 5 | } 6 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/src/exceptions/authentication_exception.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect_platform_interface; 2 | 3 | class AuthenticationException extends OpenIdConnectException { 4 | AuthenticationException([String? errorMessage]) : super(errorMessage); 5 | } 6 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /openidconnect/example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /openidconnect/example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/src/exceptions/http_response_exception.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect_platform_interface; 2 | 3 | class HttpResponseException implements Exception { 4 | final String? errorMessage; 5 | HttpResponseException([this.errorMessage]); 6 | 7 | @override 8 | String toString() => errorMessage ?? "Unknown"; 9 | } 10 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/src/exceptions/openidconnect_exception.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect_platform_interface; 2 | 3 | abstract class OpenIdConnectException implements Exception { 4 | final String? errorMessage; 5 | OpenIdConnectException([this.errorMessage]); 6 | 7 | @override 8 | String toString() => errorMessage ?? "Unknown"; 9 | } 10 | -------------------------------------------------------------------------------- /openidconnect/.metadata: -------------------------------------------------------------------------------- 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: f4abaa0735eba4dfd8f33f73363911d63931fe03 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /openidconnect/example/.metadata: -------------------------------------------------------------------------------- 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: f4abaa0735eba4dfd8f33f73363911d63931fe03 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /openidconnect_web/.metadata: -------------------------------------------------------------------------------- 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: f4abaa0735eba4dfd8f33f73363911d63931fe03 8 | channel: stable 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /openidconnect_windows/.metadata: -------------------------------------------------------------------------------- 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: cf4400006550b70f28e4b4af815151d1e74846c6 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/responses/token_response.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class TokenResponse { 4 | final String tokenType; 5 | final Map? additionalProperties; 6 | final DateTime expiresAt; 7 | 8 | const TokenResponse({ 9 | required this.tokenType, 10 | required this.expiresAt, 11 | this.additionalProperties, 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/user_info_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class UserInfoRequest { 4 | final String accessToken; 5 | final OpenIdConfiguration configuration; 6 | final String tokenType; 7 | 8 | const UserInfoRequest({ 9 | required this.accessToken, 10 | required this.configuration, 11 | this.tokenType = "Bearer", 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/.metadata: -------------------------------------------------------------------------------- 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: f4abaa0735eba4dfd8f33f73363911d63931fe03 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /openidconnect/example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/user_registration_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class UserRegistrationRequest { 4 | final String accessToken; 5 | final OpenIdConfiguration configuration; 6 | final String tokenType; 7 | 8 | const UserRegistrationRequest({ 9 | required this.accessToken, 10 | required this.configuration, 11 | this.tokenType = "Bearer", 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /openidconnect/example/linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /openidconnect/example/windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /openidconnect_windows/README.md: -------------------------------------------------------------------------------- 1 | # openidconnect_windows 2 | 3 | Windows implementation for the Flutter OpenIdConnect package. For usage instructions please see https://pub.dev/openidconnect. 4 | 5 | Because this project is endorsed by the openidconnect project, you need not add it to your pubspec.yaml, only the root openidconnect dependancy. 6 | 7 | **Note** 8 | This package will be depreciated once windows support is natively added to webview. 9 | -------------------------------------------------------------------------------- /openidconnect/example/windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | 11 | void RegisterPlugins(flutter::PluginRegistry* registry) { 12 | UrlLauncherWindowsRegisterWithRegistrar( 13 | registry->GetRegistrarForPlugin("UrlLauncherWindows")); 14 | } 15 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /openidconnect/example/lib/credentials.dart: -------------------------------------------------------------------------------- 1 | final defaultDiscoveryUrl = 2 | "https://localhost:15112/.well-known/openid-configuration"; 3 | final defaultClientId = "Scribe"; 4 | final String? defaultClientSecret = "scribe321!"; 5 | final List defaultAudience = ["fieldservice"]; 6 | final defaultRedirectUrl = "http://localhost:15503/callback.html"; 7 | final defaultscopes = ["openid", "profile", "email", "offline_access"]; 8 | final defaultEncryptionKey = "example123456789"; 9 | -------------------------------------------------------------------------------- /openidconnect_web/README.md: -------------------------------------------------------------------------------- 1 | # openidconnect_web 2 | 3 | Web implementation for the Flutter OpenIdConnect package. For usage instructions please see https://pub.dev/packages/openidconnect. 4 | 5 | Because this project is endorsed by the openidconnect project, you need not add it to your pubspec.yaml, only the root openidconnect dependancy. 6 | 7 | **Note** 8 | Ensure that you copy the callback.html file into your web folder of your project so that interactive authentication will work correctly. 9 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /openidconnect/example/linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/test/openidconnect_platform_mock.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:mockito/mockito.dart'; 3 | import 'package:openidconnect_platform_interface/openidconnect_platform_interface.dart'; 4 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 5 | 6 | class MockMethodChannel extends Mock implements MethodChannel {} 7 | 8 | class MockOpenIdConnectPlatform extends Mock 9 | with MockPlatformInterfaceMixin 10 | implements OpenIdConnectPlatform {} 11 | -------------------------------------------------------------------------------- /openidconnect/example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /openidconnect/example/linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | 11 | void fl_register_plugins(FlPluginRegistry* registry) { 12 | g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = 13 | fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); 14 | url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); 15 | } 16 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: openidconnect_platform_interface 2 | description: Platform interface for OpenIdConnect. 3 | version: 1.0.17 4 | homepage: https://github.com/4D-Technologies/openidconnect_flutter/tree/main/openidconnect_platform_interface 5 | 6 | environment: 7 | sdk: ">=3.5.3 <4.0.0" 8 | flutter: ">=3.1.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | plugin_platform_interface: ^2.1.8 14 | 15 | dev_dependencies: 16 | flutter_lints: ^6.0.0 17 | mockito: ^5.5.1 18 | flutter_test: 19 | sdk: flutter 20 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/event.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | enum AuthEventTypes { Error, Success, LoggingOut, NotLoggedIn, Refresh } 4 | 5 | @immutable 6 | class AuthEvent { 7 | final AuthEventTypes type; 8 | final String? message; 9 | const AuthEvent(this.type, {this.message}); 10 | 11 | @override 12 | operator ==(Object o) { 13 | if (identical(this, o)) return true; 14 | return o is AuthEvent && o.type == type && o.message == message; 15 | } 16 | 17 | @override 18 | int get hashCode => type.hashCode ^ (message?.hashCode ?? 0); 19 | } 20 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/refresh_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class RefreshRequest extends TokenRequest { 4 | RefreshRequest({ 5 | required super.clientId, 6 | super.clientSecret, 7 | required super.scopes, 8 | required String refreshToken, 9 | required super.configuration, 10 | Map? additionalParameters, 11 | bool autoRefresh = true, 12 | }) : super( 13 | grantType: "refresh_token", 14 | additionalParameters: { 15 | "refresh_token": refreshToken, 16 | ...?additionalParameters, 17 | }, 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/test/openidconnect_platform_interface_test.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter_test/flutter_test.dart'; 2 | 3 | // import 'package:openidconnect_platform_interface/openidconnect_platform_interface.dart'; 4 | 5 | import 'package:flutter_test/flutter_test.dart'; 6 | import 'package:openidconnect_platform_interface/openidconnect_platform_interface.dart'; 7 | 8 | import 'openidconnect_platform_mock.dart'; 9 | 10 | void main() { 11 | TestWidgetsFlutterBinding.ensureInitialized(); 12 | final mock = MockOpenIdConnectPlatform(); 13 | OpenIdConnectPlatform.instance = mock; 14 | 15 | //Run tests here 16 | } 17 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import shared_preferences_foundation 9 | import url_launcher_macos 10 | import webview_flutter_wkwebview 11 | 12 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 13 | SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) 14 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) 15 | WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) 16 | } 17 | -------------------------------------------------------------------------------- /openidconnect/example/README.md: -------------------------------------------------------------------------------- 1 | # openidconnect_example 2 | 3 | Demonstrates how to use the openidconnect plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /openidconnect_windows/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 25 | /pubspec.lock 26 | **/doc/api/ 27 | .dart_tool/ 28 | .packages 29 | build/ 30 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/logout_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class LogoutRequest { 4 | final String idToken; 5 | final String? postLogoutRedirectUri; 6 | final String? state; 7 | final OpenIdConfiguration configuration; 8 | 9 | const LogoutRequest({ 10 | required this.idToken, 11 | this.postLogoutRedirectUri, 12 | this.state, 13 | required this.configuration, 14 | }); 15 | 16 | Map toMap() { 17 | return { 18 | "id_token_hint": idToken, 19 | if (postLogoutRedirectUri != null) 20 | "post_logout_redirect_uri": postLogoutRedirectUri!, 21 | if (state != null) "state": state!, 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /openidconnect/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:openidconnect_example/choose.dart'; 3 | 4 | void main() { 5 | runApp(MyApp()); 6 | } 7 | 8 | //Credentials gathered from the playground 9 | //login: dull-moth@example.com 10 | //password: Yawning-Octopus-58 11 | 12 | class MyApp extends StatefulWidget { 13 | @override 14 | _MyAppState createState() => _MyAppState(); 15 | } 16 | 17 | class _MyAppState extends State { 18 | @override 19 | void initState() { 20 | super.initState(); 21 | } 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return MaterialApp( 26 | home: ChoosePage(), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2021 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(runner LANGUAGES CXX) 3 | 4 | add_executable(${BINARY_NAME} WIN32 5 | "flutter_window.cpp" 6 | "main.cpp" 7 | "run_loop.cpp" 8 | "utils.cpp" 9 | "win32_window.cpp" 10 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 11 | "Runner.rc" 12 | "runner.exe.manifest" 13 | ) 14 | apply_standard_settings(${BINARY_NAME}) 15 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 16 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 17 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 18 | add_dependencies(${BINARY_NAME} flutter_assemble) 19 | -------------------------------------------------------------------------------- /openidconnect/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: openidconnect_example 2 | description: Demonstrates how to use the openidconnect plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: "none" # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: '>=3.5.3 <4.0.0' 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | openidconnect: 16 | path: ../ 17 | 18 | cupertino_icons: ^1.0.8 19 | 20 | dev_dependencies: 21 | flutter_lints: ^6.0.0 22 | flutter_test: 23 | sdk: flutter 24 | 25 | flutter: 26 | uses-material-design: true 27 | -------------------------------------------------------------------------------- /openidconnect_windows/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: openidconnect_windows 2 | description: Windows implementation for OpenIdConnect. 3 | version: 0.0.7 4 | homepage: https://github.com/Concerti-IO/openidconnect_flutter/tree/main/openidconnect_windows 5 | 6 | environment: 7 | sdk: ">=3.1.4 <4.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | openidconnect_platform_interface: ^1.0.16 13 | webview_windows: ^0.4.0 14 | 15 | dev_dependencies: 16 | flutter_lints: ^5.0.0 17 | flutter_test: 18 | sdk: flutter 19 | 20 | flutter: 21 | plugin: 22 | implements: openidconnect 23 | platforms: 24 | windows: 25 | dartPluginClass: OpenIdConnectWindows 26 | fileName: openidconnect_windows.dart 27 | -------------------------------------------------------------------------------- /openidconnect/example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | tasks.register("clean", Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /openidconnect/example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/ephemeral/ 22 | Flutter/app.flx 23 | Flutter/app.zip 24 | Flutter/flutter_assets/ 25 | Flutter/flutter_export_environment.sh 26 | ServiceDefinitions.json 27 | Runner/GeneratedPluginRegistrant.* 28 | 29 | # Exceptions to above rules. 30 | !default.mode1v3 31 | !default.mode2v3 32 | !default.pbxuser 33 | !default.perspectivev3 34 | -------------------------------------------------------------------------------- /openidconnect/example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openidconnect_example", 3 | "short_name": "openidconnect_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "Demonstrates how to use the openidconnect plugin.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/password_authorization_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class PasswordAuthorizationRequest extends TokenRequest { 4 | PasswordAuthorizationRequest({ 5 | required super.clientId, 6 | super.clientSecret, 7 | required super.scopes, 8 | required String userName, 9 | required String password, 10 | required super.configuration, 11 | required bool autoRefresh, 12 | super.prompts, 13 | Map? additionalParameters, 14 | }) : super( 15 | grantType: "password", 16 | additionalParameters: { 17 | "username": userName, 18 | "password": password, 19 | ...?additionalParameters, 20 | }, 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/logout_token_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class LogoutTokenRequest { 4 | final String refreshToken; 5 | final String? clientId; 6 | final String? clientSecret; 7 | final String? redirectUrl; 8 | final OpenIdConfiguration configuration; 9 | 10 | const LogoutTokenRequest({ 11 | required this.configuration, 12 | required this.refreshToken, 13 | this.clientId, 14 | this.clientSecret, 15 | this.redirectUrl, 16 | }); 17 | 18 | Map toMap() { 19 | var map = {"refresh_token": refreshToken}; 20 | if (clientId != null) map = {"client_id": clientId!, ...map}; 21 | if (clientSecret != null) map = {"client_secret": clientSecret!, ...map}; 22 | if (redirectUrl != null) map = {"redirect_uri": redirectUrl!, ...map}; 23 | return map; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/interactive_logout_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class InteractiveLogoutRequest { 4 | final String idToken; 5 | final OpenIdConfiguration configuration; 6 | final int popupWidth; 7 | final int popupHeight; 8 | final bool useWebPopup; 9 | final String postLogoutRedirectUrl; 10 | final String? state; 11 | 12 | InteractiveLogoutRequest({ 13 | required this.configuration, 14 | required this.idToken, 15 | required this.postLogoutRedirectUrl, 16 | this.popupWidth = 640, 17 | this.popupHeight = 480, 18 | this.useWebPopup = true, 19 | this.state, 20 | }); 21 | 22 | Map toMap() { 23 | return { 24 | "id_token_hint": idToken, 25 | "post_logout_redirect_uri": postLogoutRedirectUrl, 26 | if (state != null) "state": state!, 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /openidconnect_web/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false 6 | constant_identifier_names: ALL_CAPS_WITH_UNDERSCORES 7 | overridden_fields: true 8 | iterable_contains_unrelated_type: true 9 | camel_case_types: true 10 | 11 | analyzer: 12 | language: 13 | strict-inference: true 14 | strict-raw-types: true 15 | strong-mode: 16 | implicit-casts: false 17 | implicit-dynamic: false 18 | errors: 19 | unused_element: error 20 | unused_import: error 21 | unused_local_variable: error 22 | invalid_assignment: error 23 | missing_return: error 24 | dead_code: info 25 | todo: ignore 26 | exclude: 27 | - "**/*.freezed.dart" 28 | - "**/*.g.dart" 29 | - "**/*.config.dart" 30 | - "**/generated_plugin_registrant.dart" 31 | -------------------------------------------------------------------------------- /openidconnect/example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false 6 | constant_identifier_names: ALL_CAPS_WITH_UNDERSCORES 7 | overridden_fields: true 8 | iterable_contains_unrelated_type: true 9 | camel_case_types: true 10 | 11 | analyzer: 12 | language: 13 | strict-inference: true 14 | strict-raw-types: true 15 | strong-mode: 16 | implicit-casts: false 17 | implicit-dynamic: false 18 | errors: 19 | unused_element: error 20 | unused_import: error 21 | unused_local_variable: error 22 | invalid_assignment: error 23 | missing_return: error 24 | dead_code: info 25 | todo: ignore 26 | exclude: 27 | - "**/*.freezed.dart" 28 | - "**/*.g.dart" 29 | - "**/*.config.dart" 30 | - "**/generated_plugin_registrant.dart" 31 | -------------------------------------------------------------------------------- /openidconnect_windows/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false 6 | constant_identifier_names: ALL_CAPS_WITH_UNDERSCORES 7 | overridden_fields: true 8 | iterable_contains_unrelated_type: true 9 | camel_case_types: true 10 | 11 | analyzer: 12 | language: 13 | strict-inference: true 14 | strict-raw-types: true 15 | strong-mode: 16 | implicit-casts: false 17 | implicit-dynamic: false 18 | errors: 19 | unused_element: error 20 | unused_import: error 21 | unused_local_variable: error 22 | invalid_assignment: error 23 | missing_return: error 24 | dead_code: info 25 | todo: ignore 26 | exclude: 27 | - "**/*.freezed.dart" 28 | - "**/*.g.dart" 29 | - "**/*.config.dart" 30 | - "**/generated_plugin_registrant.dart" 31 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false 6 | constant_identifier_names: ALL_CAPS_WITH_UNDERSCORES 7 | overridden_fields: true 8 | iterable_contains_unrelated_type: true 9 | camel_case_types: true 10 | 11 | analyzer: 12 | language: 13 | strict-inference: true 14 | strict-raw-types: true 15 | strong-mode: 16 | implicit-casts: false 17 | implicit-dynamic: false 18 | errors: 19 | unused_element: error 20 | unused_import: error 21 | unused_local_variable: error 22 | invalid_assignment: error 23 | missing_return: error 24 | dead_code: info 25 | todo: ignore 26 | exclude: 27 | - "**/*.freezed.dart" 28 | - "**/*.g.dart" 29 | - "**/*.config.dart" 30 | - "**/generated_plugin_registrant.dart" 31 | -------------------------------------------------------------------------------- /openidconnect/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false 6 | constant_identifier_names: ALL_CAPS_WITH_UNDERSCORES 7 | overridden_fields: true 8 | iterable_contains_unrelated_type: true 9 | camel_case_types: true 10 | 11 | analyzer: 12 | language: 13 | strict-inference: true 14 | strict-raw-types: true 15 | strict-casts: false 16 | strong-mode: 17 | implicit-casts: false 18 | implicit-dynamic: false 19 | errors: 20 | unused_element: error 21 | unused_import: error 22 | unused_local_variable: error 23 | invalid_assignment: error 24 | missing_return: error 25 | dead_code: info 26 | todo: ignore 27 | exclude: 28 | - "**/*.freezed.dart" 29 | - "**/*.g.dart" 30 | - "**/*.config.dart" 31 | - "**/generated_plugin_registrant.dart" 32 | -------------------------------------------------------------------------------- /openidconnect/example/linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | url_launcher_linux 7 | ) 8 | 9 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 10 | ) 11 | 12 | set(PLUGIN_BUNDLED_LIBRARIES) 13 | 14 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 15 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 16 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 19 | endforeach(plugin) 20 | 21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 22 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 23 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 24 | endforeach(ffi_plugin) 25 | -------------------------------------------------------------------------------- /openidconnect/example/windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | url_launcher_windows 7 | ) 8 | 9 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 10 | ) 11 | 12 | set(PLUGIN_BUNDLED_LIBRARIES) 13 | 14 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 15 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 16 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 19 | endforeach(plugin) 20 | 21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 22 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 23 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 24 | endforeach(ffi_plugin) 25 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/device_authorization_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class DeviceAuthorizationRequest { 4 | final OpenIdConfiguration configuration; 5 | final String clientId; 6 | final String? clientSecret; 7 | final Iterable scopes; 8 | final String? audience; 9 | final Map? additionalParameters; 10 | 11 | const DeviceAuthorizationRequest({ 12 | required this.clientId, 13 | required this.scopes, 14 | required this.audience, 15 | required this.configuration, 16 | this.clientSecret, 17 | this.additionalParameters, 18 | }); 19 | 20 | Map toMap() { 21 | return { 22 | "client_id": clientId, 23 | "scope": scopes.join(" "), 24 | if (audience != null) "audience": audience!, 25 | if (clientSecret != null) "client_secret": clientSecret!, 26 | ...?additionalParameters 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /openidconnect/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [1.0.17] - April 1st 2025 4 | 5 | - Update dependencies 6 | 7 | ## [1.0.16] - December 4th 2024 8 | 9 | - Update dependencies 10 | 11 | ## [1.0.15] - February 7th 2024 12 | 13 | - Update dependencies 14 | 15 | ## [1.0.14] - October 29th, 2023 16 | 17 | - Update dependencies 18 | 19 | ## [1.0.13] - November 10th, 2022 20 | 21 | - Update dependencies 22 | 23 | ## [1.0.11] - December 9th, 2021 24 | 25 | - Add Build context to the authorizeInteractive method 26 | 27 | ## [1.0.4] - November 29th, 2021 28 | 29 | - Update dependencies 30 | 31 | ## [1.0.3] - September 10th, 2021 32 | 33 | - Update to Dart 2.14 34 | - Add linting 35 | - Fix mokito dependency being in the wrong area. 36 | 37 | ## 1.0.2 38 | 39 | - Expanded the response for processStartup 40 | - Add parameters for if a web login redirect loop should be used 41 | 42 | ## 1.0.1 43 | 44 | - Add processStartup to handle web redirect loop. 45 | 46 | ## 1.0.0 47 | 48 | - Initial Release 49 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/token_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | abstract class TokenRequest { 4 | final String clientId; 5 | final String? clientSecret; 6 | 7 | final String grantType; 8 | final Iterable scopes; 9 | final Map? additionalParameters; 10 | final Iterable? prompts; 11 | final OpenIdConfiguration configuration; 12 | 13 | const TokenRequest({ 14 | required this.clientId, 15 | this.clientSecret, 16 | required this.scopes, 17 | required this.grantType, 18 | this.additionalParameters, 19 | this.prompts, 20 | required this.configuration, 21 | }); 22 | 23 | @mustCallSuper 24 | Map toMap() { 25 | return { 26 | "client_id": clientId, 27 | "grant_type": grantType, 28 | "scope": scopes.join(" "), 29 | if (prompts != null && prompts!.isNotEmpty) 'prompt': prompts!.join(' '), 30 | if (clientSecret != null) "client_secret": clientSecret!, 31 | ...?additionalParameters 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /openidconnect/example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:openidconnect_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && 22 | widget.data!.startsWith('Running on:'), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /openidconnect_web/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [1.0.26] - April 1st 2025 4 | 5 | - Dependency Update 6 | 7 | ## [1.0.25] - December 4th 2024 8 | 9 | - Remove dart:html for wasm support 10 | 11 | ## [1.0.24] - December 4th 2024 12 | 13 | - Update dependencies 14 | 15 | ## [1.0.23] - February 7th 2024 16 | 17 | - Update dependencies 18 | 19 | ## [1.0.22] - October 29th, 2023 20 | 21 | - Update dependencies 22 | 23 | ## [1.0.21] - November 10th, 2022 24 | 25 | - Update dependencies 26 | 27 | ## [1.0.19] - December 9th, 2021 28 | 29 | - Update to new interface and fix errors. 30 | 31 | ## [1.0.12] - November 29th, 2021 32 | 33 | - Update dependencies 34 | 35 | ## [1.0.11] - September 10, 2021 36 | 37 | - Updated to Dart 2.14 38 | - Added linting 39 | 40 | ## [1.0.10] 41 | 42 | - Add the endorsement directive in the pubspec.yaml 43 | 44 | ## 1.0.9 45 | 46 | - Implement redirect loop functionality in addition to the default web popup. 47 | 48 | ## 1.0.7 49 | 50 | - Fix readme instructions 51 | 52 | ## 1.0.6 53 | 54 | - Initial Release 55 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/src/method_channel_openidconnect.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect_platform_interface; 2 | 3 | const MethodChannel _channel = 4 | MethodChannel('plugins.concerti.io/openidconnect'); 5 | 6 | class MethodChannelOpenIdConnect extends OpenIdConnectPlatform { 7 | @override 8 | Future authorizeInteractive({ 9 | required BuildContext context, 10 | required String title, 11 | required String authorizationUrl, 12 | required String redirectUrl, 13 | required int popupWidth, 14 | required int popupHeight, 15 | bool useWebRedirectLoop = false, 16 | }) => 17 | _channel.invokeMethod('authorizeInteractive', { 18 | "title": "title", 19 | "authorizationUrl": authorizationUrl, 20 | "redirectUrl": redirectUrl, 21 | "popupWidth": popupWidth, 22 | "popupHeight": popupHeight, 23 | "useWebRedirectLoop": useWebRedirectLoop, 24 | }); 25 | 26 | @override 27 | Future processStartup() => 28 | _channel.invokeMethod("processStartup"); 29 | } 30 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/revoke_token_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | enum TokenType { idToken, accessToken, refreshToken } 4 | 5 | class RevokeTokenRequest { 6 | final OpenIdConfiguration configuration; 7 | final String token; 8 | final TokenType tokenType; 9 | final String? clientId; 10 | final String? clientSecret; 11 | 12 | const RevokeTokenRequest({ 13 | required this.configuration, 14 | required this.token, 15 | required this.tokenType, 16 | this.clientId, 17 | this.clientSecret, 18 | }) : assert(tokenType != TokenType.idToken, "ID Tokens cannot be revoked."); 19 | 20 | Map toMap({bool useBasicAuth = true}) { 21 | var map = { 22 | "token": token, 23 | "token_type_hint": tokenType == TokenType.accessToken 24 | ? "access_token" 25 | : "refresh_token", 26 | }; 27 | if (!useBasicAuth && clientId != null) 28 | map = {"client_id": clientId!, ...map}; 29 | if (!useBasicAuth && clientSecret != null) 30 | map = {"client_secret": clientSecret!, ...map}; 31 | return map; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/run_loop.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_RUN_LOOP_H_ 2 | #define RUNNER_RUN_LOOP_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | // A runloop that will service events for Flutter instances as well 10 | // as native messages. 11 | class RunLoop { 12 | public: 13 | RunLoop(); 14 | ~RunLoop(); 15 | 16 | // Prevent copying 17 | RunLoop(RunLoop const&) = delete; 18 | RunLoop& operator=(RunLoop const&) = delete; 19 | 20 | // Runs the run loop until the application quits. 21 | void Run(); 22 | 23 | // Registers the given Flutter instance for event servicing. 24 | void RegisterFlutterInstance( 25 | flutter::FlutterEngine* flutter_instance); 26 | 27 | // Unregisters the given Flutter instance from event servicing. 28 | void UnregisterFlutterInstance( 29 | flutter::FlutterEngine* flutter_instance); 30 | 31 | private: 32 | using TimePoint = std::chrono::steady_clock::time_point; 33 | 34 | // Processes all currently pending messages for registered Flutter instances. 35 | TimePoint ProcessFlutterMessages(); 36 | 37 | std::set flutter_instances_; 38 | }; 39 | 40 | #endif // RUNNER_RUN_LOOP_H_ 41 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/responses/device_code_response.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class DeviceCodeResponse { 4 | final String deviceCode; 5 | final String userCode; 6 | final String verificationUrl; 7 | final String verificationUrlComplete; 8 | final DateTime expiresAt; 9 | final int pollingInterval; 10 | final String? qrCodeUrl; 11 | 12 | DeviceCodeResponse._({ 13 | required this.deviceCode, 14 | required this.userCode, 15 | required this.verificationUrl, 16 | required this.expiresAt, 17 | required this.pollingInterval, 18 | required this.verificationUrlComplete, 19 | this.qrCodeUrl, 20 | }); 21 | 22 | factory DeviceCodeResponse.fromJson(Map json) => 23 | DeviceCodeResponse._( 24 | deviceCode: json["device_code"].toString(), 25 | userCode: json["user_code"].toString(), 26 | verificationUrl: json["verification_url"].toString(), 27 | expiresAt: 28 | DateTime.now().add(Duration(seconds: json["expires_in"] as int)), 29 | pollingInterval: (json["interval"] ?? 5) as int, 30 | verificationUrlComplete: json["verification_uri_complete"].toString(), 31 | qrCodeUrl: json['qr_code']?.toString(), 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /openidconnect/example/web/callback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/responses/authorization_response.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class AuthorizationResponse extends TokenResponse { 4 | final String accessToken; 5 | final String? refreshToken; 6 | final String idToken; 7 | final String? state; 8 | 9 | AuthorizationResponse({ 10 | required this.accessToken, 11 | required this.idToken, 12 | this.refreshToken, 13 | this.state, 14 | required String tokenType, 15 | required DateTime expiresAt, 16 | Map? additionalProperties, 17 | }) : super( 18 | tokenType: tokenType, 19 | expiresAt: expiresAt, 20 | additionalProperties: additionalProperties, 21 | ); 22 | 23 | factory AuthorizationResponse.fromJson( 24 | Map json, { 25 | String? state, 26 | }) => 27 | AuthorizationResponse( 28 | accessToken: json["access_token"].toString(), 29 | tokenType: json["token_type"].toString(), 30 | idToken: json["id_token"].toString(), 31 | refreshToken: json["refresh_token"]?.toString(), 32 | expiresAt: DateTime.now().add( 33 | Duration(seconds: (json['expires_in'] as int?) ?? 0), 34 | ), 35 | additionalProperties: json, 36 | state: state, 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "run_loop.h" 10 | #include "win32_window.h" 11 | 12 | // A window that does nothing but host a Flutter view. 13 | class FlutterWindow : public Win32Window { 14 | public: 15 | // Creates a new FlutterWindow driven by the |run_loop|, hosting a 16 | // Flutter view running |project|. 17 | explicit FlutterWindow(RunLoop* run_loop, 18 | const flutter::DartProject& project); 19 | virtual ~FlutterWindow(); 20 | 21 | protected: 22 | // Win32Window: 23 | bool OnCreate() override; 24 | void OnDestroy() override; 25 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 26 | LPARAM const lparam) noexcept override; 27 | 28 | private: 29 | // The run loop driving events for this window. 30 | RunLoop* run_loop_; 31 | 32 | // The project to run. 33 | flutter::DartProject project_; 34 | 35 | // The Flutter instance hosted by this window. 36 | std::unique_ptr flutter_controller_; 37 | }; 38 | 39 | #endif // RUNNER_FLUTTER_WINDOW_H_ 40 | -------------------------------------------------------------------------------- /openidconnect_web/callback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /openidconnect/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: openidconnect 2 | description: OpenIdConnect library for flutter. 3 | version: 1.0.42 4 | homepage: https://github.com/4D-Technologies/openidconnect_flutter 5 | 6 | environment: 7 | sdk: ">=3.8.0 <4.0.0" 8 | flutter: ">=3.5.3" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | flutter_web_plugins: 14 | sdk: flutter 15 | openidconnect_platform_interface: ^1.0.17 16 | openidconnect_web: ^1.0.26 17 | # openidconnect_windows: ^0.0.6 18 | jwt_decoder: ^2.0.1 19 | 20 | url_launcher: ^6.3.2 21 | http: ^1.5.0 22 | retry: ^3.1.2 23 | 24 | # TODO Remove these once native implementations can be added. Refactor so that the native implementations don't need to do the full cycle through. 25 | webview_flutter: ^4.13.0 26 | encrypt_shared_preferences: ^0.9.10 27 | cryptography_plus: ^2.7.1 28 | 29 | dev_dependencies: 30 | flutter_lints: 31 | flutter_test: 32 | sdk: flutter 33 | mockito: 34 | 35 | # For information on the generic Dart part of this file, see the 36 | # following page: https://dart.dev/tools/pub/pubspec 37 | 38 | # The following section is specific to Flutter. 39 | flutter: 40 | plugin: 41 | platforms: 42 | web: 43 | default_package: openidconnect_web 44 | # windows: 45 | # default_package: openidconnect_windows 46 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "example", 9 | "cwd": "openidconnect\\example", 10 | "request": "launch", 11 | "type": "dart", 12 | "args": [ 13 | "--web-enable-expression-evaluation", 14 | "--disable-web-security", 15 | "--web-port", 16 | "62568" 17 | ] 18 | }, 19 | { 20 | "name": "example chrome", 21 | "cwd": "openidconnect\\example", 22 | "request": "launch", 23 | "type": "dart", 24 | "args": [ 25 | "-d", 26 | "chrome", 27 | "--web-port", 28 | "15503", 29 | "--web-browser-flag", 30 | "--disable-web-security", 31 | "--web-browser-flag", 32 | "--user-data-dir=%temp%/search" 33 | ] 34 | }, 35 | { 36 | "name": "example (profile mode)", 37 | "cwd": "openidconnect\\example", 38 | "request": "launch", 39 | "type": "dart", 40 | "flutterMode": "profile", 41 | "args": [ 42 | "--web-enable-expression-evaluation", 43 | "--web-port", 44 | "62568" 45 | ] 46 | } 47 | ] 48 | } -------------------------------------------------------------------------------- /openidconnect/test/openidconnect_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | import 'package:openidconnect/openidconnect.dart'; 4 | 5 | const TEST_ID_TOKEN = 6 | "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; 7 | 8 | void main() { 9 | group("openididentity", () { 10 | test("save identity", () async { 11 | final identity = OpenIdIdentity( 12 | accessToken: "testing_access_token", 13 | expiresAt: DateTime.now(), 14 | idToken: TEST_ID_TOKEN, 15 | tokenType: "Bearer", 16 | ); 17 | 18 | await identity.save(); 19 | }); 20 | 21 | test("load identity", () async { 22 | final identity = OpenIdIdentity( 23 | accessToken: "testing_access_token", 24 | expiresAt: DateTime.now(), 25 | idToken: TEST_ID_TOKEN, 26 | tokenType: "Bearer", 27 | ); 28 | 29 | await identity.save(); 30 | 31 | final loaded = await OpenIdIdentity.load(); 32 | expect(loaded, isNot(null)); 33 | }); 34 | }); 35 | // test('adds one to input values', () { 36 | // final calculator = Calculator(); 37 | // expect(calculator.addOne(2), 3); 38 | // expect(calculator.addOne(-7), -6); 39 | // expect(calculator.addOne(0), 1); 40 | // }); 41 | } 42 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "run_loop.h" 7 | #include "utils.h" 8 | 9 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 10 | _In_ wchar_t *command_line, _In_ int show_command) { 11 | // Attach to console when present (e.g., 'flutter run') or create a 12 | // new console when running with a debugger. 13 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 14 | CreateAndAttachConsole(); 15 | } 16 | 17 | // Initialize COM, so that it is available for use in the library and/or 18 | // plugins. 19 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 20 | 21 | RunLoop run_loop; 22 | 23 | flutter::DartProject project(L"data"); 24 | 25 | std::vector command_line_arguments = 26 | GetCommandLineArguments(); 27 | 28 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 29 | 30 | FlutterWindow window(&run_loop, project); 31 | Win32Window::Point origin(10, 10); 32 | Win32Window::Size size(1280, 720); 33 | if (!window.CreateAndShow(L"example", origin, size)) { 34 | return EXIT_FAILURE; 35 | } 36 | window.SetQuitOnClose(true); 37 | 38 | run_loop.Run(); 39 | 40 | ::CoUninitialize(); 41 | return EXIT_SUCCESS; 42 | } 43 | -------------------------------------------------------------------------------- /openidconnect/example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | testapp 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.14' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | 32 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 33 | target 'RunnerTests' do 34 | inherit! :search_paths 35 | end 36 | end 37 | 38 | post_install do |installer| 39 | installer.pods_project.targets.each do |target| 40 | flutter_additional_macos_build_settings(target) 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '12.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | 33 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 34 | target 'RunnerTests' do 35 | inherit! :search_paths 36 | end 37 | end 38 | 39 | post_install do |installer| 40 | installer.pods_project.targets.each do |target| 41 | flutter_additional_ios_build_settings(target) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | openidconnect_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/ephemeral 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | -------------------------------------------------------------------------------- /openidconnect/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/ephemeral 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | -------------------------------------------------------------------------------- /openidconnect/lib/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/ephemeral 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | -------------------------------------------------------------------------------- /openidconnect_web/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/ephemeral 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/ephemeral 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | -------------------------------------------------------------------------------- /openidconnect/lib/src/android_ios.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class OpenIdConnectAndroidiOS { 4 | static Future authorizeInteractive({ 5 | required BuildContext context, 6 | required String title, 7 | required String authorizationUrl, 8 | required String redirectUrl, 9 | required int popupWidth, 10 | required int popupHeight, 11 | }) async { 12 | final controller = WebViewController() 13 | ..setJavaScriptMode(JavaScriptMode.unrestricted); 14 | 15 | //Create the url 16 | final result = await showDialog( 17 | context: context, 18 | barrierDismissible: false, 19 | builder: (dialogContext) { 20 | return AlertDialog( 21 | actions: [ 22 | IconButton( 23 | onPressed: () => Navigator.pop(dialogContext, null), 24 | icon: Icon(Icons.close), 25 | ), 26 | ], 27 | content: Container( 28 | width: 29 | min(popupWidth.toDouble(), MediaQuery.of(context).size.width), 30 | height: 31 | min(popupHeight.toDouble(), MediaQuery.of(context).size.height), 32 | child: flutterWebView.WebViewWidget( 33 | controller: controller 34 | ..setNavigationDelegate( 35 | NavigationDelegate( 36 | onPageFinished: (String url) { 37 | if (url.startsWith(redirectUrl)) { 38 | Navigator.pop(dialogContext, url); 39 | } 40 | }, 41 | ), 42 | ) 43 | ..loadRequest(Uri.parse(authorizationUrl)), 44 | ), 45 | ), 46 | title: Text(title), 47 | ); 48 | }, 49 | ); 50 | 51 | if (result == null) throw AuthenticationException(ERROR_USER_CLOSED); 52 | 53 | return result; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /openidconnect_platform_interface/lib/openidconnect_platform_interface.dart: -------------------------------------------------------------------------------- 1 | library openidconnect_platform_interface; 2 | 3 | import 'dart:async'; 4 | 5 | import 'package:flutter/services.dart'; 6 | import 'package:flutter/widgets.dart'; 7 | import 'package:plugin_platform_interface/plugin_platform_interface.dart'; 8 | 9 | part './src/method_channel_openidconnect.dart'; 10 | part './src/exceptions/authentication_exception.dart'; 11 | part './src/exceptions/http_response_exception.dart'; 12 | part './src/exceptions/logout_exception.dart'; 13 | part './src/exceptions/openidconnect_exception.dart'; 14 | part './src/exceptions/revoke_exception.dart'; 15 | part './src/exceptions/user_info_exception.dart'; 16 | 17 | const String AUTHORIZE_ERROR_MESSAGE_FORMAT = 18 | "Failed to authorize: [error: %1, description: %2]"; 19 | const String AUTHORIZE_ERROR_CODE = "authorize_failed"; 20 | const String ERROR_MESSAGE_FORMAT = 21 | "Request Failed: [error: request_failed, description: %2]"; 22 | const ERROR_USER_CLOSED = "user_closed"; 23 | const ERROR_INVALID_RESPONSE = "invalid_response"; 24 | 25 | abstract class OpenIdConnectPlatform extends PlatformInterface { 26 | static final Object _token = Object(); 27 | 28 | OpenIdConnectPlatform() : super(token: _token); 29 | 30 | static OpenIdConnectPlatform _instance = MethodChannelOpenIdConnect(); 31 | 32 | static OpenIdConnectPlatform get instance => _instance; 33 | 34 | static set instance(OpenIdConnectPlatform instance) { 35 | PlatformInterface.verifyToken(instance, _token); 36 | _instance = instance; 37 | } 38 | 39 | Future authorizeInteractive({ 40 | required BuildContext context, 41 | required String title, 42 | required String authorizationUrl, 43 | required String redirectUrl, 44 | required int popupWidth, 45 | required int popupHeight, 46 | bool useWebRedirectLoop = false, 47 | }); 48 | 49 | Future processStartup(); 50 | } 51 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | if (target_length == 0) { 52 | return std::string(); 53 | } 54 | std::string utf8_string; 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 30 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.example.openidconnect_example" 38 | minSdkVersion flutter.minSdkVersion 39 | targetSdkVersion 30 40 | versionCode flutterVersionCode.toInteger() 41 | versionName flutterVersionName 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | 57 | dependencies { 58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 59 | implementation 'com.google.android.material:material:1.4.0' 60 | } 61 | -------------------------------------------------------------------------------- /openidconnect/example/lib/choose.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:openidconnect_example/client.dart'; 3 | import 'device.dart'; 4 | import 'interactive.dart'; 5 | import 'password.dart'; 6 | import 'redirectloop_result_page.dart'; 7 | 8 | class ChoosePage extends StatelessWidget { 9 | @override 10 | Widget build(BuildContext context) { 11 | return Scaffold( 12 | appBar: AppBar( 13 | title: const Text('Choose Your OpenIdConnect Flow'), 14 | ), 15 | body: Center( 16 | child: Column( 17 | children: [ 18 | TextButton( 19 | onPressed: () => Navigator.of(context).push( 20 | MaterialPageRoute( 21 | builder: (context) => InteractivePage(), 22 | ), 23 | ), 24 | child: Text("Interactive Authorization Code PKCE"), 25 | ), 26 | TextButton( 27 | onPressed: () => Navigator.of(context).push( 28 | MaterialPageRoute( 29 | builder: (context) => DeviceCodePage(), 30 | ), 31 | ), 32 | child: Text("Device Code"), 33 | ), 34 | TextButton( 35 | onPressed: () => Navigator.of(context).push( 36 | MaterialPageRoute( 37 | builder: (context) => PasswordPage(), 38 | ), 39 | ), 40 | child: Text("Password"), 41 | ), 42 | TextButton( 43 | onPressed: () => Navigator.of(context).push( 44 | MaterialPageRoute( 45 | builder: (context) => ClientPage(), 46 | ), 47 | ), 48 | child: Text("Client Usage Example"), 49 | ), 50 | TextButton( 51 | onPressed: () => Navigator.of(context).push( 52 | MaterialPageRoute( 53 | builder: (context) => RedirectLoopResultPage(), 54 | ), 55 | ), 56 | child: Text("Redirect Loop Result Page"), 57 | ), 58 | ], 59 | ), 60 | ), 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(RunLoop* run_loop, 8 | const flutter::DartProject& project) 9 | : run_loop_(run_loop), project_(project) {} 10 | 11 | FlutterWindow::~FlutterWindow() {} 12 | 13 | bool FlutterWindow::OnCreate() { 14 | if (!Win32Window::OnCreate()) { 15 | return false; 16 | } 17 | 18 | RECT frame = GetClientArea(); 19 | 20 | // The size here must match the window dimensions to avoid unnecessary surface 21 | // creation / destruction in the startup path. 22 | flutter_controller_ = std::make_unique( 23 | frame.right - frame.left, frame.bottom - frame.top, project_); 24 | // Ensure that basic setup of the controller was successful. 25 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 26 | return false; 27 | } 28 | RegisterPlugins(flutter_controller_->engine()); 29 | run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); 30 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 31 | return true; 32 | } 33 | 34 | void FlutterWindow::OnDestroy() { 35 | if (flutter_controller_) { 36 | run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); 37 | flutter_controller_ = nullptr; 38 | } 39 | 40 | Win32Window::OnDestroy(); 41 | } 42 | 43 | LRESULT 44 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 45 | WPARAM const wparam, 46 | LPARAM const lparam) noexcept { 47 | // Give Flutter, including plugins, an opportunity to handle window messages. 48 | if (flutter_controller_) { 49 | std::optional result = 50 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 51 | lparam); 52 | if (result) { 53 | return *result; 54 | } 55 | } 56 | 57 | switch (message) { 58 | case WM_FONTCHANGE: 59 | flutter_controller_->engine()->ReloadSystemFonts(); 60 | break; 61 | } 62 | 63 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 64 | } 65 | -------------------------------------------------------------------------------- /openidconnect/lib/src/helpers.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | Future?> httpRetry( 4 | FutureOr Function() fn, { 5 | Duration delayFactor = const Duration(milliseconds: 200), 6 | double randomizationFactor = 0.25, 7 | Duration maxDelay = const Duration(seconds: 30), 8 | int maxAttempts = 8, 9 | FutureOr Function(Exception)? retryIf, 10 | FutureOr Function(Exception)? onRetry, 11 | }) async { 12 | var attempt = 1; 13 | while (true) { 14 | final options = RetryOptions( 15 | delayFactor: delayFactor, 16 | randomizationFactor: randomizationFactor, 17 | maxDelay: maxDelay, 18 | maxAttempts: maxAttempts, 19 | ); 20 | 21 | var result = await options.retry(fn, 22 | retryIf: retryIf ?? (e) => e is IOException || e is TimeoutException, 23 | onRetry: onRetry); 24 | 25 | if (result.statusCode == 503 || 26 | result.statusCode == 502 || 27 | result.statusCode == 504) { 28 | if (attempt >= maxAttempts) { 29 | throw HttpException( 30 | "The server could not be reached. Please try again later."); 31 | } 32 | await Future.delayed(options.delay(attempt)); 33 | attempt++; 34 | continue; 35 | } 36 | 37 | final body = result.body.isEmpty 38 | ? "{}" 39 | : result.body.startsWith("{") 40 | ? result.body 41 | : result.body.startsWith("?; 46 | 47 | if (result.statusCode < 200 || result.statusCode >= 300) { 48 | if (jsonResponse!["error"] != null) { 49 | var error = jsonResponse["error"].toString(); 50 | if (jsonResponse["error_description"] != null) 51 | error += ": ${jsonResponse["error_description"]}"; 52 | throw HttpResponseException( 53 | ERROR_MESSAGE_FORMAT.replaceAll("%2", error)); 54 | } else { 55 | throw HttpResponseException( 56 | ERROR_MESSAGE_FORMAT.replaceAll("%2", "unknown_error")); 57 | } 58 | } 59 | 60 | return result.body.isEmpty ? null : jsonResponse; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /openidconnect/example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/run_loop.cpp: -------------------------------------------------------------------------------- 1 | #include "run_loop.h" 2 | 3 | #include 4 | 5 | #include 6 | 7 | RunLoop::RunLoop() {} 8 | 9 | RunLoop::~RunLoop() {} 10 | 11 | void RunLoop::Run() { 12 | bool keep_running = true; 13 | TimePoint next_flutter_event_time = TimePoint::clock::now(); 14 | while (keep_running) { 15 | std::chrono::nanoseconds wait_duration = 16 | std::max(std::chrono::nanoseconds(0), 17 | next_flutter_event_time - TimePoint::clock::now()); 18 | ::MsgWaitForMultipleObjects( 19 | 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), 20 | QS_ALLINPUT); 21 | bool processed_events = false; 22 | MSG message; 23 | // All pending Windows messages must be processed; MsgWaitForMultipleObjects 24 | // won't return again for items left in the queue after PeekMessage. 25 | while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { 26 | processed_events = true; 27 | if (message.message == WM_QUIT) { 28 | keep_running = false; 29 | break; 30 | } 31 | ::TranslateMessage(&message); 32 | ::DispatchMessage(&message); 33 | // Allow Flutter to process messages each time a Windows message is 34 | // processed, to prevent starvation. 35 | next_flutter_event_time = 36 | std::min(next_flutter_event_time, ProcessFlutterMessages()); 37 | } 38 | // If the PeekMessage loop didn't run, process Flutter messages. 39 | if (!processed_events) { 40 | next_flutter_event_time = 41 | std::min(next_flutter_event_time, ProcessFlutterMessages()); 42 | } 43 | } 44 | } 45 | 46 | void RunLoop::RegisterFlutterInstance( 47 | flutter::FlutterEngine* flutter_instance) { 48 | flutter_instances_.insert(flutter_instance); 49 | } 50 | 51 | void RunLoop::UnregisterFlutterInstance( 52 | flutter::FlutterEngine* flutter_instance) { 53 | flutter_instances_.erase(flutter_instance); 54 | } 55 | 56 | RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { 57 | TimePoint next_event_time = TimePoint::max(); 58 | for (auto instance : flutter_instances_) { 59 | std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); 60 | if (wait_duration != std::chrono::nanoseconds::max()) { 61 | next_event_time = 62 | std::min(next_event_time, TimePoint::clock::now() + wait_duration); 63 | } 64 | } 65 | return next_event_time; 66 | } 67 | -------------------------------------------------------------------------------- /openidconnect_web/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: openidconnect_web 2 | description: Web implementation for OpenIdConnect. 3 | version: 1.0.26 4 | homepage: https://github.com/4D-Technologies/openidconnect_flutter/tree/main/openidconnect_web 5 | 6 | environment: 7 | sdk: ">=3.5.3 <4.0.0" 8 | flutter: ">=3.4.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | flutter_web_plugins: 14 | sdk: flutter 15 | openidconnect_platform_interface: ^1.0.17 16 | web: ^1.1.1 17 | 18 | dev_dependencies: 19 | flutter_lints: ^5.0.0 20 | flutter_test: 21 | sdk: flutter 22 | 23 | # For information on the generic Dart part of this file, see the 24 | # following page: https://dart.dev/tools/pub/pubspec 25 | 26 | # The following section is specific to Flutter. 27 | flutter: 28 | # This section identifies this Flutter project as a plugin project. 29 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily 30 | # be modified. They are used by the tooling to maintain consistency when 31 | # adding or updating assets for this project. 32 | plugin: 33 | implements: openidconnect 34 | platforms: 35 | web: 36 | pluginClass: OpenIdConnectWeb 37 | fileName: openidconnect_web.dart 38 | # To add assets to your plugin package, add an assets section, like this: 39 | # assets: 40 | # - images/a_dot_burr.jpeg 41 | # - images/a_dot_ham.jpeg 42 | # 43 | # For details regarding assets in packages, see 44 | # https://flutter.dev/assets-and-images/#from-packages 45 | # 46 | # An image asset can refer to one or more resolution-specific "variants", see 47 | # https://flutter.dev/assets-and-images/#resolution-aware. 48 | # To add custom fonts to your plugin package, add a fonts section here, 49 | # in this "flutter" section. Each entry in this list should have a 50 | # "family" key with the font family name, and a "fonts" key with a 51 | # list giving the asset and other descriptors for the font. For 52 | # example: 53 | # fonts: 54 | # - family: Schyler 55 | # fonts: 56 | # - asset: fonts/Schyler-Regular.ttf 57 | # - asset: fonts/Schyler-Italic.ttf 58 | # style: italic 59 | # - family: Trajan Pro 60 | # fonts: 61 | # - asset: fonts/TrajanPro.ttf 62 | # - asset: fonts/TrajanPro_Bold.ttf 63 | # weight: 700 64 | # 65 | # For details regarding fonts in packages, see 66 | # https://flutter.dev/custom-fonts/#from-packages 67 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /openidconnect_web/lib/openidconnect_web.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:web/web.dart' as html; 4 | 5 | // In order to *not* need this ignore, consider extracting the "web" version 6 | // of your plugin as a separate package, instead of inlining it in the same 7 | // package as the core of your plugin. 8 | // ignore: avoid_web_libraries_in_flutter 9 | import 'package:flutter/widgets.dart'; 10 | import 'package:flutter_web_plugins/flutter_web_plugins.dart'; 11 | import 'package:openidconnect_platform_interface/openidconnect_platform_interface.dart'; 12 | 13 | /// A web implementation of the OpenidconnectWeb plugin. 14 | class OpenIdConnectWeb extends OpenIdConnectPlatform { 15 | static void registerWith(Registrar registrar) { 16 | OpenIdConnectPlatform.instance = OpenIdConnectWeb(); 17 | } 18 | 19 | @override 20 | Future authorizeInteractive({ 21 | required BuildContext context, 22 | required String title, 23 | required String authorizationUrl, 24 | required String redirectUrl, 25 | required int popupWidth, 26 | required int popupHeight, 27 | bool useWebRedirectLoop = false, 28 | }) async { 29 | if (useWebRedirectLoop) { 30 | const AUTH_DESTINATION_KEY = "openidconnect_auth_destination_url"; 31 | html.window.sessionStorage 32 | .setItem(AUTH_DESTINATION_KEY, html.window.location.toString()); 33 | html.window.location.assign(authorizationUrl); 34 | return Future.value(null); 35 | } 36 | 37 | final top = (html.window.outerHeight - popupHeight) / 2 + 38 | (html.window.screen.availHeight); 39 | final left = (html.window.outerWidth - popupWidth) / 2 + 40 | (html.window.screen.availWidth); 41 | 42 | var options = 43 | 'width=${popupWidth},height=${popupHeight},toolbar=no,location=no,directories=no,status=no,menubar=no,copyhistory=no&top=$top,left=$left'; 44 | 45 | final child = html.window.open( 46 | authorizationUrl, 47 | "open_id_connect_authentication", 48 | options, 49 | ); 50 | 51 | final c = new Completer(); 52 | html.window.onMessage.first.then((event) { 53 | final url = event.data.toString(); 54 | c.complete(url); 55 | child?.close(); 56 | }); 57 | 58 | return c.future; 59 | } 60 | 61 | @override 62 | Future processStartup() async { 63 | const AUTH_RESPONSE_KEY = "openidconnect_auth_response_info"; 64 | 65 | final url = html.window.sessionStorage.getItem(AUTH_RESPONSE_KEY); 66 | html.window.sessionStorage.removeItem(AUTH_RESPONSE_KEY); 67 | 68 | return url; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /openidconnect/example/lib/identity_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:openidconnect/openidconnect.dart'; 3 | 4 | class IdentityView extends StatelessWidget { 5 | final AuthorizationResponse identity; 6 | IdentityView(this.identity); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | final captionTheme = Theme.of(context).textTheme.bodySmall; 11 | return Padding( 12 | padding: EdgeInsets.all(15), 13 | child: SingleChildScrollView( 14 | scrollDirection: Axis.horizontal, 15 | child: Column( 16 | crossAxisAlignment: CrossAxisAlignment.start, 17 | children: [ 18 | Row( 19 | children: [ 20 | Text( 21 | "Access Token:", 22 | softWrap: true, 23 | style: captionTheme, 24 | ), 25 | Text( 26 | identity.accessToken, 27 | ) 28 | ], 29 | ), 30 | Row( 31 | children: [ 32 | Text( 33 | "Identity Token:", 34 | style: captionTheme, 35 | ), 36 | Text( 37 | identity.idToken, 38 | ) 39 | ], 40 | ), 41 | Row( 42 | children: [ 43 | Text( 44 | "Token Type:", 45 | style: captionTheme, 46 | ), 47 | Text( 48 | identity.tokenType, 49 | ) 50 | ], 51 | ), 52 | Row( 53 | children: [ 54 | Text( 55 | "Expires At:", 56 | style: captionTheme, 57 | ), 58 | Text( 59 | identity.expiresAt.toIso8601String(), 60 | ) 61 | ], 62 | ), 63 | Row( 64 | children: [ 65 | Text( 66 | "Refresh Token:", 67 | style: captionTheme, 68 | ), 69 | Text( 70 | identity.refreshToken ?? "Not included", 71 | ) 72 | ], 73 | ), 74 | Row( 75 | children: [ 76 | Text( 77 | "State:", 78 | style: captionTheme, 79 | ), 80 | Text( 81 | identity.state ?? "Not Included", 82 | ) 83 | ], 84 | ), 85 | ], 86 | ), 87 | ), 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /openidconnect/example/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | 11 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 12 | # which isn't available in 3.10. 13 | function(list_prepend LIST_NAME PREFIX) 14 | set(NEW_LIST "") 15 | foreach(element ${${LIST_NAME}}) 16 | list(APPEND NEW_LIST "${PREFIX}${element}") 17 | endforeach(element) 18 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 19 | endfunction() 20 | 21 | # === Flutter Library === 22 | # System-level dependencies. 23 | find_package(PkgConfig REQUIRED) 24 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 25 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 26 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 27 | 28 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 29 | 30 | # Published to parent scope for install step. 31 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 32 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 33 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 34 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 35 | 36 | list(APPEND FLUTTER_LIBRARY_HEADERS 37 | "fl_basic_message_channel.h" 38 | "fl_binary_codec.h" 39 | "fl_binary_messenger.h" 40 | "fl_dart_project.h" 41 | "fl_engine.h" 42 | "fl_json_message_codec.h" 43 | "fl_json_method_codec.h" 44 | "fl_message_codec.h" 45 | "fl_method_call.h" 46 | "fl_method_channel.h" 47 | "fl_method_codec.h" 48 | "fl_method_response.h" 49 | "fl_plugin_registrar.h" 50 | "fl_plugin_registry.h" 51 | "fl_standard_message_codec.h" 52 | "fl_standard_method_codec.h" 53 | "fl_string_codec.h" 54 | "fl_value.h" 55 | "fl_view.h" 56 | "flutter_linux.h" 57 | ) 58 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 59 | add_library(flutter INTERFACE) 60 | target_include_directories(flutter INTERFACE 61 | "${EPHEMERAL_DIR}" 62 | ) 63 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 64 | target_link_libraries(flutter INTERFACE 65 | PkgConfig::GTK 66 | PkgConfig::GLIB 67 | PkgConfig::GIO 68 | ) 69 | add_dependencies(flutter flutter_assemble) 70 | 71 | # === Flutter tool backend === 72 | # _phony_ is a non-existent file to force this command to run every time, 73 | # since currently there's no way to get a full input/output list from the 74 | # flutter tool. 75 | add_custom_command( 76 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 77 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 78 | COMMAND ${CMAKE_COMMAND} -E env 79 | ${FLUTTER_TOOL_ENVIRONMENT} 80 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 81 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 82 | VERBATIM 83 | ) 84 | add_custom_target(flutter_assemble DEPENDS 85 | "${FLUTTER_LIBRARY}" 86 | ${FLUTTER_LIBRARY_HEADERS} 87 | ) 88 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /openidconnect/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 73 | 79 | 80 | 81 | 82 | 84 | 85 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /openidconnect_windows/lib/openidconnect_windows.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:openidconnect_platform_interface/openidconnect_platform_interface.dart'; 5 | import 'package:webview_windows/webview_windows.dart'; 6 | 7 | class OpenIdConnectWindows extends OpenIdConnectPlatform { 8 | static void registerWith() { 9 | OpenIdConnectPlatform.instance = OpenIdConnectWindows(); 10 | } 11 | 12 | @override 13 | Future processStartup() { 14 | return Future.value(null); 15 | } 16 | 17 | @override 18 | Future authorizeInteractive({ 19 | required BuildContext context, 20 | required String title, 21 | required String authorizationUrl, 22 | required String redirectUrl, 23 | required int popupWidth, 24 | required int popupHeight, 25 | bool useWebRedirectLoop = false, 26 | }) async { 27 | final _controller = WebviewController(); 28 | try { 29 | //Create the url 30 | await _controller.initialize(); 31 | 32 | final result = await showDialog( 33 | context: context, 34 | barrierDismissible: false, 35 | builder: (dialogContext) { 36 | _controller.url.listen((url) { 37 | if (url.startsWith(redirectUrl)) { 38 | Navigator.pop(dialogContext, url); 39 | } 40 | }); 41 | 42 | return AlertDialog( 43 | actions: [ 44 | IconButton( 45 | onPressed: () => Navigator.pop(dialogContext, null), 46 | icon: const Icon(Icons.close), 47 | ), 48 | ], 49 | content: SizedBox( 50 | width: 51 | min(popupWidth.toDouble(), MediaQuery.of(context).size.width), 52 | height: min( 53 | popupHeight.toDouble(), MediaQuery.of(context).size.height), 54 | child: Webview( 55 | _controller, 56 | permissionRequested: (url, permissionKind, isUserInitiated) => 57 | _onPermissionRequested( 58 | url, 59 | permissionKind, 60 | isUserInitiated, 61 | dialogContext, 62 | ), 63 | ), 64 | ), 65 | title: Text(title), 66 | ); 67 | }, 68 | ); 69 | 70 | if (result == null) throw AuthenticationException(ERROR_USER_CLOSED); 71 | 72 | return result; 73 | } finally { 74 | _controller.dispose(); 75 | } 76 | } 77 | 78 | Future _onPermissionRequested( 79 | String url, 80 | WebviewPermissionKind kind, 81 | bool isUserInitiated, 82 | BuildContext context) async { 83 | final decision = await showDialog( 84 | context: context, 85 | builder: (BuildContext context) => AlertDialog( 86 | title: const Text('WebView permission requested'), 87 | content: Text('WebView has requested permission \'$kind\''), 88 | actions: [ 89 | TextButton( 90 | onPressed: () => 91 | Navigator.pop(context, WebviewPermissionDecision.deny), 92 | child: const Text('Deny'), 93 | ), 94 | TextButton( 95 | onPressed: () => 96 | Navigator.pop(context, WebviewPermissionDecision.allow), 97 | child: const Text('Allow'), 98 | ), 99 | ], 100 | ), 101 | ); 102 | 103 | return decision ?? WebviewPermissionDecision.none; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.example" "\0" 93 | VALUE "FileDescription", "A new Flutter project." "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "example" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "example.exe" "\0" 98 | VALUE "ProductName", "example" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /openidconnect/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /openidconnect/example/windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates and shows a win32 window with |title| and position and size using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | -------------------------------------------------------------------------------- /openidconnect/example/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(example LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "example") 5 | 6 | cmake_policy(SET CMP0063 NEW) 7 | 8 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 9 | 10 | # Configure build options. 11 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 12 | if(IS_MULTICONFIG) 13 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 14 | CACHE STRING "" FORCE) 15 | else() 16 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 17 | set(CMAKE_BUILD_TYPE "Debug" CACHE 18 | STRING "Flutter build mode" FORCE) 19 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 20 | "Debug" "Profile" "Release") 21 | endif() 22 | endif() 23 | 24 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 25 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 26 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 27 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 28 | 29 | # Use Unicode for all projects. 30 | add_definitions(-DUNICODE -D_UNICODE) 31 | 32 | # Compilation settings that should be applied to most targets. 33 | function(APPLY_STANDARD_SETTINGS TARGET) 34 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 35 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 36 | target_compile_options(${TARGET} PRIVATE /EHsc) 37 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 38 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 39 | endfunction() 40 | 41 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 42 | 43 | # Flutter library and tool build rules. 44 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 45 | 46 | # Application build 47 | add_subdirectory("runner") 48 | 49 | # Generated plugin build rules, which manage building the plugins and adding 50 | # them to the application. 51 | include(flutter/generated_plugins.cmake) 52 | 53 | 54 | # === Installation === 55 | # Support files are copied into place next to the executable, so that it can 56 | # run in place. This is done instead of making a separate bundle (as on Linux) 57 | # so that building and running from within Visual Studio will work. 58 | set(BUILD_BUNDLE_DIR "$") 59 | # Make the "install" step default, as it's required to run. 60 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 61 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 62 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 63 | endif() 64 | 65 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 66 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 67 | 68 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 69 | COMPONENT Runtime) 70 | 71 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 72 | COMPONENT Runtime) 73 | 74 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 75 | COMPONENT Runtime) 76 | 77 | if(PLUGIN_BUNDLED_LIBRARIES) 78 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 79 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 80 | COMPONENT Runtime) 81 | endif() 82 | 83 | # Fully re-copy the assets directory on each build to avoid having stale files 84 | # from a previous install. 85 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 86 | install(CODE " 87 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 88 | " COMPONENT Runtime) 89 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 90 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 91 | 92 | # Install the AOT library on non-Debug builds only. 93 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 94 | CONFIGURATIONS Profile;Release 95 | COMPONENT Runtime) 96 | -------------------------------------------------------------------------------- /openidconnect/example/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 11 | 12 | # === Flutter Library === 13 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 14 | 15 | # Published to parent scope for install step. 16 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 17 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 18 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 19 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 20 | 21 | list(APPEND FLUTTER_LIBRARY_HEADERS 22 | "flutter_export.h" 23 | "flutter_windows.h" 24 | "flutter_messenger.h" 25 | "flutter_plugin_registrar.h" 26 | "flutter_texture_registrar.h" 27 | ) 28 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 29 | add_library(flutter INTERFACE) 30 | target_include_directories(flutter INTERFACE 31 | "${EPHEMERAL_DIR}" 32 | ) 33 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 34 | add_dependencies(flutter flutter_assemble) 35 | 36 | # === Wrapper === 37 | list(APPEND CPP_WRAPPER_SOURCES_CORE 38 | "core_implementations.cc" 39 | "standard_codec.cc" 40 | ) 41 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 42 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 43 | "plugin_registrar.cc" 44 | ) 45 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 46 | list(APPEND CPP_WRAPPER_SOURCES_APP 47 | "flutter_engine.cc" 48 | "flutter_view_controller.cc" 49 | ) 50 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 51 | 52 | # Wrapper sources needed for a plugin. 53 | add_library(flutter_wrapper_plugin STATIC 54 | ${CPP_WRAPPER_SOURCES_CORE} 55 | ${CPP_WRAPPER_SOURCES_PLUGIN} 56 | ) 57 | apply_standard_settings(flutter_wrapper_plugin) 58 | set_target_properties(flutter_wrapper_plugin PROPERTIES 59 | POSITION_INDEPENDENT_CODE ON) 60 | set_target_properties(flutter_wrapper_plugin PROPERTIES 61 | CXX_VISIBILITY_PRESET hidden) 62 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 63 | target_include_directories(flutter_wrapper_plugin PUBLIC 64 | "${WRAPPER_ROOT}/include" 65 | ) 66 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 67 | 68 | # Wrapper sources needed for the runner. 69 | add_library(flutter_wrapper_app STATIC 70 | ${CPP_WRAPPER_SOURCES_CORE} 71 | ${CPP_WRAPPER_SOURCES_APP} 72 | ) 73 | apply_standard_settings(flutter_wrapper_app) 74 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 75 | target_include_directories(flutter_wrapper_app PUBLIC 76 | "${WRAPPER_ROOT}/include" 77 | ) 78 | add_dependencies(flutter_wrapper_app flutter_assemble) 79 | 80 | # === Flutter tool backend === 81 | # _phony_ is a non-existent file to force this command to run every time, 82 | # since currently there's no way to get a full input/output list from the 83 | # flutter tool. 84 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 85 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 86 | add_custom_command( 87 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 88 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 89 | ${CPP_WRAPPER_SOURCES_APP} 90 | ${PHONY_OUTPUT} 91 | COMMAND ${CMAKE_COMMAND} -E env 92 | ${FLUTTER_TOOL_ENVIRONMENT} 93 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 94 | windows-x64 $ 95 | VERBATIM 96 | ) 97 | add_custom_target(flutter_assemble DEPENDS 98 | "${FLUTTER_LIBRARY}" 99 | ${FLUTTER_LIBRARY_HEADERS} 100 | ${CPP_WRAPPER_SOURCES_CORE} 101 | ${CPP_WRAPPER_SOURCES_PLUGIN} 102 | ${CPP_WRAPPER_SOURCES_APP} 103 | ) 104 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/requests/interactive_authorization_request.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class InteractiveAuthorizationRequest extends TokenRequest { 4 | static const String _charset = 5 | 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'; 6 | 7 | final int popupWidth; 8 | final int popupHeight; 9 | final String codeVerifier; 10 | final String codeChallenge; 11 | final bool useWebPopup; 12 | final String redirectUrl; 13 | 14 | /// read: https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest 15 | /// 16 | /// [prompts] 17 | /// * none - The Authorization Server MUST NOT display any authentication or consent user interface pages. An error is returned if an End-User is not already authenticated or the Client does not have pre-configured consent for the requested Claims or does not fulfill other conditions for processing the request. The error code will typically be login_required, interaction_required, or another code defined in Section 3.1.2.6. This can be used as a method to check for existing authentication and/or consent. 18 | /// * login - The Authorization Server SHOULD prompt the End-User for reauthentication. If it cannot reauthenticate the End-User, it MUST return an error, typically login_required. 19 | /// * consent - The Authorization Server SHOULD prompt the End-User for consent before returning information to the Client. If it cannot obtain consent, it MUST return an error, typically consent_required. 20 | /// * select_account - The Authorization Server SHOULD prompt the End-User to select a user account. This enables an End-User who has multiple accounts at the Authorization Server to select amongst the multiple accounts that they might have current sessions for. If it cannot obtain an account selection choice made by the End-User, it MUST return an error, typically account_selection_required. 21 | static Future create({ 22 | required String clientId, 23 | String? clientSecret, 24 | required String redirectUrl, 25 | required Iterable scopes, 26 | required OpenIdConfiguration configuration, 27 | required bool autoRefresh, 28 | String? loginHint, 29 | Iterable? prompts, 30 | Map? additionalParameters, 31 | int popupWidth = 640, 32 | int popupHeight = 600, 33 | bool useWebPopup = true, 34 | }) async { 35 | final codeVerifier = List.generate( 36 | 128, (i) => _charset[Random.secure().nextInt(_charset.length)]).join(); 37 | 38 | final sha256 = crypto.Sha256(); 39 | 40 | final codeChallenge = base64Url 41 | .encode((await sha256.hash(ascii.encode(codeVerifier))).bytes) 42 | .replaceAll('=', ''); 43 | 44 | return InteractiveAuthorizationRequest._( 45 | clientId: clientId, 46 | redirectUrl: redirectUrl, 47 | scopes: scopes, 48 | configuration: configuration, 49 | autoRefresh: autoRefresh, 50 | codeVerifier: codeVerifier, 51 | codeChallenge: codeChallenge, 52 | additionalParameters: additionalParameters, 53 | clientSecret: clientSecret, 54 | loginHint: loginHint, 55 | prompts: prompts, 56 | popupHeight: popupHeight, 57 | popupWidth: popupWidth, 58 | useWebPopup: useWebPopup, 59 | ); 60 | } 61 | 62 | InteractiveAuthorizationRequest._({ 63 | required super.clientId, 64 | super.clientSecret, 65 | required this.redirectUrl, 66 | required super.scopes, 67 | required super.configuration, 68 | required bool autoRefresh, 69 | required this.codeVerifier, 70 | required this.codeChallenge, 71 | String? loginHint, 72 | super.prompts, 73 | Map? additionalParameters, 74 | this.popupWidth = 640, 75 | this.popupHeight = 480, 76 | this.useWebPopup = true, 77 | }) : super( 78 | grantType: "code", 79 | additionalParameters: { 80 | "redirect_uri": redirectUrl, 81 | "login_hint": loginHint ?? "", 82 | "response_type": "code", 83 | "code_challenge_method": "S256", 84 | "code_challenge": codeChallenge, 85 | ...?additionalParameters, 86 | }, 87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /openidconnect/example/linux/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen *screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "example"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } 47 | else { 48 | gtk_window_set_title(window, "example"); 49 | } 50 | 51 | gtk_window_set_default_size(window, 1280, 720); 52 | gtk_widget_show(GTK_WIDGET(window)); 53 | 54 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 55 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 56 | 57 | FlView* view = fl_view_new(project); 58 | gtk_widget_show(GTK_WIDGET(view)); 59 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 60 | 61 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 62 | 63 | gtk_widget_grab_focus(GTK_WIDGET(view)); 64 | } 65 | 66 | // Implements GApplication::local_command_line. 67 | static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { 68 | MyApplication* self = MY_APPLICATION(application); 69 | // Strip out the first argument as it is the binary name. 70 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 71 | 72 | g_autoptr(GError) error = nullptr; 73 | if (!g_application_register(application, nullptr, &error)) { 74 | g_warning("Failed to register: %s", error->message); 75 | *exit_status = 1; 76 | return TRUE; 77 | } 78 | 79 | g_application_activate(application); 80 | *exit_status = 0; 81 | 82 | return TRUE; 83 | } 84 | 85 | // Implements GObject::dispose. 86 | static void my_application_dispose(GObject *object) { 87 | MyApplication* self = MY_APPLICATION(object); 88 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 89 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 90 | } 91 | 92 | static void my_application_class_init(MyApplicationClass* klass) { 93 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 94 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 95 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 96 | } 97 | 98 | static void my_application_init(MyApplication* self) {} 99 | 100 | MyApplication* my_application_new() { 101 | return MY_APPLICATION(g_object_new(my_application_get_type(), 102 | "application-id", APPLICATION_ID, 103 | "flags", G_APPLICATION_NON_UNIQUE, 104 | nullptr)); 105 | } 106 | -------------------------------------------------------------------------------- /openidconnect/example/lib/redirectloop_result_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:openidconnect/openidconnect.dart'; 3 | 4 | import 'identity_view.dart'; 5 | import 'credentials.dart'; 6 | 7 | class RedirectLoopResultPage extends StatefulWidget { 8 | @override 9 | _RedirectLoopResultPageState createState() => _RedirectLoopResultPageState(); 10 | } 11 | 12 | class _RedirectLoopResultPageState extends State { 13 | final _formKey = GlobalKey(); 14 | String discoveryUrl = defaultDiscoveryUrl; 15 | OpenIdConfiguration? discoveryDocument; 16 | AuthorizationResponse? identity; 17 | String? errorMessage = null; 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return Scaffold( 22 | appBar: AppBar( 23 | title: const Text('Complete startup'), 24 | ), 25 | body: Center( 26 | child: Form( 27 | key: _formKey, 28 | autovalidateMode: AutovalidateMode.onUserInteraction, 29 | child: Column( 30 | children: [ 31 | TextFormField( 32 | textInputAction: TextInputAction.done, 33 | decoration: InputDecoration(labelText: "Discovery Url"), 34 | keyboardType: TextInputType.url, 35 | initialValue: discoveryUrl, 36 | onChanged: (value) => discoveryUrl = value, 37 | validator: (value) { 38 | const errorMessage = 39 | "Please enter a valid openid discovery document url"; 40 | if (value == null || value.isEmpty) return errorMessage; 41 | try { 42 | Uri.parse(value); 43 | return null; 44 | } on Exception catch (e) { 45 | print(e.toString()); 46 | return errorMessage; 47 | } 48 | }, 49 | ), 50 | TextButton.icon( 51 | onPressed: () async { 52 | _formKey.currentState!.save(); 53 | if (!_formKey.currentState!.validate()) return; 54 | try { 55 | final configuration = 56 | await OpenIdConnect.getConfiguration(discoveryUrl); 57 | setState(() { 58 | discoveryDocument = configuration; 59 | errorMessage = null; 60 | }); 61 | } on Exception catch (e) { 62 | setState(() { 63 | errorMessage = e.toString(); 64 | discoveryDocument = null; 65 | }); 66 | } 67 | }, 68 | icon: Icon(Icons.search), 69 | label: Text("Lookup OpenId Connect Configuration"), 70 | ), 71 | Visibility( 72 | child: TextButton.icon( 73 | onPressed: () async { 74 | try { 75 | final response = await OpenIdConnect.processStartup( 76 | clientId: defaultClientId, 77 | clientSecret: defaultClientSecret, 78 | scopes: defaultscopes, 79 | configuration: discoveryDocument!, 80 | redirectUrl: defaultRedirectUrl, 81 | autoRefresh: true, 82 | ); 83 | setState(() { 84 | identity = response; 85 | errorMessage = null; 86 | }); 87 | } on Exception catch (e) { 88 | setState(() { 89 | errorMessage = e.toString(); 90 | identity = null; 91 | }); 92 | } 93 | }, 94 | icon: Icon(Icons.loop), 95 | label: Text("Process Startup loop"), 96 | ), 97 | visible: discoveryDocument != null, 98 | ), 99 | Visibility( 100 | child: identity == null ? Container() : IdentityView(identity!), 101 | visible: identity != null, 102 | ), 103 | ], 104 | ), 105 | ), 106 | ), 107 | ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /openidconnect/example/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(runner LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "example") 5 | set(APPLICATION_ID "com.example.example") 6 | 7 | cmake_policy(SET CMP0063 NEW) 8 | 9 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 10 | 11 | # Root filesystem for cross-building. 12 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 13 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 14 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 15 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 16 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 17 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 18 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 19 | endif() 20 | 21 | # Configure build options. 22 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 23 | set(CMAKE_BUILD_TYPE "Debug" CACHE 24 | STRING "Flutter build mode" FORCE) 25 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 26 | "Debug" "Profile" "Release") 27 | endif() 28 | 29 | # Compilation settings that should be applied to most targets. 30 | function(APPLY_STANDARD_SETTINGS TARGET) 31 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 32 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 33 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 34 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 35 | endfunction() 36 | 37 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 38 | 39 | # Flutter library and tool build rules. 40 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 41 | 42 | # System-level dependencies. 43 | find_package(PkgConfig REQUIRED) 44 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 45 | 46 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 47 | 48 | # Application build 49 | add_executable(${BINARY_NAME} 50 | "main.cc" 51 | "my_application.cc" 52 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 53 | ) 54 | apply_standard_settings(${BINARY_NAME}) 55 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 56 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 57 | add_dependencies(${BINARY_NAME} flutter_assemble) 58 | # Only the install-generated bundle's copy of the executable will launch 59 | # correctly, since the resources must in the right relative locations. To avoid 60 | # people trying to run the unbundled copy, put it in a subdirectory instead of 61 | # the default top-level location. 62 | set_target_properties(${BINARY_NAME} 63 | PROPERTIES 64 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 65 | ) 66 | 67 | # Generated plugin build rules, which manage building the plugins and adding 68 | # them to the application. 69 | include(flutter/generated_plugins.cmake) 70 | 71 | 72 | # === Installation === 73 | # By default, "installing" just makes a relocatable bundle in the build 74 | # directory. 75 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 76 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 77 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 78 | endif() 79 | 80 | # Start with a clean build bundle directory every time. 81 | install(CODE " 82 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 83 | " COMPONENT Runtime) 84 | 85 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 86 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 87 | 88 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 89 | COMPONENT Runtime) 90 | 91 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 92 | COMPONENT Runtime) 93 | 94 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 95 | COMPONENT Runtime) 96 | 97 | if(PLUGIN_BUNDLED_LIBRARIES) 98 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 99 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 100 | COMPONENT Runtime) 101 | endif() 102 | 103 | # Fully re-copy the assets directory on each build to avoid having stale files 104 | # from a previous install. 105 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 106 | install(CODE " 107 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 108 | " COMPONENT Runtime) 109 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 110 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 111 | 112 | # Install the AOT library on non-Debug builds only. 113 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 114 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 115 | COMPONENT Runtime) 116 | endif() 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenIdConnect for Flutter 2 | 3 | Standards compliant OpenIdConnect library for flutter that supports: 4 | 5 | 1. Code flow with PKCE (the evolution of implicit flow). This allows poping a web browser (included) for authentication to any open id connect compliant IdP. 6 | 2. Password flow. For use when you control the client and server and you wish to have your users login directly to your IdP. 7 | 3. Device flow. For use typically with console applications and similar. Used currently for Windows, Linux and MacOs until WebView is supported on those platforms. 8 | 4. Full OpenIdConnect Client library that encapsulates the entire process including refresh tokens, refreshing and publishes an event stream for your application. 9 | 10 | The base library supports most of the basic OpenIdConnect functionality: 11 | 12 | 1. Authorize/Login (for all 3 code flows) 13 | 2. Logout 14 | 3. Revoke Token 15 | 4. Refresh Token 16 | 5. User Info 17 | 18 | In addition there is a complete OpenIdConnectClient which supports all 3 authorization flows AND automatically maintains login information in secure (ish, web is always the problem with this) storage and automatically refreshes tokens as needed. 19 | 20 | Currently supports: 21 | 22 | 1. iOS 23 | 2. Android 24 | 3. Web 25 | 4. Windows 26 | 5. MacOs 27 | 6. Linux 28 | 29 | **Important** 30 | 31 | For Linux and macOS currently your IdP MUST support device code flow to function properly with interactive login. Otherwise you must use password flow. This is because webView is not yet supported on these environments. 32 | 33 | ## Getting Started 34 | 35 | 1. Add openidconnect to your pubspec.yaml file 36 | 2. Import openidconnect: import 'package:openidconnect/openidconnect.dart'; 37 | 3. Call the various methods: on OpenIdConnect OR use OpenIdConnectClient and subscribe to the events 38 | 4. Review the example project for details. 39 | 40 | **(more detailed instructions coming soon)** 41 | 42 | ## Web 43 | 44 | 1. Copy the callback.html file from openidconnect_web (in this repo) into the web folder of your app. Make sure that your Idp has the proper redirect path https://{your_url_to_app/callback.html} as one of the accepted urls. 45 | 46 | 2. OpenIdConnect web has 2 separate interactive login flows as a result of security restrictions in the browser. (Password and device flows are identical for all platforms) In most cases you'll want to use the default popup window to handle authentication as this keeps everything in process and doesn't require a reload of your flutter application. However, if you have to initiate interactive login outside of clicking a button on the page, your browser will block the popup and put a prompt up asking the user to allow it. This is a bad thing of course. Thus you can set useWebPopup = false on interactiveAuthorization when you need to initialize your authorization outside of a button click. This will result in a redirect in the same page and then the login page on your IdP will redirect back to /callback.html (see notes). This will then be processed using the OpenIdConnect.processStartup or by the OpenIdConnectClient on .create() and then your app will resume as normal including the url that it left off. 47 | 48 | **Note:** It is VERY important to make sure you test on Firefox with the web, as it's behavior for blocking popups is _significantly_ more restrictive than Chromium browsers. 49 | 50 | ## TODO 51 | 52 | Because of the ever changing nature of desktop support on flutter and incomplete plugin implementations the following are outstanding and will be updated when the functionality exists to do so: 53 | 54 | 1. Use custom tabs and secure authentication popup on Android and IOS instead of WebView 55 | 2. Use Secure authentication popup on windows (requires work from Tim Sneath on integration with Project Reunion on Windows and Dart) 56 | 3. Switch macOs, and Linux to WebView and/or use secure authentication popup at least on macOs. 57 | 4. More documentation! 58 | 59 | ## Contributing 60 | 61 | Pull requests most welcome to fix any bugs found or address any of the above TODOs. I'm not a C++, Kotlin or Swift developer, so custom implementations for various environments would be greatly appreciated. 62 | 63 | If adding a custom environment other than android and iOS please follow the flutter best practices and add a separate implementation project with: flutter create --template=plugin --platforms={YourPlatformHere} openidconnect\_{YourPlatformHere} and add your code as appropriate there and then update the example project to use the new implementation. 64 | 65 | Your new implementation needs to import the platform interface which is exactly one entry. That entry passes in the url to display in the secure browser and the redirect url that you should watch for to respond accordingly. (You can ignore the redirect url on most platforms that support custom URLs such as Android, iOS etc.) You should return the entire redirected URL which should include the ?code= (and perhaps state) when complete. 66 | 67 | Everything else is handled in native dart code so the implementation is very straight forward. 68 | -------------------------------------------------------------------------------- /openidconnect/example/lib/device.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:openidconnect/openidconnect.dart'; 3 | import 'identity_view.dart'; 4 | 5 | import 'credentials.dart'; 6 | 7 | class DeviceCodePage extends StatefulWidget { 8 | @override 9 | _DeviceCodePageState createState() => _DeviceCodePageState(); 10 | } 11 | 12 | class _DeviceCodePageState extends State { 13 | final _formKey = GlobalKey(); 14 | 15 | OpenIdConnectClient? client; 16 | String discoveryUrl = defaultDiscoveryUrl; 17 | OpenIdConfiguration? discoveryDocument; 18 | AuthorizationResponse? identity; 19 | 20 | String? errorMessage = null; 21 | 22 | Future lookupSettings() async { 23 | _formKey.currentState!.save(); 24 | if (!_formKey.currentState!.validate()) return; 25 | 26 | try { 27 | final configuration = await OpenIdConnect.getConfiguration(discoveryUrl); 28 | client = await OpenIdConnectClient.create( 29 | clientId: defaultClientId, 30 | discoveryDocumentUrl: discoveryUrl, 31 | scopes: defaultscopes, 32 | audiences: defaultAudience, 33 | clientSecret: defaultClientSecret, 34 | redirectUrl: defaultRedirectUrl, 35 | webUseRefreshTokens: true, 36 | autoRefresh: true, 37 | encryptionKey: defaultEncryptionKey); 38 | setState(() { 39 | discoveryDocument = configuration; 40 | errorMessage = null; 41 | }); 42 | } on Exception catch (e) { 43 | setState(() { 44 | errorMessage = e.toString(); 45 | discoveryDocument = null; 46 | }); 47 | } 48 | } 49 | 50 | Future authorize() async { 51 | try { 52 | if (client == null) return; 53 | 54 | final response = await client!.loginWithDeviceCode(); 55 | setState(() { 56 | identity = response; 57 | errorMessage = null; 58 | }); 59 | } on Exception catch (e) { 60 | setState(() { 61 | errorMessage = e.toString(); 62 | identity = null; 63 | }); 64 | } 65 | } 66 | 67 | @override 68 | Widget build(BuildContext context) { 69 | return Scaffold( 70 | appBar: AppBar( 71 | title: const Text('Device Code Flow Example'), 72 | ), 73 | body: Center( 74 | child: Form( 75 | key: _formKey, 76 | autovalidateMode: AutovalidateMode.onUserInteraction, 77 | child: Column( 78 | children: [ 79 | TextFormField( 80 | textInputAction: TextInputAction.done, 81 | decoration: InputDecoration(labelText: "Discovery Url"), 82 | keyboardType: TextInputType.url, 83 | initialValue: discoveryUrl, 84 | onChanged: (value) => discoveryUrl = value, 85 | validator: (value) { 86 | const errorMessage = 87 | "Please enter a valid openid discovery document url"; 88 | if (value == null || value.isEmpty) return errorMessage; 89 | try { 90 | Uri.parse(value); 91 | return null; 92 | } on Exception catch (e) { 93 | print(e.toString()); 94 | return errorMessage; 95 | } 96 | }, 97 | ), 98 | TextButton.icon( 99 | onPressed: lookupSettings, 100 | icon: Icon(Icons.search), 101 | label: Text("Lookup OpenId Connect Configuration"), 102 | ), 103 | Visibility( 104 | child: TextButton.icon( 105 | onPressed: authorize, 106 | icon: Icon(Icons.login), 107 | label: Text("Login"), 108 | ), 109 | visible: discoveryDocument != null, 110 | ), 111 | Visibility( 112 | child: Text( 113 | errorMessage ?? "", 114 | style: Theme.of(context) 115 | .textTheme 116 | .bodyLarge! 117 | .copyWith(color: Theme.of(context).colorScheme.error), 118 | ), 119 | visible: errorMessage != null, 120 | ), 121 | Visibility( 122 | child: identity == null ? Container() : IdentityView(identity!), 123 | visible: identity != null, 124 | ), 125 | Visibility( 126 | child: TextButton.icon( 127 | onPressed: () => OpenIdConnect.logout( 128 | request: LogoutRequest( 129 | idToken: identity!.idToken, 130 | configuration: discoveryDocument!, 131 | ), 132 | ), 133 | icon: Icon(Icons.logout), 134 | label: Text("Logout"), 135 | ), 136 | visible: identity != null, 137 | ), 138 | ], 139 | ), 140 | ), 141 | ), 142 | ); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /openidconnect/lib/src/models/identity.dart: -------------------------------------------------------------------------------- 1 | part of openidconnect; 2 | 3 | class OpenIdIdentity extends AuthorizationResponse { 4 | static const String _AUTHENTICATION_TOKEN_KEY = "ACCESS_TOKEN"; 5 | static const String _ID_TOKEN_KEY = "ID_TOKEN"; 6 | static const String _REFRESH_TOKEN_KEY = "REFRESH_TOKEN"; 7 | static const String _TOKEN_TYPE_KEY = "TOKEN_TYPE"; 8 | static const String _EXPIRES_ON_KEY = "EXPIRES_ON"; 9 | static const String _STATE_KEY = "STATE"; 10 | 11 | late Map claims; 12 | late String sub; 13 | 14 | OpenIdIdentity({ 15 | required String accessToken, 16 | required DateTime expiresAt, 17 | required String idToken, 18 | required String tokenType, 19 | String? refreshToken, 20 | String? state, 21 | }) : super( 22 | expiresAt: expiresAt, 23 | tokenType: tokenType, 24 | accessToken: accessToken, 25 | idToken: idToken, 26 | refreshToken: refreshToken, 27 | state: state, 28 | ) { 29 | this.claims = JwtDecoder.decode(idToken); 30 | 31 | this.sub = claims["sub"].toString(); 32 | } 33 | 34 | factory OpenIdIdentity.fromAuthorizationResponse( 35 | AuthorizationResponse response, 36 | ) => OpenIdIdentity( 37 | accessToken: response.accessToken, 38 | expiresAt: response.expiresAt, 39 | idToken: response.idToken, 40 | tokenType: response.tokenType, 41 | refreshToken: response.refreshToken, 42 | state: response.state, 43 | ); 44 | 45 | static final _storage = EncryptedSharedPreferencesAsync.getInstance(); 46 | 47 | static Future load() async { 48 | try { 49 | late String? accessToken; 50 | late String? refreshToken; 51 | late int expiresOn; 52 | late String tokenType; 53 | late String? idToken; 54 | late String? state; 55 | 56 | accessToken = await _storage.getString(_AUTHENTICATION_TOKEN_KEY); 57 | idToken = await _storage.getString(_ID_TOKEN_KEY); 58 | expiresOn = await _storage.getInt(_EXPIRES_ON_KEY) ?? 0; 59 | tokenType = await _storage.getString(_TOKEN_TYPE_KEY) ?? "bearer"; 60 | state = await _storage.getString(_STATE_KEY); 61 | refreshToken = await _storage.getString(_REFRESH_TOKEN_KEY); 62 | 63 | if (accessToken == null || idToken == null) return null; 64 | 65 | return OpenIdIdentity( 66 | accessToken: accessToken, 67 | expiresAt: DateTime.fromMillisecondsSinceEpoch(expiresOn), 68 | idToken: idToken, 69 | tokenType: tokenType, 70 | refreshToken: refreshToken, 71 | state: state, 72 | ); 73 | } on Exception catch (e) { 74 | print(e.toString()); 75 | try { 76 | clear(); 77 | } on Exception {} 78 | return null; //Invalid values, flush. 79 | } 80 | } 81 | 82 | Future save() async { 83 | await Future.wait([ 84 | _storage.setString(_AUTHENTICATION_TOKEN_KEY, this.accessToken), 85 | _storage.setString(_ID_TOKEN_KEY, this.idToken), 86 | _storage.setString(_TOKEN_TYPE_KEY, this.tokenType), 87 | _storage.setInt(_EXPIRES_ON_KEY, this.expiresAt.millisecondsSinceEpoch), 88 | ]); 89 | 90 | this.refreshToken == null 91 | ? await _storage.remove(_REFRESH_TOKEN_KEY) 92 | : await _storage.setString(_REFRESH_TOKEN_KEY, this.refreshToken); 93 | 94 | this.state == null 95 | ? await _storage.remove(_STATE_KEY) 96 | : await _storage.setString(_STATE_KEY, this.state); 97 | } 98 | 99 | static Future clear() async { 100 | await Future.wait([ 101 | _storage.remove(_AUTHENTICATION_TOKEN_KEY), 102 | _storage.remove(_ID_TOKEN_KEY), 103 | _storage.remove(_REFRESH_TOKEN_KEY), 104 | _storage.remove(_TOKEN_TYPE_KEY), 105 | _storage.remove(_EXPIRES_ON_KEY), 106 | _storage.remove(_STATE_KEY), 107 | ]); 108 | } 109 | 110 | String? get familyName => claims["family_name"]?.toString(); 111 | String? get givenName => claims["given_name"]?.toString(); 112 | String? get fullName => 113 | claims["name"]?.toString() ?? 114 | (givenName == null ? familyName : "${givenName} ${familyName}"); 115 | String? get userName => 116 | claims["username"]?.toString() ?? 117 | claims["preferred_username"]?.toString() ?? 118 | claims["sub"]?.toString(); 119 | String? get email => claims["email"]?.toString(); 120 | String? get act => claims["act"]?.toString(); 121 | List get roles => claims["role"] == null 122 | ? List.empty() 123 | : claims["role"] is String 124 | ? [claims["role"].toString()] 125 | : List.from(claims["role"] as Iterable); 126 | String? get picture => claims["picture"]?.toString(); 127 | 128 | @override 129 | operator ==(Object o) { 130 | if (identical(this, o)) return true; 131 | 132 | return o is OpenIdIdentity && 133 | o.accessToken == accessToken && 134 | o.idToken == idToken && 135 | o.refreshToken == refreshToken && 136 | o.state == state && 137 | o.tokenType == tokenType && 138 | o.claims == claims; 139 | } 140 | 141 | @override 142 | int get hashCode => 143 | accessToken.hashCode ^ 144 | idToken.hashCode ^ 145 | (refreshToken?.hashCode ?? 0) ^ 146 | (state?.hashCode ?? 0) ^ 147 | tokenType.hashCode ^ 148 | claims.hashCode; 149 | } 150 | -------------------------------------------------------------------------------- /openidconnect/README.md: -------------------------------------------------------------------------------- 1 | # OpenIdConnect for Flutter 2 | 3 | Standards compliant OpenIdConnect library for flutter that supports: 4 | 5 | 1. Code flow with PKCE (the evolution of implicit flow). This allows poping a web browser (included) for authentication to any open id connect compliant IdP. 6 | 2. Password flow. For use when you control the client and server and you wish to have your users login directly to your IdP. 7 | 3. Device flow. For use typically with console applications and similar. Used currently for Windows, Linux and MacOs until WebView is supported on those platforms. 8 | 4. Full OpenIdConnect Client library that encapsulates the entire process including refresh tokens, refreshing and publishes an event stream for your application. 9 | 10 | The base library supports most of the basic OpenIdConnect functionality: 11 | 12 | 1. Authorize/Login (for all 3 code flows) 13 | 2. Logout 14 | 3. Revoke Token 15 | 4. Refresh Token 16 | 5. User Info 17 | 18 | In addition there is a complete OpenIdConnectClient which supports all 3 authorization flows AND automatically maintains login information in secure (ish, web is always the problem with this) storage and automatically refreshes tokens as needed. 19 | 20 | Currently supports: 21 | 22 | 1. iOS 23 | 2. Android 24 | 3. Web 25 | 4. Windows 26 | 5. MacOs 27 | 6. Linux 28 | 29 | ## **Important** 30 | 31 | 1. For Linux, Windows and macOS currently your IdP MUST support device code flow to function properly with interactive login. Otherwise you must use password flow. This is because webView is not yet supported on these environments. 32 | 33 | 2. If using the base library you **MUST** call OpenIdConnect.InitializeEncryption(encryptionKey) before use. It MUST be a 16 character key that you generate. If using the OpenIdConnectClient you SHOULD provide your own encryption key and NOT rely on the default. Espeically if you're using EncryptedSharedPreferences in your project, it should use the same key. 34 | 35 | ## Getting Started 36 | 37 | 1. Add openidconnect to your pubspec.yaml file 38 | 2. Import openidconnect: import 'package:openidconnect/openidconnect.dart'; 39 | 3. Call the various methods: on OpenIdConnect OR use OpenIdConnectClient and subscribe to the events 40 | 4. Make sure that you call initalizeEncryption (If you've already initialized EncryptedSharedPreferences you don't need to call this again) on OpenIdConnect if you're using it directly or pass in your app's 16 character encryption key to OpenIdConnectClient. 41 | 5. Review the example project for details. 42 | 43 | (more detailed instructions coming soon) 44 | 45 | ## Web 46 | 47 | 1. Copy the callback.html file from openidconnect_web (in this repo) into the web folder of your app. Make sure that your Idp has the proper redirect path https://{your_url_to_app/callback.html} as one of the accepted urls. 48 | 49 | 2. OpenIdConnect web has 2 separate interactive login flows as a result of security restrictions in the browser. (Password and device flows are identical for all platforms) In most cases you'll want to use the default popup window to handle authentication as this keeps everything in process and doesn't require a reload of your flutter application. However, if you have to initiate interactive login outside of clicking a button on the page, your browser will block the popup and put a prompt up asking the user to allow it. This is a bad thing of course. Thus you can set useWebPopup = false on interactiveAuthorization when you need to initialize your authorization outside of a button click. This will result in a redirect in the same page and then the login page on your IdP will redirect back to /callback.html (see notes). This will then be processed using the OpenIdConnect.processStartup or by the OpenIdConnectClient on .create() and then your app will resume as normal including the url that it left off. 50 | 51 | **Note:** It is VERY important to make sure you test on Firefox with the web, as it's behavior for blocking popups is _significantly_ more restrictive than Chromium browsers. 52 | 53 | ## TODO 54 | 55 | Because of the ever changing nature of desktop support on flutter and incomplete plugin implementations the following are outstanding and will be updated when the functionality exists to do so: 56 | 57 | 1. Use custom tabs and secure authentication popup on Android and IOS instead of WebView 58 | 2. Use Secure authentication popup on windows (requires work from Tim Sneath on integration with Project Reunion on Windows and Dart) 59 | 3. Switch macOs, and Linux to WebView and/or use secure authentication popup at least on macOs. 60 | 4. More documentation! 61 | 62 | ## Contributing 63 | 64 | Pull requests most welcome to fix any bugs found or address any of the above TODOs. I'm not a C++, Kotlin or Swift developer, so custom implementations for various environments would be greatly appreciated. 65 | 66 | If adding a custom environment other than android and iOS please follow the flutter best practices and add a separate implementation project with: flutter create --template=plugin --platforms={YourPlatformHere} openidconnect\_{YourPlatformHere} and add your code as appropriate there and then update the example project to use the new implementation. 67 | 68 | Your new implementation needs to import the platform interface which is exactly one entry. That entry passes in the url to display in the secure browser and the redirect url that you should watch for to respond accordingly. (You can ignore the redirect url on most platforms that support custom URLs such as Android, iOS etc.) You should return the entire redirected URL which should include the ?code= (and perhaps state) when complete. 69 | 70 | Everything else is handled in native dart code so the implementation is very straight forward. 71 | -------------------------------------------------------------------------------- /openidconnect/example/lib/interactive.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:openidconnect/openidconnect.dart'; 4 | import 'credentials.dart'; 5 | 6 | import 'identity_view.dart'; 7 | 8 | class InteractivePage extends StatefulWidget { 9 | @override 10 | _InteractivePageState createState() => _InteractivePageState(); 11 | } 12 | 13 | class _InteractivePageState extends State { 14 | final _formKey = GlobalKey(); 15 | 16 | String discoveryUrl = defaultDiscoveryUrl; 17 | OpenIdConfiguration? discoveryDocument; 18 | OpenIdConnectClient? client; 19 | AuthorizationResponse? identity; 20 | bool usePopup = true; 21 | 22 | String? errorMessage = null; 23 | 24 | Future lookupSettings() async { 25 | _formKey.currentState!.save(); 26 | if (!_formKey.currentState!.validate()) return; 27 | 28 | try { 29 | final configuration = await OpenIdConnect.getConfiguration(discoveryUrl); 30 | client = await OpenIdConnectClient.create( 31 | clientId: defaultClientId, 32 | discoveryDocumentUrl: discoveryUrl, 33 | scopes: defaultscopes, 34 | audiences: defaultAudience, 35 | clientSecret: defaultClientSecret, 36 | redirectUrl: defaultRedirectUrl, 37 | webUseRefreshTokens: true, 38 | autoRefresh: true, 39 | encryptionKey: defaultEncryptionKey, 40 | ); 41 | setState(() { 42 | discoveryDocument = configuration; 43 | errorMessage = null; 44 | }); 45 | } on Exception catch (e) { 46 | setState(() { 47 | errorMessage = e.toString(); 48 | discoveryDocument = null; 49 | }); 50 | } 51 | } 52 | 53 | Future authorize() async { 54 | try { 55 | if (client == null) return; 56 | 57 | final response = await client!.loginInteractive( 58 | context: context, 59 | title: "Login", 60 | useWebPopup: usePopup, 61 | ); 62 | 63 | setState(() { 64 | identity = response; 65 | errorMessage = null; 66 | }); 67 | } on Exception catch (e) { 68 | setState(() { 69 | errorMessage = e.toString(); 70 | identity = null; 71 | }); 72 | } 73 | } 74 | 75 | @override 76 | Widget build(BuildContext context) { 77 | return Scaffold( 78 | appBar: AppBar( 79 | title: const Text('OpenIdConnect Code Flow with PKCE Example'), 80 | ), 81 | body: Center( 82 | child: Form( 83 | key: _formKey, 84 | autovalidateMode: AutovalidateMode.onUserInteraction, 85 | child: Column( 86 | children: [ 87 | TextFormField( 88 | textInputAction: TextInputAction.done, 89 | decoration: InputDecoration(labelText: "Discovery Url"), 90 | keyboardType: TextInputType.url, 91 | initialValue: discoveryUrl, 92 | onChanged: (value) => discoveryUrl = value, 93 | validator: (value) { 94 | const errorMessage = 95 | "Please enter a valid openid discovery document url"; 96 | if (value == null || value.isEmpty) return errorMessage; 97 | try { 98 | Uri.parse(value); 99 | return null; 100 | } on Exception catch (e) { 101 | print(e.toString()); 102 | return errorMessage; 103 | } 104 | }, 105 | ), 106 | TextButton.icon( 107 | onPressed: lookupSettings, 108 | icon: Icon(Icons.search), 109 | label: Text("Lookup OpenId Connect Configuration"), 110 | ), 111 | Visibility( 112 | child: SwitchListTile.adaptive( 113 | value: usePopup, 114 | title: Text("Use Web Popup"), 115 | onChanged: (value) { 116 | setState(() { 117 | usePopup = value; 118 | }); 119 | }, 120 | ), 121 | visible: kIsWeb, 122 | ), 123 | Visibility( 124 | child: TextButton.icon( 125 | onPressed: authorize, 126 | icon: Icon(Icons.login), 127 | label: Text("Login"), 128 | ), 129 | visible: discoveryDocument != null, 130 | ), 131 | Visibility( 132 | child: identity == null ? Container() : IdentityView(identity!), 133 | visible: identity != null, 134 | ), 135 | Visibility( 136 | child: SelectableText(errorMessage ?? ""), 137 | visible: errorMessage != null, 138 | ), 139 | Visibility( 140 | child: TextButton.icon( 141 | onPressed: () async { 142 | OpenIdConnect.logout( 143 | request: LogoutRequest( 144 | idToken: identity!.idToken, 145 | configuration: discoveryDocument!, 146 | ), 147 | ); 148 | setState(() { 149 | identity = null; 150 | }); 151 | }, 152 | icon: Icon(Icons.logout), 153 | label: Text("Logout"), 154 | ), 155 | visible: identity != null, 156 | ), 157 | ], 158 | ), 159 | ), 160 | ), 161 | ); 162 | } 163 | } 164 | --------------------------------------------------------------------------------