@@ -4,18 +4,16 @@ import android.content.Context
4
4
import android.net.Uri
5
5
import androidx.browser.customtabs.CustomTabsIntent
6
6
import com.descope.internal.http.DescopeClient
7
+ import com.descope.internal.others.toBase64
7
8
import com.descope.internal.others.with
8
9
import com.descope.sdk.DescopeFlow
9
10
import com.descope.sdk.DescopeLogger.Level.Info
10
11
import com.descope.types.AuthenticationResponse
11
12
import com.descope.types.DescopeException
12
13
import com.descope.types.Result
13
14
import java.security.MessageDigest
14
- import kotlin.io.encoding.Base64
15
- import kotlin.io.encoding.ExperimentalEncodingApi
16
15
import kotlin.random.Random
17
16
18
- @OptIn(ExperimentalEncodingApi ::class )
19
17
internal class Flow (
20
18
override val client : DescopeClient
21
19
) : Route, DescopeFlow {
@@ -44,27 +42,27 @@ internal class Flow(
44
42
Random .nextBytes(randomBytes)
45
43
46
44
// codeVerifier == base64(randomBytes)
47
- codeVerifier = Base64 . UrlSafe .encode(randomBytes )
45
+ codeVerifier = randomBytes.toBase64( )
48
46
49
47
// hash bytes using sha256
50
48
val md = MessageDigest .getInstance(" SHA-256" )
51
49
val hashed = md.digest(randomBytes)
52
50
53
51
// codeChallenge == base64(sha256(randomBytes))
54
- val codeChallenge = Base64 . UrlSafe .encode(hashed )
52
+ val codeChallenge = hashed.toBase64( )
55
53
56
- // embed into url parameters
57
- val uriBuilder = Uri .parse(flowUrl).buildUpon()
58
- .appendQueryParameter(" ra-callback" , deepLinkUrl)
59
- .appendQueryParameter(" ra-challenge" , codeChallenge)
60
- .appendQueryParameter(" ra-initiator" , " android" )
61
- backupCustomScheme?.let {
62
- uriBuilder.appendQueryParameter(" ra-backup-callback" , it)
63
- }
64
- val uri = uriBuilder.build()
54
+ startFlowViaBrowser(codeChallenge, context)
55
+ }
65
56
66
- // launch via chrome custom tabs
67
- launchUri(context, uri)
57
+ override suspend fun start (context : Context , flowId : String , refreshJwt : String ) {
58
+ val primeResponse = client.flowPrime(flowId, refreshJwt)
59
+ // use server generated verifier and challenge
60
+ codeVerifier = primeResponse.codeVerifier
61
+ startFlowViaBrowser(primeResponse.codeChallenge, context)
62
+ }
63
+
64
+ override fun start (context : Context , flowId : String , refreshJwt : String , callback : (Result <Unit >) -> Unit ) = wrapCoroutine(callback) {
65
+ start(context, flowId, refreshJwt)
68
66
}
69
67
70
68
override fun resume (context : Context , incomingUriString : String ) {
@@ -92,6 +90,22 @@ internal class Flow(
92
90
override fun exchange (incomingUri : Uri , callback : (Result <AuthenticationResponse >) -> Unit ) = wrapCoroutine(callback) {
93
91
exchange(incomingUri)
94
92
}
93
+
94
+ // Internal
95
+
96
+ private fun startFlowViaBrowser (codeChallenge : String , context : Context ) {
97
+ val uriBuilder = Uri .parse(flowUrl).buildUpon()
98
+ .appendQueryParameter(" ra-callback" , deepLinkUrl)
99
+ .appendQueryParameter(" ra-challenge" , codeChallenge)
100
+ .appendQueryParameter(" ra-initiator" , " android" )
101
+ backupCustomScheme?.let {
102
+ uriBuilder.appendQueryParameter(" ra-backup-callback" , it)
103
+ }
104
+ val uri = uriBuilder.build()
105
+
106
+ // launch via chrome custom tabs
107
+ launchUri(context, uri)
108
+ }
95
109
96
110
}
97
111
0 commit comments