mirror of
https://github.com/element-hq/element-android
synced 2024-11-23 18:05:36 +03:00
Support for login by m.login.token during QR code sign in
This commit is contained in:
parent
9429a4f22a
commit
88238c0f04
7 changed files with 125 additions and 5 deletions
|
@ -130,4 +130,17 @@ interface AuthenticationService {
|
||||||
* Return true if qr code login is supported by the server, false otherwise.
|
* Return true if qr code login is supported by the server, false otherwise.
|
||||||
*/
|
*/
|
||||||
suspend fun isQrLoginSupported(homeServerConnectionConfig: HomeServerConnectionConfig): Boolean
|
suspend fun isQrLoginSupported(homeServerConnectionConfig: HomeServerConnectionConfig): Boolean
|
||||||
|
* Authenticate using m.login.token method during sign in with QR code.
|
||||||
|
* @param homeServerConnectionConfig the information about the homeserver and other configuration
|
||||||
|
* @param loginToken the m.login.token
|
||||||
|
* @param initialDeviceName the initial device name
|
||||||
|
* @param deviceId the device id, optional. If not provided or null, the server will generate one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
suspend fun loginUsingQrLoginToken(
|
||||||
|
homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
loginToken: String,
|
||||||
|
initialDeviceName: String,
|
||||||
|
deviceId: String? = null
|
||||||
|
): Session
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ enum class LoginType {
|
||||||
UNSUPPORTED,
|
UNSUPPORTED,
|
||||||
CUSTOM,
|
CUSTOM,
|
||||||
DIRECT,
|
DIRECT,
|
||||||
UNKNOWN;
|
UNKNOWN,
|
||||||
|
QR;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ enum class LoginType {
|
||||||
UNSUPPORTED.name -> UNSUPPORTED
|
UNSUPPORTED.name -> UNSUPPORTED
|
||||||
CUSTOM.name -> CUSTOM
|
CUSTOM.name -> CUSTOM
|
||||||
DIRECT.name -> DIRECT
|
DIRECT.name -> DIRECT
|
||||||
|
QR.name -> QR
|
||||||
else -> UNKNOWN
|
else -> UNKNOWN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.matrix.android.sdk.internal.auth.data.WebClientConfig
|
||||||
import org.matrix.android.sdk.internal.auth.db.PendingSessionData
|
import org.matrix.android.sdk.internal.auth.db.PendingSessionData
|
||||||
import org.matrix.android.sdk.internal.auth.login.DefaultLoginWizard
|
import org.matrix.android.sdk.internal.auth.login.DefaultLoginWizard
|
||||||
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
|
import org.matrix.android.sdk.internal.auth.login.DirectLoginTask
|
||||||
|
import org.matrix.android.sdk.internal.auth.login.QrLoginTokenTask
|
||||||
import org.matrix.android.sdk.internal.auth.registration.DefaultRegistrationWizard
|
import org.matrix.android.sdk.internal.auth.registration.DefaultRegistrationWizard
|
||||||
import org.matrix.android.sdk.internal.auth.version.Versions
|
import org.matrix.android.sdk.internal.auth.version.Versions
|
||||||
import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices
|
import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices
|
||||||
|
@ -64,7 +65,8 @@ internal class DefaultAuthenticationService @Inject constructor(
|
||||||
private val sessionCreator: SessionCreator,
|
private val sessionCreator: SessionCreator,
|
||||||
private val pendingSessionStore: PendingSessionStore,
|
private val pendingSessionStore: PendingSessionStore,
|
||||||
private val getWellknownTask: GetWellknownTask,
|
private val getWellknownTask: GetWellknownTask,
|
||||||
private val directLoginTask: DirectLoginTask
|
private val directLoginTask: DirectLoginTask,
|
||||||
|
private val loginTokenAuthTask: QrLoginTokenTask
|
||||||
) : AuthenticationService {
|
) : AuthenticationService {
|
||||||
|
|
||||||
private var pendingSessionData: PendingSessionData? = pendingSessionStore.getPendingSessionData()
|
private var pendingSessionData: PendingSessionData? = pendingSessionStore.getPendingSessionData()
|
||||||
|
@ -420,6 +422,17 @@ internal class DefaultAuthenticationService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun loginUsingQrLoginToken(homeServerConnectionConfig: HomeServerConnectionConfig, loginToken: String, initialDeviceName: String, deviceId: String?): Session {
|
||||||
|
return loginTokenAuthTask.execute(
|
||||||
|
QrLoginTokenTask.Params(
|
||||||
|
homeServerConnectionConfig = homeServerConnectionConfig,
|
||||||
|
loginToken = loginToken,
|
||||||
|
deviceName = initialDeviceName,
|
||||||
|
deviceId = deviceId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
|
private fun buildAuthAPI(homeServerConnectionConfig: HomeServerConnectionConfig): AuthAPI {
|
||||||
val retrofit = retrofitFactory.create(buildClient(homeServerConnectionConfig), homeServerConnectionConfig.homeServerUriBase.toString())
|
val retrofit = retrofitFactory.create(buildClient(homeServerConnectionConfig), homeServerConnectionConfig.homeServerUriBase.toString())
|
||||||
return retrofit.create(AuthAPI::class.java)
|
return retrofit.create(AuthAPI::class.java)
|
||||||
|
|
|
@ -18,4 +18,6 @@ package org.matrix.android.sdk.internal.auth.data
|
||||||
|
|
||||||
internal interface LoginParams {
|
internal interface LoginParams {
|
||||||
val type: String
|
val type: String
|
||||||
|
val deviceDisplayName: String?
|
||||||
|
val deviceId: String?
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,8 @@ internal data class PasswordLoginParams(
|
||||||
@Json(name = "identifier") val identifier: Map<String, String>,
|
@Json(name = "identifier") val identifier: Map<String, String>,
|
||||||
@Json(name = "password") val password: String,
|
@Json(name = "password") val password: String,
|
||||||
@Json(name = "type") override val type: String,
|
@Json(name = "type") override val type: String,
|
||||||
@Json(name = "initial_device_display_name") val deviceDisplayName: String?,
|
@Json(name = "initial_device_display_name") override val deviceDisplayName: String?,
|
||||||
@Json(name = "device_id") val deviceId: String?
|
@Json(name = "device_id") override val deviceId: String?
|
||||||
) : LoginParams {
|
) : LoginParams {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -23,5 +23,7 @@ import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
internal data class TokenLoginParams(
|
internal data class TokenLoginParams(
|
||||||
@Json(name = "type") override val type: String = LoginFlowTypes.TOKEN,
|
@Json(name = "type") override val type: String = LoginFlowTypes.TOKEN,
|
||||||
@Json(name = "token") val token: String
|
@Json(name = "token") val token: String,
|
||||||
|
@Json(name = "initial_device_display_name") override val deviceDisplayName: String?,
|
||||||
|
@Json(name = "device_id") override val deviceId: String?
|
||||||
) : LoginParams
|
) : LoginParams
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.auth.login
|
||||||
|
|
||||||
|
import dagger.Lazy
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import org.matrix.android.sdk.api.auth.LoginType
|
||||||
|
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
||||||
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
import org.matrix.android.sdk.internal.auth.AuthAPI
|
||||||
|
import org.matrix.android.sdk.internal.auth.SessionCreator
|
||||||
|
import org.matrix.android.sdk.internal.auth.data.TokenLoginParams
|
||||||
|
import org.matrix.android.sdk.internal.di.Unauthenticated
|
||||||
|
import org.matrix.android.sdk.internal.network.RetrofitFactory
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.network.httpclient.addSocketFactory
|
||||||
|
import org.matrix.android.sdk.internal.network.ssl.UnrecognizedCertificateException
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface QrLoginTokenTask : Task<QrLoginTokenTask.Params, Session> {
|
||||||
|
data class Params(
|
||||||
|
val homeServerConnectionConfig: HomeServerConnectionConfig,
|
||||||
|
val loginToken: String,
|
||||||
|
val deviceName: String?,
|
||||||
|
val deviceId: String?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultQrLoginTokenTask @Inject constructor(
|
||||||
|
@Unauthenticated
|
||||||
|
private val okHttpClient: Lazy<OkHttpClient>,
|
||||||
|
private val retrofitFactory: RetrofitFactory,
|
||||||
|
private val sessionCreator: SessionCreator,
|
||||||
|
) : QrLoginTokenTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: QrLoginTokenTask.Params): Session {
|
||||||
|
val client = buildClient(params.homeServerConnectionConfig)
|
||||||
|
val homeServerUrl = params.homeServerConnectionConfig.homeServerUriBase.toString()
|
||||||
|
|
||||||
|
val authAPI = retrofitFactory.create(client, homeServerUrl)
|
||||||
|
.create(AuthAPI::class.java)
|
||||||
|
|
||||||
|
val loginParams = TokenLoginParams(
|
||||||
|
token = params.loginToken,
|
||||||
|
deviceDisplayName = params.deviceName,
|
||||||
|
deviceId = params.deviceId
|
||||||
|
)
|
||||||
|
|
||||||
|
val credentials = try {
|
||||||
|
executeRequest(null) {
|
||||||
|
authAPI.login(loginParams)
|
||||||
|
}
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
throw when (throwable) {
|
||||||
|
is UnrecognizedCertificateException -> Failure.UnrecognizedCertificateFailure(
|
||||||
|
homeServerUrl,
|
||||||
|
throwable.fingerprint
|
||||||
|
)
|
||||||
|
else -> throwable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionCreator.createSession(credentials, params.homeServerConnectionConfig, LoginType.QR)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildClient(homeServerConnectionConfig: HomeServerConnectionConfig): OkHttpClient {
|
||||||
|
return okHttpClient.get()
|
||||||
|
.newBuilder()
|
||||||
|
.addSocketFactory(homeServerConnectionConfig)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue