Skip to content

Commit

Permalink
Merge pull request #555 from vimeo/sso-connections
Browse files Browse the repository at this point in the history
Adding SsoConnections DTO and associated endpoint
  • Loading branch information
anthonycr authored Apr 28, 2022
2 parents 6499604 + 6ed77dc commit b10a070
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 2 deletions.
35 changes: 35 additions & 0 deletions auth/src/main/java/com/vimeo/networking2/Authenticator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,39 @@ interface Authenticator {
callback: VimeoCallback<VimeoAccount>
): VimeoRequest

/**
* Find a supported SSO connection that can be used by the [email] provided. If this request returns a valid
* [SsoConnection] then SSO authentication can be initiated, starting with the creation of the SSO authorization URI
* via [createSsoAuthorizationUri].
*
* @param email The email of the user that is logging in and might be supported for SSO by the Vimeo API.
* @param callback Callback to be notified of the result of the request.
*
* @return A [VimeoRequest] object to cancel API requests.
*/
@Internal
fun checkSsoConnection(
email: String,
callback: VimeoCallback<SsoConnection>
): VimeoRequest

/**
* Create a URI which can be used to log in the user via a browser and will redirect to a URI that can be exchanged
* using [authenticateWithSso] for a logged in account. Obtain the [SsoConnection] required by this function first
* using [checkSsoConnection].
*
* @param ssoConnection The connection info obtained from the API that specifies the connection URI which will be
* used as the base for this URI. NOTE: The connection URI (obtained from [SsoConnectionInteractions.connect]) must
* not be null, if a domain is provided with a null connection, then this function will return null.
* @param responseCode An arbitrary response code that can be used to verify the origin of the redirect URI. The
* API will return this value to later as a security measure in a query string parameter named `state` in the
* callback URI.
*
* @return The URI which can be opened in a browser, or null if the parameters provided were invalid.
*/
@Internal
fun createSsoAuthorizationUri(ssoConnection: SsoConnection, responseCode: String): String?

/**
* Find a supported SSO domain that matches the [domain] parameter. If this request returns a valid [SsoDomain],
* then SSO authentication can be initiated, starting with the creation of the SSO authorization URI via
Expand All @@ -258,6 +291,7 @@ interface Authenticator {
*
* @return A [VimeoRequest] object to cancel API requests.
*/
@Deprecated("Deprecated in favor of checkSsoConnection")
@Internal
fun fetchSsoDomain(
domain: String,
Expand All @@ -278,6 +312,7 @@ interface Authenticator {
*
* @return The URI which can be opened in a browser, or null if the parameters provided were invalid.
*/
@Deprecated("Deprecated in favor of the function by the same name that accepts an SsoConnection")
@Internal
fun createSsoAuthorizationUri(ssoDomain: SsoDomain, responseCode: String): String?

Expand Down
18 changes: 18 additions & 0 deletions auth/src/main/java/com/vimeo/networking2/internal/AuthService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package com.vimeo.networking2.internal
import com.vimeo.networking2.GrantType
import com.vimeo.networking2.PinCodeInfo
import com.vimeo.networking2.Scopes
import com.vimeo.networking2.SsoConnection
import com.vimeo.networking2.SsoDomain
import com.vimeo.networking2.TeamToken
import com.vimeo.networking2.VimeoAccount
Expand All @@ -35,6 +36,7 @@ import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Headers
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query
import retrofit2.http.Url
Expand Down Expand Up @@ -317,6 +319,21 @@ internal interface AuthService {
@Field(SCOPE) scopes: Scopes
): VimeoCall<VimeoAccount>

/**
* Check whether an [SsoConnection] exists for the provided [email].
*
* @param authorization Created from the client id and client secret.
* @param email The email used to check for the presence of an [SsoConnection].
*
* @return A [VimeoCall] that provides an [SsoConnection] that can be used to perform SSO.
*/
@FormUrlEncoded
@PUT("sso_connections/verify")
fun checkSsoConnection(
@Header(AUTHORIZATION) authorization: String,
@Field(EMAIL) email: String
): VimeoCall<SsoConnection>

/**
* Searches Vimeo for the presence of a supported SSO domain that matches the one provided by the [domain]
* parameter.
Expand All @@ -326,6 +343,7 @@ internal interface AuthService {
*
* @return A [VimeoCall] that provides a [SsoDomain] that can be used to perform SSO.
*/
@Deprecated("deprecated in favor of checkSsoConnection")
@Internal
@GET("sso_domains")
fun getSsoDomain(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.vimeo.networking2.Authenticator
import com.vimeo.networking2.GrantType
import com.vimeo.networking2.NoOpVimeoRequest
import com.vimeo.networking2.PinCodeInfo
import com.vimeo.networking2.SsoConnection
import com.vimeo.networking2.SsoDomain
import com.vimeo.networking2.TeamToken
import com.vimeo.networking2.VimeoAccount
Expand All @@ -35,6 +36,7 @@ import com.vimeo.networking2.config.AuthenticationMethod
import com.vimeo.networking2.internal.AuthService.Companion.AUTHORIZATION_CODE
import com.vimeo.networking2.internal.AuthService.Companion.CODE
import com.vimeo.networking2.internal.AuthService.Companion.DEVICE_CODE
import com.vimeo.networking2.internal.AuthService.Companion.DOMAIN
import com.vimeo.networking2.internal.AuthService.Companion.EMAIL
import com.vimeo.networking2.internal.AuthService.Companion.ID_TOKEN
import com.vimeo.networking2.internal.AuthService.Companion.NAME
Expand Down Expand Up @@ -231,8 +233,27 @@ internal class AuthenticatorImpl(
).url
}

override fun checkSsoConnection(email: String, callback: VimeoCallback<SsoConnection>): VimeoRequest {
val emailParameter = ApiParameter(EMAIL, email)

return localVimeoCallAdapter.validateParameters(callback, "SSO connection check error", emailParameter)
?: authService.checkSsoConnection(
authorization = authenticationMethod.basicAuthHeader,
email = email
).enqueue(callback)
}

override fun createSsoAuthorizationUri(ssoConnection: SsoConnection, responseCode: String): String? {
val connectUrl = ssoConnection.metadata?.interactions?.connect?.uri ?: return null
return authService.createSsoGrantRequest(
uri = connectUrl,
redirectUri = redirectUri,
state = responseCode
).url
}

override fun fetchSsoDomain(domain: String, callback: VimeoCallback<SsoDomain>): VimeoRequest {
val domainParameter = ApiParameter(AuthService.DOMAIN, domain)
val domainParameter = ApiParameter(DOMAIN, domain)

return localVimeoCallAdapter.validateParameters(callback, "SSO domain fetch error", domainParameter)
?: authService.getSsoDomain(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package com.vimeo.networking2.internal

import com.vimeo.networking2.Authenticator
import com.vimeo.networking2.PinCodeInfo
import com.vimeo.networking2.SsoConnection
import com.vimeo.networking2.SsoDomain
import com.vimeo.networking2.TeamToken
import com.vimeo.networking2.VimeoAccount
Expand Down Expand Up @@ -90,6 +91,12 @@ class MutableAuthenticatorDelegate(var actual: Authenticator? = null) : Authenti
override fun authenticateWithCodeGrant(uri: String, callback: VimeoCallback<VimeoAccount>): VimeoRequest =
authenticator.authenticateWithCodeGrant(uri, callback)

override fun checkSsoConnection(email: String, callback: VimeoCallback<SsoConnection>): VimeoRequest =
authenticator.checkSsoConnection(email, callback)

override fun createSsoAuthorizationUri(ssoConnection: SsoConnection, responseCode: String): String? =
authenticator.createSsoAuthorizationUri(ssoConnection, responseCode)

override fun fetchSsoDomain(domain: String, callback: VimeoCallback<SsoDomain>): VimeoRequest =
authenticator.fetchSsoDomain(domain, callback)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.vimeo.networking2.internal

import com.vimeo.networking2.Authenticator
import com.vimeo.networking2.PinCodeInfo
import com.vimeo.networking2.SsoConnection
import com.vimeo.networking2.SsoDomain
import com.vimeo.networking2.TeamToken
import com.vimeo.networking2.VimeoAccount
Expand Down Expand Up @@ -64,6 +65,10 @@ class NoOpAuthenticatorImpl(

override fun authenticateWithCodeGrant(uri: String, callback: VimeoCallback<VimeoAccount>): VimeoRequest = reject()

override fun checkSsoConnection(email: String, callback: VimeoCallback<SsoConnection>): VimeoRequest = reject()

override fun createSsoAuthorizationUri(ssoConnection: SsoConnection, responseCode: String): String = reject()

override fun fetchSsoDomain(domain: String, callback: VimeoCallback<SsoDomain>): VimeoRequest = reject()

override fun createSsoAuthorizationUri(ssoDomain: SsoDomain, responseCode: String): String = reject()
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
org.gradle.parallel=true
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx4096M
version=2.0.0
version=3.2.0

android.useAndroidX=true
android.enableJetifier=true
26 changes: 26 additions & 0 deletions models/src/main/java/com/vimeo/networking2/SsoConnection.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.vimeo.networking2

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.vimeo.networking2.annotations.Internal

/**
* A connection used to log into Vimeo via Single Sign-On.
*
* @param connectionName The name of the connection.
* @param metadata The metadata containing the interactions of the connection.
* @param uri The URI of the connection.
*/
@Internal
@JsonClass(generateAdapter = true)
data class SsoConnection(

@Json(name = "connection_name")
val connectionName: String? = null,

@Json(name = "metadata")
val metadata: MetadataInteractions<SsoConnectionInteractions>? = null,

@Json(name = "uri")
val uri: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.vimeo.networking2

import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.vimeo.networking2.annotations.Internal

/**
* The interaction for an Single Sign-On connection.
*
* @param connect The interaction to connect via Single Sign-On.
*/
@Internal
@JsonClass(generateAdapter = true)
data class SsoConnectionInteractions(

@Json(name = "connect")
val connect: BasicInteraction? = null
)
1 change: 1 addition & 0 deletions models/src/main/java/com/vimeo/networking2/SsoDomain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.vimeo.networking2.annotations.Internal
*/
@Internal
@JsonClass(generateAdapter = true)
@Deprecated("Deprecated in favor of SsoConnection")
data class SsoDomain(

@Json(name = "uri")
Expand Down
2 changes: 2 additions & 0 deletions models/src/test/java/com/vimeo/networking2/ModelsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ class ModelsTest {
SeasonList::class,
Space::class,
Spatial::class,
SsoConnection::class,
SsoConnectionInteractions::class,
SsoDomain::class,
Subscription::class,
SubscriptionInteraction::class,
Expand Down

0 comments on commit b10a070

Please sign in to comment.