Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ secured by PingOne.
│ ├── oath # TOTP / HOTP one-time passwords
│ └── push # Push notification authentication
├── protect # PingOne Protect fraud signals
├── pingonemfa # PingOne MFA authentication
├── recaptcha-enterprise # reCAPTCHA Enterprise integration
└── samples # Sample applications
└── pingsampleapp # Combined Ping sample app
Expand Down
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ coilCompose = "2.7.0"
startupRuntime = "1.2.0"

com-pingidentity-signals = "5.3.0"
com-pingidentity-pingonemfa = "2.3.0"
kotlin-playservices-coroutine = "1.10.2"

barcodeScanning = "17.3.0"
Expand All @@ -71,6 +72,7 @@ security-crypto = "1.1.0"

play-services-location = "21.3.0"
google-android-recaptcha = "18.6.1" # This version is compatible with API Level 29 and does not require desugaring.
google-gson-lib = "2.10.1"
zxing = "3.5.3"

[libraries]
Expand Down Expand Up @@ -141,6 +143,7 @@ googleid = { group = "com.google.android.libraries.identity.googleid", name = "g
facebook-login = { module = "com.facebook.android:facebook-login", version.ref = "facebook-login" }
androidx-startup-runtime = { group = "androidx.startup", name = "startup-runtime", version.ref = "startupRuntime" }
com-pingidentity-signals = { group = "com.pingidentity.signals", name = "android-sdk", version.ref = "com-pingidentity-signals" }
com-pingidentity-pingonemfa = { group = "com.pingidentity.pingonemfa", name = "android-sdk", version.ref = "com-pingidentity-pingonemfa" }
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraCamera2" }
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraCamera2" }
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraCamera2" }
Expand All @@ -163,6 +166,7 @@ zxing-qr-generator = { module = "com.google.zxing:core", version.ref = "zXingQR"

play-services-location = { module = "com.google.android.gms:play-services-location", version.ref = "play-services-location" }
google-android-recaptcha = { module = "com.google.android.recaptcha:recaptcha", version.ref = "google-android-recaptcha" }
google-gson-lib = {module = "com.google.code.gson:gson", version.ref = "google-gson-lib"}

zxing-core = { module = "com.google.zxing:core", version.ref = "zxing" }

Expand Down
1 change: 1 addition & 0 deletions pingonemfa/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
363 changes: 363 additions & 0 deletions pingonemfa/README.md

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions pingonemfa/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2026 Ping Identity Corporation. All rights reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
description = "Ping Identity PingOneMFA SDK for Android"

plugins {
id("com.pingidentity.convention.android.library")
id("com.pingidentity.convention.centralPublish")
id("kotlin-parcelize")
alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.kotlinSerialization)
}
android {
namespace = "com.pingidentity.pingonemfa"
}
dependencies {
implementation(project(":foundation:android"))
implementation(project(":foundation:logger"))
implementation(libs.com.pingidentity.pingonemfa)

implementation(libs.kotlinx.coroutines.core)
implementation(libs.google.gson.lib)
implementation(libs.kotlinx.serialization.json)

// Firebase Cloud Messaging for push notifications
implementation(platform(libs.firebase.bom))
implementation(libs.firebase.messaging)

testImplementation(libs.kotlin.test)
testImplementation(libs.mockk)
testImplementation(libs.kotlinx.coroutines.test)
}
19 changes: 19 additions & 0 deletions pingonemfa/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2026 Ping Identity Corporation. All rights reserved.
~
~ This software may be modified and distributed under the terms
~ of the MIT license. See the LICENSE file for details.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING"/>

<application>
<service
android:name="com.pingidentity.pingonemfa.push.PushApprovalService"
android:exported="false"
android:foregroundServiceType="remoteMessaging" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2026 Ping Identity Corporation. All rights reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

package com.pingidentity.pingonemfa.commons

/**
* Structured representation of a single PingOne SDK error.
*
* Instances are produced by [com.pingidentity.pingonemfa.util.ErrorParser] from the native type
* and exposed through [PingOneMFAException.internalErrorsList].
*
* @property code Numeric error code returned by the PingOne MFA native SDK. For details on returned error codes, see the native SDK documentation:
* https://pingidentity.github.io/pingone-mobile-sdk-android/-ping-one%20-m-f-a%20-android%20-s-d-k/com.pingidentity.pingidsdkv2.error/-ping-one-s-d-k-error-type/index.html
* @property message Human-readable error message returned by the native SDK.
* @property userInfo Additional diagnostic key/value pairs returned by the server.
* Intended for use for logging or debugging. The map may be empty if the server did not include
* additional context.
*/
data class Error(
val code: Int?,
val message: String?,
val userInfo: Map<String, String> = emptyMap()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2026 Ping Identity Corporation. All rights reserved.
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/

package com.pingidentity.pingonemfa.commons

import com.pingidentity.pingidsdkv2.PingOneGeo

/**
* PingOne MFA service region used when configuring the native SDK.
*
* This enum is part of the pingonemfa public API. It intentionally mirrors the
* native SDK regions without exposing the native PingOneGeo type.
*/
enum class Geo {
NORTH_AMERICA,
EUROPE,
CANADA,
AUSTRALIA,
SINGAPORE;

/**
* Converts the public wrapper value to the native SDK value at the adapter boundary.
*
* Keep this mapping internal so apps can choose a PingOne region without taking a
* compile-time dependency on native PingOne MFA SDK API types.
*/
internal fun toPingOneGeo(): PingOneGeo =
when (this) {
NORTH_AMERICA -> PingOneGeo.NORTH_AMERICA
EUROPE -> PingOneGeo.EUROPE
CANADA -> PingOneGeo.CANADA
AUSTRALIA -> PingOneGeo.AUSTRALIA
SINGAPORE -> PingOneGeo.SINGAPORE
}
}
Loading
Loading