Skip to content

Commit 717be11

Browse files
titanousThexXTURBOXx
authored andcommitted
1 parent 925cc48 commit 717be11

6 files changed

Lines changed: 71 additions & 19 deletions

File tree

flutter_web_auth_2/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
A Flutter plugin for authenticating a user with a web service, even if the web service is run by a third party. Most commonly used with OAuth2, but can be used with any web flow that can redirect to a custom scheme.
88

9-
In the background, this plugin uses [`ASWebAuthenticationSession`](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) on iOS 12+ and macOS 10.15+, [`SFAuthenticationSession`](https://developer.apple.com/documentation/safariservices/sfauthenticationsession) on iOS 11, [Chrome Custom Tabs](https://developer.chrome.com/docs/android/custom-tabs/) on Android and opens a new window on Web. You can build it with iOS 8+, but it is currently only supported by iOS 11 or higher.
9+
In the background, this plugin uses [`ASWebAuthenticationSession`](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession) on iOS 12+ and macOS 10.15+, [`SFAuthenticationSession`](https://developer.apple.com/documentation/safariservices/sfauthenticationsession) on iOS 11, [Chrome Auth Tab](https://developer.chrome.com/docs/android/custom-tabs/guide-auth-tab) on Android and opens a new window on Web. You can build it with iOS 8+, but it is currently only supported by iOS 11 or higher.
1010

1111
<!-- TODO: Replace with a nicer GIF
1212
| **iOS** | **Android** |
@@ -88,6 +88,7 @@ final accessToken = jsonDecode(response.body)['access_token'] as String;
8888

8989
The following constraints have been added in `5.0.0`:
9090
- The existing Android approach has been replaced with a new (improved) one (no migration necessary; is automatically used)
91+
- Android now uses Auth Tab: `httpsHost` and `httpsPath` are now required on Android if you are using a `https` in `callbackUrlScheme`
9192
- Dart SDK `>=3.5.0` is now required (due to migration to melos `7.x`)
9293

9394
### Upgrading to `4.x`

flutter_web_auth_2/android/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ android {
4949
}
5050

5151
dependencies {
52-
implementation 'androidx.browser:browser:1.8.0'
52+
implementation 'androidx.browser:browser:1.9.0-alpha01'
53+
implementation 'androidx.activity:activity-ktx:1.10.1'
5354
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
5455
}
5556
}
Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,98 @@
11
package com.linusu.flutter_web_auth_2
22

3-
import android.app.Activity
43
import android.content.Context
54
import android.content.Intent
65
import android.net.Uri
76
import android.os.Build
87
import android.os.Bundle
9-
import androidx.browser.customtabs.CustomTabsIntent
8+
import android.util.Log
9+
import androidx.activity.ComponentActivity
10+
import androidx.activity.result.ActivityResultLauncher
11+
import androidx.browser.auth.AuthTabIntent
12+
import androidx.browser.auth.AuthTabIntent.AuthResult
1013

11-
class AuthenticationManagementActivity(
12-
) : Activity() {
14+
class AuthenticationManagementActivity : ComponentActivity() {
1315
companion object {
1416
const val KEY_AUTH_STARTED: String = "authStarted"
1517
const val KEY_AUTH_URI: String = "authUri"
1618
const val KEY_AUTH_OPTION_INTENT_FLAGS: String = "authOptionsIntentFlags"
1719
const val KEY_AUTH_OPTION_TARGET_PACKAGE: String = "authOptionsTargetPackage"
20+
const val KEY_AUTH_CALLBACK_SCHEME: String = "authCallbackScheme"
21+
const val KEY_AUTH_CALLBACK_HOST: String = "authCallbackHost"
22+
const val KEY_AUTH_CALLBACK_PATH: String = "authCallbackPath"
1823

1924
fun createResponseHandlingIntent(context: Context): Intent {
2025
val intent = Intent(context, AuthenticationManagementActivity::class.java)
2126
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
2227
return intent
2328
}
2429
}
30+
2531
private var authStarted: Boolean = false
2632
private lateinit var authenticationUri: Uri
2733
private var intentFlags: Int = 0
2834
private var targetPackage: String? = null
35+
private lateinit var callbackScheme: String
36+
private var callbackHost: String? = null
37+
private var callbackPath: String? = null
38+
39+
private lateinit var authLauncher: ActivityResultLauncher<Intent>
2940

3041
override fun onCreate(savedInstanceState: Bundle?) {
3142
super.onCreate(savedInstanceState)
43+
44+
// Register the activity result launcher
45+
authLauncher = AuthTabIntent.registerActivityResultLauncher(this, this::handleAuthResult)
46+
3247
if (savedInstanceState == null) {
3348
extractState(intent.extras)
3449
} else {
3550
extractState(savedInstanceState)
3651
}
3752
}
3853

54+
private fun handleAuthResult(result: AuthResult) {
55+
val callback = FlutterWebAuth2Plugin.callbacks[callbackScheme]
56+
if (callback == null) {
57+
finish()
58+
return
59+
}
60+
61+
when (result.resultCode) {
62+
AuthTabIntent.RESULT_OK -> {
63+
callback.success(result.resultUri!!.toString())
64+
}
65+
AuthTabIntent.RESULT_CANCELED -> {
66+
callback.error("CANCELED", "User canceled authentication", null)
67+
}
68+
else -> {
69+
callback.error("FAILED", "Authentication failed with code: ${result.resultCode}", null)
70+
}
71+
}
72+
73+
FlutterWebAuth2Plugin.callbacks.remove(callbackScheme)
74+
finish()
75+
}
76+
3977
override fun onResume() {
4078
super.onResume()
4179

4280
if (!authStarted) {
43-
val intent = CustomTabsIntent.Builder().build()
81+
val intent = AuthTabIntent.Builder().build()
4482
intent.intent.addFlags(intentFlags)
4583

4684
if (targetPackage != null) {
4785
intent.intent.setPackage(targetPackage)
4886
}
49-
intent.launchUrl(this, authenticationUri)
87+
88+
if (callbackScheme == "https" && callbackHost != null && callbackPath != null) {
89+
Log.d("flutter_web_auth_2", "Using https host and path: $callbackHost, $callbackPath")
90+
intent.launch(authLauncher, authenticationUri, callbackHost!!, callbackPath!!)
91+
} else {
92+
Log.d("flutter_web_auth_2", "Using custom scheme: $callbackScheme")
93+
intent.launch(authLauncher, authenticationUri, callbackScheme)
94+
}
95+
5096
authStarted = true
5197
return
5298
}
@@ -57,20 +103,18 @@ class AuthenticationManagementActivity(
57103
finish()
58104
}
59105

60-
override fun onNewIntent(intent: Intent?) {
61-
super.onNewIntent(intent)
62-
setIntent(intent);
63-
}
64-
65106
override fun onSaveInstanceState(outState: Bundle) {
66107
super.onSaveInstanceState(outState)
67108
outState.putBoolean(KEY_AUTH_STARTED, authStarted)
68109
outState.putParcelable(KEY_AUTH_URI, authenticationUri)
69110
outState.putInt(KEY_AUTH_OPTION_INTENT_FLAGS, intentFlags)
70111
outState.putString(
71112
KEY_AUTH_OPTION_TARGET_PACKAGE,
72-
targetPackage
113+
targetPackage,
73114
)
115+
outState.putString(KEY_AUTH_CALLBACK_SCHEME, callbackScheme)
116+
outState.putString(KEY_AUTH_CALLBACK_HOST, callbackHost)
117+
outState.putString(KEY_AUTH_CALLBACK_PATH, callbackPath)
74118
}
75119

76120
private fun extractState(state: Bundle?) {
@@ -87,5 +131,8 @@ class AuthenticationManagementActivity(
87131
} ?: throw IllegalStateException("Authentication URI is null")
88132
intentFlags = state.getInt(KEY_AUTH_OPTION_INTENT_FLAGS, 0)
89133
targetPackage = state.getString(KEY_AUTH_OPTION_TARGET_PACKAGE)
134+
callbackScheme = state.getString(KEY_AUTH_CALLBACK_SCHEME)!!
135+
callbackHost = state.getString(KEY_AUTH_CALLBACK_HOST)
136+
callbackPath = state.getString(KEY_AUTH_CALLBACK_PATH)
90137
}
91138
}

flutter_web_auth_2/android/src/main/kotlin/com/linusu/flutter_web_auth_2/FlutterWebAuth2Plugin.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,17 @@ class FlutterWebAuth2Plugin(
4545
when (call.method) {
4646
"authenticate" -> {
4747
val url = Uri.parse(call.argument("url"))
48-
val callbackUrlScheme = call.argument<String>("callbackUrlScheme")!!
48+
val callbackUrlScheme: String = call.argument<String>("callbackUrlScheme")!!
4949
val options = call.argument<Map<String, Any>>("options")!!
5050

5151
callbacks[callbackUrlScheme] = resultCallback
5252
activity?.startActivity(Intent(activity,AuthenticationManagementActivity::class.java).apply {
5353
putExtra(AuthenticationManagementActivity.KEY_AUTH_URI,url)
5454
putExtra(AuthenticationManagementActivity.KEY_AUTH_OPTION_INTENT_FLAGS, options["intentFlags"] as Int)
5555
putExtra(AuthenticationManagementActivity.KEY_AUTH_OPTION_TARGET_PACKAGE, findTargetBrowserPackageName(options))
56+
putExtra(AuthenticationManagementActivity.KEY_AUTH_CALLBACK_SCHEME, callbackUrlScheme)
57+
putExtra(AuthenticationManagementActivity.KEY_AUTH_CALLBACK_HOST, options["httpsHost"] as String?)
58+
putExtra(AuthenticationManagementActivity.KEY_AUTH_CALLBACK_PATH, options["httpsPath"] as String?)
5659
})
5760
}
5861

flutter_web_auth_2/example/android/gradlew

100644100755
File mode changed.

flutter_web_auth_2/lib/src/options.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,20 @@ class FlutterWebAuth2Options {
140140
/// described in https://github.com/ThexXTURBOXx/flutter_web_auth_2/issues/25
141141
final bool useWebview;
142142

143-
/// **Only has an effect on iOS, Linux, macOS, and Windows!**
143+
/// **Only has an effect on Android, iOS, Linux, macOS, and Windows!**
144144
/// String specifying the **host** of the URL that the page will redirect to
145145
/// upon successful authentication (callback URL).
146146
/// When `callbackUrlScheme` is `https`, this **must** be specified on
147-
/// Apple devices running iOS >= 17.4 or macOS >= 14.4.
147+
/// Android and Apple devices running iOS >= 17.4 or macOS >= 14.4.
148148
/// On Linux and Windows, this is used when `useWebview == true` in order to
149149
/// compare with the host of the callback URL (no matter which scheme!).
150150
final String? httpsHost;
151151

152-
/// **Only has an effect on iOS, Linux, macOS, and Windows!**
152+
/// **Only has an effect on Android, iOS, Linux, macOS, and Windows!**
153153
/// String specifying the **path** of the URL that the page will redirect to
154154
/// upon successful authentication (callback URL).
155155
/// When `callbackUrlScheme` is `https`, this **must** be specified on
156-
/// Apple devices running iOS >= 17.4 or macOS >= 14.4.
156+
/// Android and Apple devices running iOS >= 17.4 or macOS >= 14.4.
157157
/// On Linux and Windows, this is used when `useWebview == true` in order to
158158
/// compare with the path of the callback URL (no matter which scheme!).
159159
final String? httpsPath;

0 commit comments

Comments
 (0)