Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-12406] Introduce new endpoint and replace SSO details response flow #4177

Merged
merged 20 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9757160
[PM-12406] Add unauthenticated verified org domains endpoint setup
andrebispo5 Oct 25, 2024
ea16cd9
[PM-12406] Add verified organization domain details service call to Oโ€ฆ
andrebispo5 Oct 25, 2024
4768824
[PM-12406] Add feature flag for the new verified SSO domain endpoint
andrebispo5 Oct 25, 2024
467ccde
[PM-12406] Add missing feature flag information
andrebispo5 Oct 25, 2024
74efb7e
[PM-12406] Add verified organization domain details call to AuthReposโ€ฆ
andrebispo5 Oct 25, 2024
689a93b
[PM-12406] Add verified date to OrganizationDomainSsoDetailsResponseJson
andrebispo5 Oct 28, 2024
23ede75
[PM-12406] Add verifiedDate to SSO login checks
andrebispo5 Oct 28, 2024
c75cf4f
[PM-12406] handle verified organization domain sso details within theโ€ฆ
andrebispo5 Oct 28, 2024
4ad36c7
[PM-12406] Add no verified date test.
andrebispo5 Oct 28, 2024
23de960
[PM-12406] Add verified date property where it's missing
andrebispo5 Oct 28, 2024
57971b0
[PM-12406] Add test for new verified domain flows to SSO login viewmodel
andrebispo5 Oct 28, 2024
0fdbd07
Merge branch 'main' into pm-12406/domain-verified-endpoint
andrebispo5 Oct 28, 2024
b5f02cf
[PM-12406] Fix DebugMenuViewModelTests with new endpoint feature flag
andrebispo5 Oct 28, 2024
ee652f8
Merge branch 'pm-12406/domain-verified-endpoint' of https://github.coโ€ฆ
andrebispo5 Oct 28, 2024
27852b3
Merge branch 'main' into pm-12406/domain-verified-endpoint
andrebispo5 Oct 29, 2024
6159089
Merge branch 'main' into pm-12406/domain-verified-endpoint
andrebispo5 Oct 30, 2024
c5eac9b
[PM-12406] PR comments fixes
andrebispo5 Oct 30, 2024
b36e301
[PM-12406] lint
andrebispo5 Oct 30, 2024
cc1ab8e
[PM-12406] lint
andrebispo5 Oct 30, 2024
8b573ec
Merge branch 'main' into pm-12406/domain-verified-endpoint
andrebispo5 Oct 31, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.x8bit.bitwarden.data.auth.datasource.network.api

import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationDomainSsoDetailsRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationDomainSsoDetailsResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsRequest
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse
import retrofit2.http.Body
import retrofit2.http.POST

Expand All @@ -16,4 +18,12 @@ interface UnauthenticatedOrganizationApi {
suspend fun getClaimedDomainOrganizationDetails(
@Body body: OrganizationDomainSsoDetailsRequestJson,
): Result<OrganizationDomainSsoDetailsResponseJson>

/**
* Checks for the verfied organization domains of an email for SSO purposes.
*/
@POST("/organizations/domain/sso/verified")
suspend fun getVerifiedOrganizationDomainsByEmail(
@Body body: VerifiedOrganizationDomainSsoDetailsRequest,
): Result<VerifiedOrganizationDomainSsoDetailsResponse>
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package com.x8bit.bitwarden.data.auth.datasource.network.model

import kotlinx.serialization.Contextual
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.ZonedDateTime

/**
* Response object returned when requesting organization domain SSO details.
*
* @property isSsoAvailable Whether or not SSO is available for this domain.
* @property organizationIdentifier The organization's identifier.
* @property verifiedDate The date the domain was verified.
*/
@Serializable
data class OrganizationDomainSsoDetailsResponseJson(
@SerialName("ssoAvailable") val isSsoAvailable: Boolean,
@SerialName("organizationIdentifier") val organizationIdentifier: String,
@SerialName("ssoAvailable")
val isSsoAvailable: Boolean,

@SerialName("organizationIdentifier")
val organizationIdentifier: String,

@SerialName("verifiedDate")
@Contextual
val verifiedDate: ZonedDateTime?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.x8bit.bitwarden.data.auth.datasource.network.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Request body object when retrieving organization verified domain SSO info.
*
* @param email The email address to check against.
*/
@Serializable
data class VerifiedOrganizationDomainSsoDetailsRequest(
@SerialName("email") val email: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.x8bit.bitwarden.data.auth.datasource.network.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

/**
* Response object returned when requesting organization verified domain SSO details.
*
* @property verifiedOrganizationDomainSsoDetails The list of verified organization domain SSO
* details.
*/
@Serializable
data class VerifiedOrganizationDomainSsoDetailsResponse(
@SerialName("data")
val verifiedOrganizationDomainSsoDetails: List<VerifiedOrganizationDomainSsoDetail>,
) {
/**
* Response body for an organization verified domain SSO details.
*
* @property organizationName The name of the organization.
* @property organizationIdentifier The identifier of the organization.
* @property domainName The name of the domain.
*/
@Serializable
data class VerifiedOrganizationDomainSsoDetail(
@SerialName("organizationName")
val organizationName: String,

@SerialName("organizationIdentifier")
val organizationIdentifier: String,

@SerialName("domainName")
val domainName: String,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.data.auth.datasource.network.service
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationAutoEnrollStatusResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationDomainSsoDetailsResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationKeysResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse

/**
* Provides an API for querying organization endpoints.
Expand Down Expand Up @@ -38,4 +39,12 @@ interface OrganizationService {
suspend fun getOrganizationKeys(
organizationId: String,
): Result<OrganizationKeysResponseJson>

/**
* Request organization verified domain details for an [email] needed for SSO
* requests.
*/
suspend fun getVerifiedOrganizationDomainSsoDetails(
email: String,
): Result<VerifiedOrganizationDomainSsoDetailsResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationDomain
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationDomainSsoDetailsResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationKeysResponseJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.OrganizationResetPasswordEnrollRequestJson
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsRequest
import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse

/**
* Default implementation of [OrganizationService].
Expand Down Expand Up @@ -52,4 +54,13 @@ class OrganizationServiceImpl(
.getOrganizationKeys(
organizationId = organizationId,
)

override suspend fun getVerifiedOrganizationDomainSsoDetails(
email: String,
): Result<VerifiedOrganizationDomainSsoDetailsResponse> = unauthenticatedOrganizationApi
.getVerifiedOrganizationDomainsByEmail(
body = VerifiedOrganizationDomainSsoDetailsRequest(
email = email,
),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.SwitchAccountResult
import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePinResult
import com.x8bit.bitwarden.data.auth.repository.model.VerifiedOrganizationDomainSsoDetailsResult
import com.x8bit.bitwarden.data.auth.repository.model.VerifyOtpResult
import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult
import com.x8bit.bitwarden.data.auth.repository.util.DuoCallbackTokenResult
Expand Down Expand Up @@ -329,6 +330,13 @@ interface AuthRepository : AuthenticatorProvider, AuthRequestManager {
email: String,
): OrganizationDomainSsoDetailsResult

/**
* Get the verified organization domain SSO details for the given [email].
*/
suspend fun getVerifiedOrganizationDomainSsoDetails(
email: String,
): VerifiedOrganizationDomainSsoDetailsResult

/**
* Prevalidates the organization identifier used in an SSO request.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import com.x8bit.bitwarden.data.auth.repository.model.UserState
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePasswordResult
import com.x8bit.bitwarden.data.auth.repository.model.ValidatePinResult
import com.x8bit.bitwarden.data.auth.repository.model.VaultUnlockType
import com.x8bit.bitwarden.data.auth.repository.model.VerifiedOrganizationDomainSsoDetailsResult
import com.x8bit.bitwarden.data.auth.repository.model.VerifyOtpResult
import com.x8bit.bitwarden.data.auth.repository.model.toLoginErrorResult
import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult
Expand Down Expand Up @@ -1123,11 +1124,27 @@ class AuthRepositoryImpl(
OrganizationDomainSsoDetailsResult.Success(
isSsoAvailable = it.isSsoAvailable,
organizationIdentifier = it.organizationIdentifier,
verifiedDate = it.verifiedDate,
)
},
onFailure = { OrganizationDomainSsoDetailsResult.Failure },
)

override suspend fun getVerifiedOrganizationDomainSsoDetails(
email: String,
): VerifiedOrganizationDomainSsoDetailsResult = organizationService
.getVerifiedOrganizationDomainSsoDetails(
email = email,
)
.fold(
onSuccess = {
VerifiedOrganizationDomainSsoDetailsResult.Success(
verifiedOrganizationDomainSsoDetails = it.verifiedOrganizationDomainSsoDetails,
)
},
onFailure = { VerifiedOrganizationDomainSsoDetailsResult.Failure },
)

override suspend fun prevalidateSso(
organizationIdentifier: String,
): PrevalidateSsoResult = identityService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.x8bit.bitwarden.data.auth.repository.model

import java.time.ZonedDateTime

/**
* Response types when checking for an email's claimed domain organization.
*/
Expand All @@ -9,10 +11,12 @@ sealed class OrganizationDomainSsoDetailsResult {
*
* @property isSsoAvailable Indicates if SSO is available for the email address.
* @property organizationIdentifier The claimed organization identifier for the email address.
* @property verifiedDate The date and time when the domain was verified.
*/
data class Success(
val isSsoAvailable: Boolean,
val organizationIdentifier: String,
val verifiedDate: ZonedDateTime?,
) : OrganizationDomainSsoDetailsResult()

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.x8bit.bitwarden.data.auth.repository.model

import com.x8bit.bitwarden.data.auth.datasource.network.model.VerifiedOrganizationDomainSsoDetailsResponse.VerifiedOrganizationDomainSsoDetail

/**
* Response types when checking for an email's claimed domain organization.
*/
sealed class VerifiedOrganizationDomainSsoDetailsResult {
/**
* The request was successful.
*
* @property verifiedOrganizationDomainSsoDetails The verified organization domain SSO details.
*/
data class Success(
val verifiedOrganizationDomainSsoDetails: List<VerifiedOrganizationDomainSsoDetail>,
) : VerifiedOrganizationDomainSsoDetailsResult()

/**
* The request failed.
*/
data object Failure : VerifiedOrganizationDomainSsoDetailsResult()
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ sealed class FlagKey<out T : Any> {
OnboardingCarousel,
ImportLoginsFlow,
SshKeyCipherItems,
VerifiedSsoDomainEndpoint,
)
}
}
Expand Down Expand Up @@ -89,6 +90,14 @@ sealed class FlagKey<out T : Any> {
override val defaultValue: Boolean = false
override val isRemotelyConfigured: Boolean = true
}
/**
* Data object holding the feature flag key for the new verified SSO domain endpoint feature.
*/
data object VerifiedSsoDomainEndpoint : FlagKey<Boolean>() {
override val keyName: String = "pm-12337-refactor-sso-details-endpoint"
override val defaultValue: Boolean = false
override val isRemotelyConfigured: Boolean = true
}

/**
* Data object holding the key for a [Boolean] flag to be used in tests.
Expand Down
Loading