Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/flutter-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: 'Flutter Continuous Integration'

on:
pull_request:
paths:
- 'flutter/**/*'

jobs:
analyze-and-test:
runs-on: macos-latest
defaults:
run:
working-directory: flutter
steps:
- uses: actions/checkout@v4

- uses: subosito/flutter-action@v2
with:
flutter-version: '3.44.4'
channel: 'stable'

- run: flutter pub get

- name: Analyze
run: flutter analyze

- name: Dart/Flutter unit + widget tests
run: flutter test

- name: Android unit tests (ping_core, ping_journey)
working-directory: flutter/flutter-journey/android
run: ./gradlew :ping_core:testDebugUnitTest :ping_journey:testDebugUnitTest
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Explore the many use cases the Ping Orchestration SDKs have to offer by referrin

- [Android](./android/)

- [Flutter](./flutter/)

## Documentation

Detailed [documentation](https://developer.pingidentity.com/orchsdks/index.html) is provided, and includes topics such as:
Expand Down Expand Up @@ -44,6 +46,10 @@ Detailed [documentation](https://developer.pingidentity.com/orchsdks/index.html)
- Gradle 8.6+
- Android API level 29+

**Flutter**
- Flutter 3.44.x stable / Dart 3.12.x
- Android API level 29+ / iOS 16+

## Disclaimer

> **This code is provided by Ping Identity Corporation ("Ping") on an "as is" basis, without warranty of any kind, to the fullest extent permitted by law.
Expand Down
37 changes: 37 additions & 0 deletions flutter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[![Ping Identity](https://www.pingidentity.com/content/dam/picr/nav/Ping-Logo-2.svg)](https://github.com/ForgeRock/sdk-sample-apps)

# Flutter Samples

Ping provides these Flutter samples to help demonstrate SDK functionality/implementation. They are provided "as is" and are not official products of Ping and are not officially supported.

Ping ships official React Native, iOS, and Android SDKs but no first-party Flutter SDK. This directory provides one: a native-wrapper **bridge plugin** ([`flutter-sdk-bridge/`](flutter-sdk-bridge/), wrapping the published native Android/iOS Ping SDKs) plus **sample apps** that use it.

This is a native Dart [pub workspace](https://dart.dev/tools/pub/workspaces) — one `flutter pub get` from this directory resolves every package below.

## Samples

- [**Journey — `flutter-journey/`**](flutter-journey/) — authenticates against a PingAM/PingOne Advanced Identity Cloud authentication Journey: dynamic callback rendering, login, self-registration, and post-login token retrieval.

## SDK Bridge

- [`flutter-sdk-bridge/`](flutter-sdk-bridge/) — the `ping_core` + `ping_journey` plugin packages
the sample above is built on. See its README for how to add a bridge module for a future
sample (e.g. DaVinci, OIDC).

## Requirements

- Flutter 3.44.x stable / Dart 3.12.x
- Android: API level 29+, Java 17
- iOS: 16.0+, Xcode with Swift Package Manager support

## Native SDK version

Both platforms pin the native Ping SDKs to **2.0.0** — Android via Maven
(`com.pingidentity.sdks:*`), iOS via Swift Package Manager
(`github.com/ForgeRock/ping-ios-sdk`, exact `2.0.0`).

## License

This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.

© Copyright 2026 Ping Identity Corporation. All rights reserved.
1 change: 1 addition & 0 deletions flutter/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include: package:flutter_lints/flutter.yaml
45 changes: 45 additions & 0 deletions flutter/flutter-journey/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
/coverage/

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
33 changes: 33 additions & 0 deletions flutter/flutter-journey/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "ad70ec4617166f1c38e5d2bfd388af71fda14f06"
channel: "stable"

project_type: app

# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
- platform: android
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
- platform: ios
create_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06
base_revision: ad70ec4617166f1c38e5d2bfd388af71fda14f06

# User provided section

# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
90 changes: 90 additions & 0 deletions flutter/flutter-journey/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
[![Ping Identity](https://www.pingidentity.com/content/dam/picr/nav/Ping-Logo-2.svg)](https://github.com/ForgeRock/sdk-sample-apps)

# Journey app using Flutter

Ping provides these Flutter samples to help demonstrate SDK functionality/implementation. They are provided "as is" and are not official products of Ping and are not officially supported.

## Introduction

This sample is a Flutter application that uses the `ping_journey` bridge plugin (see
[`../flutter-sdk-bridge/`](../flutter-sdk-bridge/)) to authenticate against a PingAM/PingOne
Advanced Identity Cloud authentication Journey. It demonstrates:

- Starting a named Journey and rendering its callbacks dynamically (Name, Password, Validated
Username/Password, Choice, KBA, Terms and Conditions, Text Input/Output, and String/Number/
Boolean Attribute Input).
- Advancing the flow (`next()`) and recovering from an `ErrorNode`/`FailureNode` via a "Try Again"
button.
- Retrieving the access/refresh token and userinfo after a successful login (OIDC module).
- Signing off and restarting.

The bridge wraps the published native Android and iOS Ping SDKs (native-wrapper approach) rather
than a pure-Dart reimplementation.

## Requirements

- Flutter 3.44.x stable / Dart 3.12.x
- A PingAM/PingOne Advanced Identity Cloud server with a configured authentication Journey
- Android: API level 29+, Java 17
- iOS: 16.0+, Xcode with Swift Package Manager support

## Getting Started

To try out the Journey Flutter sample, perform these steps:

1. Configure Ping Services. Ensure you have a PingAM/AIC server configured with an authentication
Journey (e.g. "Login") and, if you want the post-login token exchange, an OAuth 2.0 application
for native mobile apps. More details in this
[documentation](https://backstage.forgerock.com/docs/sdks/latest/sdks/serverconfiguration/pingone/create-oauth2-client.html).
2. Clone this repo:

```
git clone https://github.com/ForgeRock/sdk-sample-apps.git
```
3. From `sdk-sample-apps/flutter/`, run `flutter pub get` to resolve the pub workspace
(`flutter-sdk-bridge/ping_core`, `flutter-sdk-bridge/ping_journey`, `flutter-journey`).
4. Open [`lib/config/env.dart`](lib/config/env.dart) and replace the TODO placeholders:
- `serverUrl`, `realm`, `cookie` — your tenant's Journey server configuration.
- `oidcConfig` — your OAuth 2.0 client's `clientId`/`discoveryEndpoint`/`scopes`/`redirectUri`,
or leave `null` to skip the post-login token exchange (Journey-only, session login).
5. If you set `oidcConfig`, register `redirectUri`'s custom scheme with both native hosts:
- Android: add an `intent-filter` for the scheme in `android/app/src/main/AndroidManifest.xml`.
- iOS (SPM): add a `CFBundleURLTypes` entry for the scheme in `ios/Runner/Info.plist`.
6. Run the app: `flutter run` from this directory (`flutter-journey/`), or open
`ios/Runner.xcworkspace` in Xcode / the Android project in Android Studio.

## Testing

Unit and widget tests run with `flutter test` from this directory (or `flutter/` root). The
integration tests under `integration_test/` drive real Journeys against the configured tenant —
run each file standalone against a booted simulator/emulator or device (not combined in one
`flutter test` invocation — the native SDK persists the AM session cookie on-device across
`Journey` instances within one app install, so running both back-to-back in one process changes
each Journey's first-node response):

```
flutter test integration_test/journey_login_test.dart \
--dart-define=E2E_USERNAME=<username> --dart-define=E2E_PASSWORD=<password>
flutter test integration_test/journey_registration_test.dart
```

`journey_login_test.dart`'s credentialed assertions (login, Success screen, sign-off) only run
when `E2E_USERNAME`/`E2E_PASSWORD` are supplied, since no test credentials are committed to this
public sample repo. `journey_registration_test.dart` needs no credentials — it signs up a fresh,
uniquely-suffixed user each run.

## Native SDK version

Both platforms pin the native Ping SDK to **2.0.0** — Android via Maven
(`com.pingidentity.sdks:*`), iOS via Swift Package Manager
(`github.com/ForgeRock/ping-ios-sdk`, exact `2.0.0`).

## Additional Resources

Ping SDK Documentation: https://docs.pingidentity.com/sdks/latest/sdks/index.html

## License

This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.

© Copyright 2026 Ping Identity Corporation. All rights reserved.
29 changes: 29 additions & 0 deletions flutter/flutter-journey/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
always_use_package_imports: true
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
14 changes: 14 additions & 0 deletions flutter/flutter-journey/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
.cxx/

# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks
45 changes: 45 additions & 0 deletions flutter/flutter-journey/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
plugins {
id("com.android.application")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}

android {
namespace = "com.pingidentity.flutter.flutter_journey"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.pingidentity.flutter.flutter_journey"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 29
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}

kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}

flutter {
source = "../.."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
Loading
Loading