PM-31953: Support multiple schemes for Duo, WebAuthn, and SSO callbacks (#6498)

This commit is contained in:
David Perez
2026-02-10 14:21:40 -06:00
committed by GitHub
parent 43940102ff
commit 31d480d6b4
28 changed files with 608 additions and 157 deletions

View File

@@ -45,6 +45,7 @@ internal interface UnauthenticatedIdentityApi {
@Field(value = "twoFactorRemember") twoFactorRemember: String?,
@Field(value = "authRequest") authRequestId: String?,
@Field(value = "newDeviceOtp") newDeviceOtp: String?,
@Field(value = "deeplinkScheme") deeplinkScheme: String,
): NetworkResult<GetTokenResponseJson.Success>
@GET("/sso/prevalidate")

View File

@@ -33,6 +33,7 @@ interface IdentityService {
* Make request to get an access token.
*
* @param uniqueAppId applications unique identifier.
* @param deeplinkScheme deeplink scheme to use for duo two-factor logins.
* @param email user's email address.
* @param authModel information necessary to authenticate with any
* of the available login methods.
@@ -41,6 +42,7 @@ interface IdentityService {
@Suppress("LongParameterList")
suspend fun getToken(
uniqueAppId: String,
deeplinkScheme: String,
email: String,
authModel: IdentityTokenAuthModel,
twoFactorData: TwoFactorDataModel? = null,

View File

@@ -54,6 +54,7 @@ internal class IdentityServiceImpl(
override suspend fun getToken(
uniqueAppId: String,
deeplinkScheme: String,
email: String,
authModel: IdentityTokenAuthModel,
twoFactorData: TwoFactorDataModel?,
@@ -76,6 +77,7 @@ internal class IdentityServiceImpl(
twoFactorRemember = twoFactorData?.remember?.let { if (it) "1" else "0 " },
authRequestId = authModel.authRequestId,
newDeviceOtp = newDeviceOtp,
deeplinkScheme = deeplinkScheme,
)
.toResult()
.recoverCatching { throwable ->

View File

@@ -184,6 +184,7 @@ class IdentityServiceTest : BaseServiceTest() {
password = PASSWORD_HASH,
),
uniqueAppId = UNIQUE_APP_ID,
deeplinkScheme = DEEPLINK_SCHEME,
)
assertEquals(LOGIN_SUCCESS.asSuccess(), result)
}
@@ -198,6 +199,7 @@ class IdentityServiceTest : BaseServiceTest() {
password = PASSWORD_HASH,
),
uniqueAppId = UNIQUE_APP_ID,
deeplinkScheme = DEEPLINK_SCHEME,
)
assertTrue(result.isFailure)
}
@@ -212,6 +214,7 @@ class IdentityServiceTest : BaseServiceTest() {
password = PASSWORD_HASH,
),
uniqueAppId = UNIQUE_APP_ID,
deeplinkScheme = DEEPLINK_SCHEME,
)
assertEquals(TWO_FACTOR_BODY.asSuccess(), result)
}
@@ -226,6 +229,7 @@ class IdentityServiceTest : BaseServiceTest() {
password = PASSWORD_HASH,
),
uniqueAppId = UNIQUE_APP_ID,
deeplinkScheme = DEEPLINK_SCHEME,
)
assertEquals(INVALID_LOGIN.asSuccess(), result)
}
@@ -241,6 +245,7 @@ class IdentityServiceTest : BaseServiceTest() {
password = PASSWORD_HASH,
),
uniqueAppId = UNIQUE_APP_ID,
deeplinkScheme = DEEPLINK_SCHEME,
)
assertEquals(INVALID_LOGIN.asSuccess(), result)
}
@@ -438,6 +443,7 @@ class IdentityServiceTest : BaseServiceTest() {
}
companion object {
private const val DEEPLINK_SCHEME = "deeplinkScheme"
private const val UNIQUE_APP_ID = "testUniqueAppId"
private const val REFRESH_TOKEN = "refreshToken"
private const val EMAIL_TOKEN = "emailToken"