From f15851b8f1650efb8c0a0a8f1463a2120345cdd1 Mon Sep 17 00:00:00 2001 From: HuangRed Date: Fri, 23 Aug 2024 08:54:05 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=85=B3=E9=97=AD=E7=BD=91=E9=A1=B5?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E6=B7=BB=E5=8A=A0onLoad=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/twitter_login.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/twitter_login.dart b/lib/src/twitter_login.dart index 55f711e..e847792 100644 --- a/lib/src/twitter_login.dart +++ b/lib/src/twitter_login.dart @@ -173,7 +173,7 @@ class TwitterLogin { } } - Future loginV2({bool forceLogin = false}) async { + Future loginV2({bool forceLogin = false, void Function()? onLoad}) async { String? resultURI; RequestToken requestToken; try { @@ -253,6 +253,7 @@ class TwitterLogin { throw const CanceledByUserException(); } + onLoad?.call(); final token = await AccessToken.getAccessToken( apiKey, apiSecretKey, From b4b55d5ed501ebcf7d043a5cd0191cff0783d4cf Mon Sep 17 00:00:00 2001 From: HuangRed Date: Wed, 18 Sep 2024 09:20:43 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E7=9A=84=E7=99=BB=E5=BD=95=E4=BA=A4=E4=BA=92=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/main.dart | 110 ++++++++++---------- lib/entity/auth_result.dart | 21 ++-- lib/src/twitter_login.dart | 196 ++---------------------------------- 3 files changed, 70 insertions(+), 257 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index e6e364c..8dd8108 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:twitter_login/twitter_login.dart'; + void main() { runApp(MyApp()); @@ -73,77 +73,77 @@ class _MyAppState extends State { /// Use Twitter API v1.1 Future login() async { - final twitterLogin = TwitterLogin( - /// Consumer API keys - apiKey: apiKey, + // final twitterLogin = TwitterLogin( + // /// Consumer API keys + // // apiKey: apiKey, - /// Consumer API Secret keys - apiSecretKey: apiSecretKey, + // /// Consumer API Secret keys + // // apiSecretKey: apiSecretKey, - /// Registered Callback URLs in TwitterApp - /// Android is a deeplink - /// iOS is a URLScheme - redirectURI: 'example://', - ); + // /// Registered Callback URLs in TwitterApp + // /// Android is a deeplink + // /// iOS is a URLScheme + // redirectURI: 'example://', + // ); /// Forces the user to enter their credentials /// to ensure the correct users account is authorized. /// If you want to implement Twitter account switching, set [force_login] to true /// login(forceLogin: true); - final authResult = await twitterLogin.login(); - switch (authResult.status) { - case TwitterLoginStatus.loggedIn: - // success - print('====== Login success ======'); - print(authResult.authToken); - print(authResult.authTokenSecret); - break; - case TwitterLoginStatus.cancelledByUser: - // cancel - print('====== Login cancel ======'); - break; - case TwitterLoginStatus.error: - case null: - // error - print('====== Login error ======'); - break; - } + // final authResult = await twitterLogin.login(); + // switch (authResult.status) { + // case TwitterLoginStatus.loggedIn: + // // success + // print('====== Login success ======'); + // print(authResult.authToken); + // print(authResult.authTokenSecret); + // break; + // case TwitterLoginStatus.cancelledByUser: + // // cancel + // print('====== Login cancel ======'); + // break; + // case TwitterLoginStatus.error: + // case null: + // // error + // print('====== Login error ======'); + // break; + // } } /// Use Twitter API v2. Future loginV2() async { - final twitterLogin = TwitterLogin( - /// Consumer API keys - apiKey: apiKey, + // final twitterLogin = TwitterLogin( + // /// Consumer API keys + // //apiKey: apiKey, - /// Consumer API Secret keys - apiSecretKey: apiSecretKey, + // /// Consumer API Secret keys + // // apiSecretKey: apiSecretKey, - /// Registered Callback URLs in TwitterApp - /// Android is a deeplink - /// iOS is a URLScheme - redirectURI: 'example://', - ); + // /// Registered Callback URLs in TwitterApp + // /// Android is a deeplink + // /// iOS is a URLScheme + // redirectURI: 'example://', + // ); /// Forces the user to enter their credentials /// to ensure the correct users account is authorized. /// If you want to implement Twitter account switching, set [force_login] to true /// login(forceLogin: true); - final authResult = await twitterLogin.loginV2(); - switch (authResult.status) { - case TwitterLoginStatus.loggedIn: - // success - print('====== Login success ======'); - break; - case TwitterLoginStatus.cancelledByUser: - // cancel - print('====== Login cancel ======'); - break; - case TwitterLoginStatus.error: - case null: - // error - print('====== Login error ======'); - break; - } + // final authResult = await twitterLogin.loginV2(); + // switch (authResult.status) { + // case TwitterLoginStatus.loggedIn: + // // success + // print('====== Login success ======'); + // break; + // case TwitterLoginStatus.cancelledByUser: + // // cancel + // print('====== Login cancel ======'); + // break; + // case TwitterLoginStatus.error: + // case null: + // // error + // print('====== Login error ======'); + // break; + // } } } diff --git a/lib/entity/auth_result.dart b/lib/entity/auth_result.dart index 7a8782a..1c86196 100644 --- a/lib/entity/auth_result.dart +++ b/lib/entity/auth_result.dart @@ -1,29 +1,26 @@ import 'dart:core'; -import 'package:twitter_login/entity/user.dart'; import 'package:twitter_login/src/twitter_login.dart'; /// The result when the Twitter login flow has completed. /// The login methods always return an instance of this class. class AuthResult { - /// constructor AuthResult({ String? authToken, - String? authTokenSecret, + String? authVerifier, required TwitterLoginStatus status, String? errorMessage, - User? user, }) : _authToken = authToken, - _authTokenSecret = authTokenSecret, + _authVerifier = authVerifier, _status = status, - _errorMessage = errorMessage, - _user = user; + _errorMessage = errorMessage; + /// The access token for using the Twitter APIs final String? _authToken; - //// The access token secret for using the Twitter APIs - final String? _authTokenSecret; + /// The access token secret for using the Twitter APIs + final String? _authVerifier; /// The status after a Twitter login flow has completed final TwitterLoginStatus? _status; @@ -31,12 +28,8 @@ class AuthResult { /// The error message when the log in flow completed with an error final String? _errorMessage; - /// Twitter Account user Info. - final User? _user; - String? get authToken => _authToken; - String? get authTokenSecret => _authTokenSecret; + String? get authVerifier => _authVerifier; TwitterLoginStatus? get status => _status; String? get errorMessage => _errorMessage; - User? get user => _user; } diff --git a/lib/src/twitter_login.dart b/lib/src/twitter_login.dart index e847792..72ce73b 100644 --- a/lib/src/twitter_login.dart +++ b/lib/src/twitter_login.dart @@ -1,12 +1,9 @@ import 'dart:async'; import 'dart:io'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:twitter_login/entity/auth_result.dart'; -import 'package:twitter_login/entity/user.dart'; -import 'package:twitter_login/schemes/access_token.dart'; -import 'package:twitter_login/schemes/request_token.dart'; + import 'package:twitter_login/src/auth_browser.dart'; import 'package:twitter_login/src/exception.dart'; @@ -26,17 +23,9 @@ enum TwitterLoginStatus { class TwitterLogin { /// constructor TwitterLogin({ - required this.apiKey, - required this.apiSecretKey, required this.redirectURI, }); - /// Consumer API key - final String apiKey; - - /// Consumer API secret key - final String apiSecretKey; - /// Callback URL final String redirectURI; @@ -44,25 +33,9 @@ class TwitterLogin { static const _eventChannel = EventChannel('twitter_login/event'); static final Stream _eventStream = _eventChannel.receiveBroadcastStream(); - /// Logs the user - /// Forces the user to enter their credentials to ensure the correct users account is authorized. - Future login({bool forceLogin = false}) async { + ///使用更安全的登录交互方式 + Future loginV3({required String oauthToken, void Function()? onLoad}) async { String? resultURI; - RequestToken requestToken; - try { - requestToken = await RequestToken.getRequestToken( - apiKey, - apiSecretKey, - redirectURI, - forceLogin, - ); - } on Exception { - throw PlatformException( - code: '400', - message: 'Failed to generate request token.', - details: 'Please check your APIKey or APISecret.', - ); - } final uri = Uri.parse(redirectURI); final completer = Completer(); @@ -89,140 +62,15 @@ class TwitterLogin { }, ); - try { - if (Platform.isIOS || Platform.isMacOS) { - /// Login to Twitter account with SFAuthenticationSession or ASWebAuthenticationSession. - resultURI = await authBrowser.doAuth(requestToken.authorizeURI, uri.scheme); - } else if (Platform.isAndroid) { - // Login to Twitter account with chrome_custom_tabs. - final success = await authBrowser.open(requestToken.authorizeURI, uri.scheme); - if (!success) { - throw PlatformException( - code: '200', - message: 'Could not open browser, probably caused by unavailable custom tabs.', - ); - } - resultURI = await completer.future; - await subscribe.cancel(); - } else { - throw PlatformException( - code: '100', - message: 'Not supported by this os.', - ); - } - - // The user closed the browser. - if (resultURI?.isEmpty ?? true) { - throw const CanceledByUserException(); - } - - final queries = Uri.splitQueryString(Uri.parse(resultURI!).query); - if (queries['error'] != null) { - throw Exception('Error Response: ${queries['error']}'); - } - - // The user cancelled the login flow. - if (queries['denied'] != null) { - throw const CanceledByUserException(); - } - - final token = await AccessToken.getAccessToken( - apiKey, - apiSecretKey, - queries, - ); - - if ((token.authToken?.isEmpty ?? true) || (token.authTokenSecret?.isEmpty ?? true)) { - return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, - status: TwitterLoginStatus.error, - errorMessage: 'Failed', - ); - } - - User? user; - - try { - user = await User.getUserData( - apiKey, - apiSecretKey, - token.authToken!, - token.authTokenSecret!, - ); - } on Exception { - debugPrint('The rate limit may have been reached or the API may be restricted.'); - } - - return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, - status: TwitterLoginStatus.loggedIn, - user: user, - ); - } on CanceledByUserException { - return AuthResult( - status: TwitterLoginStatus.cancelledByUser, - errorMessage: 'The user cancelled the login flow.', - ); - } catch (error) { - return AuthResult( - status: TwitterLoginStatus.error, - errorMessage: error.toString(), - ); - } - } - - Future loginV2({bool forceLogin = false, void Function()? onLoad}) async { - String? resultURI; - RequestToken requestToken; - try { - requestToken = await RequestToken.getRequestToken( - apiKey, - apiSecretKey, - redirectURI, - forceLogin, - ); - } on Exception { - throw PlatformException( - code: '400', - message: 'Failed to generate request token.', - details: 'Please check your APIKey or APISecret.', - ); - } - - final uri = Uri.parse(redirectURI); - final completer = Completer(); - late StreamSubscription subscribe; - - if (Platform.isAndroid) { - await _channel.invokeMethod('setScheme', uri.scheme); - subscribe = _eventStream.listen((data) async { - if (data['type'] == 'url') { - if (!completer.isCompleted) { - completer.complete(data['url']?.toString()); - } else { - throw const CanceledByUserException(); - } - } - }); - } - - final authBrowser = AuthBrowser( - onClose: () { - if (!completer.isCompleted) { - completer.complete(null); - } - }, - ); + final authorizeURI = 'https://api.twitter.com/oauth/authorize?oauth_token==$oauthToken'; try { if (Platform.isIOS || Platform.isMacOS) { /// Login to Twitter account with SFAuthenticationSession or ASWebAuthenticationSession. - resultURI = await authBrowser.doAuth(requestToken.authorizeURI, uri.scheme); + resultURI = await authBrowser.doAuth(authorizeURI, uri.scheme); } else if (Platform.isAndroid) { // Login to Twitter account with chrome_custom_tabs. - final success = await authBrowser.open(requestToken.authorizeURI, uri.scheme); + final success = await authBrowser.open(authorizeURI, uri.scheme); if (!success) { throw PlatformException( code: '200', @@ -254,39 +102,11 @@ class TwitterLogin { } onLoad?.call(); - final token = await AccessToken.getAccessToken( - apiKey, - apiSecretKey, - queries, - ); - - if ((token.authToken?.isEmpty ?? true) || (token.authTokenSecret?.isEmpty ?? true)) { - return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, - status: TwitterLoginStatus.error, - errorMessage: 'Failed', - ); - } - - User? user; - try { - user = await User.getUserDataV2( - apiKey, - apiSecretKey, - token.authToken!, - token.authTokenSecret!, - token.userId!, - ); - } on Exception { - debugPrint('The rate limit may have been reached or the API may be restricted.'); - } return AuthResult( - authToken: token.authToken, - authTokenSecret: token.authTokenSecret, + authToken: queries['oauth_token'], + authVerifier: queries['oauth_verifier'], status: TwitterLoginStatus.loggedIn, - user: user, ); } on CanceledByUserException { return AuthResult( From 04df49e175339a6ddd7102df86dcd723572c17d3 Mon Sep 17 00:00:00 2001 From: HuangRed Date: Wed, 18 Sep 2024 09:30:38 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/src/twitter_login.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/twitter_login.dart b/lib/src/twitter_login.dart index 72ce73b..9c7987a 100644 --- a/lib/src/twitter_login.dart +++ b/lib/src/twitter_login.dart @@ -34,7 +34,7 @@ class TwitterLogin { static final Stream _eventStream = _eventChannel.receiveBroadcastStream(); ///使用更安全的登录交互方式 - Future loginV3({required String oauthToken, void Function()? onLoad}) async { + Future login({required String oauthToken}) async { String? resultURI; final uri = Uri.parse(redirectURI); @@ -101,8 +101,6 @@ class TwitterLogin { throw const CanceledByUserException(); } - onLoad?.call(); - return AuthResult( authToken: queries['oauth_token'], authVerifier: queries['oauth_verifier'],