diff --git a/twidere.component.common/build.gradle b/twidere.component.common/build.gradle index f2a91ef6b..1a84ebc4f 100644 --- a/twidere.component.common/build.gradle +++ b/twidere.component.common/build.gradle @@ -44,7 +44,7 @@ dependencies { compile 'com.android.support:support-v4:23.1.0' compile 'com.bluelinelabs:logansquare:1.1.0' compile 'org.apache.commons:commons-lang3:3.4' - compile 'com.github.mariotaku.RestFu:library:0.9.6' + compile 'com.github.mariotaku.RestFu:library:0.9.7' compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.1' compile 'com.github.mariotaku:SQLiteQB:88291f3a28' compile 'com.github.mariotaku.LoganSquareExtension:core:b6f53c9a4d' diff --git a/twidere/build.gradle b/twidere/build.gradle index 3842de474..3bd39d9ed 100644 --- a/twidere/build.gradle +++ b/twidere/build.gradle @@ -93,8 +93,8 @@ dependencies { compile 'com.soundcloud.android:android-crop:1.0.1@aar' compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.1' compile 'com.github.mariotaku:PickNCrop:1dff3ed574' - compile 'com.github.mariotaku.RestFu:library:0.9.6' - compile 'com.github.mariotaku.RestFu:okhttp:0.9.6' + compile 'com.github.mariotaku.RestFu:library:0.9.7' + compile 'com.github.mariotaku.RestFu:okhttp:0.9.7' compile 'com.diogobernardino:williamchart:2.0.1' compile 'com.lnikkila:extendedtouchview:0.1.0' compile 'com.google.dagger:dagger:2.0.1' diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java index fb34b2b48..66ab5541b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java @@ -56,6 +56,7 @@ import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; +import android.widget.TextView; import android.widget.Toast; import com.meizu.flyme.reflect.StatusBarProxy; @@ -84,6 +85,7 @@ import org.mariotaku.twidere.util.ContentValuesCreator; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticationException; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticityTokenException; +import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.LoginVerificationException; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.WrongUserPassException; import org.mariotaku.twidere.util.ParseUtils; import org.mariotaku.twidere.util.SharedPreferencesWrapper; @@ -459,6 +461,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList Toast.makeText(this, R.string.wrong_api_key, Toast.LENGTH_SHORT).show(); } else if (result.exception instanceof WrongUserPassException) { Toast.makeText(this, R.string.wrong_username_password, Toast.LENGTH_SHORT).show(); + } else if (result.exception instanceof LoginVerificationException) { + Toast.makeText(this, R.string.login_verification_failed, Toast.LENGTH_SHORT).show(); } else if (result.exception instanceof AuthenticationException) { showErrorMessage(this, getString(R.string.action_signing_in), result.exception.getCause(), true); } else { @@ -790,7 +794,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList String challengeResponse; @Override - public String getLoginVerification() { + public String getLoginVerification(final String challengeType) { // Dismiss current progress dialog publishProgress(new Runnable() { @Override @@ -807,6 +811,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList public void run() { InputLoginVerificationDialogFragment df = new InputLoginVerificationDialogFragment(); df.setCallback(InputLoginVerificationCallback.this); + df.setChallengeType(challengeType); df.show(activity.getSupportFragmentManager(), null); } }); @@ -840,9 +845,10 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList } - public static class InputLoginVerificationDialogFragment extends BaseSupportDialogFragment implements DialogInterface.OnClickListener { + public static class InputLoginVerificationDialogFragment extends BaseSupportDialogFragment implements DialogInterface.OnClickListener, DialogInterface.OnShowListener { private SignInTask.InputLoginVerificationCallback callback; + private String challengeType; public void setCallback(SignInTask.InputLoginVerificationCallback callback) { this.callback = callback; @@ -862,7 +868,9 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList builder.setView(R.layout.dialog_login_verification_code); builder.setPositiveButton(android.R.string.ok, this); builder.setNegativeButton(android.R.string.cancel, this); - return builder.create(); + final AlertDialog dialog = builder.create(); + dialog.setOnShowListener(this); + return dialog; } @Override @@ -880,6 +888,24 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList } } } + + public void setChallengeType(String challengeType) { + this.challengeType = challengeType; + } + + @Override + public void onShow(DialogInterface dialog) { + final AlertDialog alertDialog = (AlertDialog) dialog; + final TextView verificationHint = (TextView) alertDialog.findViewById(R.id.verification_hint); + final EditText editVerification = (EditText) alertDialog.findViewById(R.id.edit_verification_code); + if ("Push".equalsIgnoreCase(challengeType)) { + verificationHint.setText(R.string.login_verification_push_hint); + editVerification.setVisibility(View.GONE); + } else { + verificationHint.setText(R.string.login_verification_pin_hint); + editVerification.setVisibility(View.VISIBLE); + } + } } static class SignInResponse { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.java b/twidere/src/main/java/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.java index 2fb02ae14..a5a84f835 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/OAuthPasswordAuthenticator.java @@ -19,6 +19,7 @@ package org.mariotaku.twidere.util; +import android.support.annotation.Nullable; import android.text.TextUtils; import com.squareup.okhttp.HttpUrl; @@ -53,6 +54,7 @@ import org.mariotaku.twidere.model.RequestType; import java.io.IOException; import java.io.Reader; import java.net.CookieManager; +import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -84,8 +86,8 @@ public class OAuthPasswordAuthenticator implements Constants { } final String location = response.header("Location"); final Response.Builder builder = response.newBuilder(); - if (!TextUtils.isEmpty(location)) { - final HttpUrl originalLocation = HttpUrl.parse(location); + if (!TextUtils.isEmpty(location) && !endpoint.checkEndpoint(location)) { + final HttpUrl originalLocation = HttpUrl.get(URI.create("https://api.twitter.com/").resolve(location)); final HttpUrl.Builder locationBuilder = HttpUrl.parse(endpoint.getUrl()).newBuilder(); for (String pathSegments : originalLocation.pathSegments()) { locationBuilder.addPathSegment(pathSegments); @@ -130,12 +132,14 @@ public class OAuthPasswordAuthenticator implements Constants { throw new WrongUserPassException(); } // Go to password verification flow + final String challengeType = authorizeResponseData.verification.challengeType; + final String loginVerification = loginVerificationCallback.getLoginVerification(challengeType); final AuthorizeRequestData verificationData = getVerificationData(authorizeResponseData, - loginVerificationCallback.getLoginVerification()); + loginVerification); authorizeResponseData = getAuthorizeResponseData(requestToken, verificationData, username, password); if (TextUtils.isEmpty(authorizeResponseData.oauthPin)) { - throw new VerificationCodeException(); + throw new LoginVerificationException(); } return oauth.getAccessToken(requestToken, authorizeResponseData.oauthPin); } catch (final IOException | NullPointerException | TwitterException e) { @@ -144,7 +148,7 @@ public class OAuthPasswordAuthenticator implements Constants { } private AuthorizeRequestData getVerificationData(AuthorizeResponseData authorizeResponseData, - String challengeResponse) throws IOException, VerificationCodeException { + @Nullable String challengeResponse) throws IOException, LoginVerificationException { RestHttpResponse response = null; try { final AuthorizeRequestData data = new AuthorizeRequestData(); @@ -159,7 +163,9 @@ public class OAuthPasswordAuthenticator implements Constants { final ArrayList> requestHeaders = new ArrayList<>(); requestHeaders.add(Pair.create("User-Agent", userAgent)); - params.add(Pair.create("challenge_response", challengeResponse)); + if (!TextUtils.isEmpty(challengeResponse)) { + params.add(Pair.create("challenge_response", challengeResponse)); + } final FormTypedBody authorizationResultBody = new FormTypedBody(params); final RestHttpRequest.Builder authorizeResultBuilder = new RestHttpRequest.Builder(); @@ -170,9 +176,12 @@ public class OAuthPasswordAuthenticator implements Constants { authorizeResultBuilder.extra(RequestType.API); response = client.execute(authorizeResultBuilder.build()); parseAuthorizeRequestData(response, data); + if (TextUtils.isEmpty(data.authenticityToken)) { + throw new LoginVerificationException(); + } return data; } catch (AttoParseException e) { - throw new VerificationCodeException(); + throw new LoginVerificationException(); } finally { Utils.closeSilently(response); } @@ -440,7 +449,7 @@ public class OAuthPasswordAuthenticator implements Constants { } public interface LoginVerificationCallback { - String getLoginVerification(); + String getLoginVerification(String challengeType); } public static class AuthenticationException extends Exception { @@ -469,7 +478,7 @@ public class OAuthPasswordAuthenticator implements Constants { } - public static final class VerificationCodeException extends AuthenticationException { + public static final class LoginVerificationException extends AuthenticationException { } diff --git a/twidere/src/main/res/layout/dialog_login_verification_code.xml b/twidere/src/main/res/layout/dialog_login_verification_code.xml index 3a0c6bd83..ab321a505 100644 --- a/twidere/src/main/res/layout/dialog_login_verification_code.xml +++ b/twidere/src/main/res/layout/dialog_login_verification_code.xml @@ -25,9 +25,10 @@ + android:text="@string/login_verification_pin_hint" /> Copy link Link copied to clipboard Login verification - Please check your phone for a PIN code and enter it to log in. + Check your phone for a PIN code and enter it to log in. + Accept login verification request from Twitter app, once you approved the request, click OK. + Login verification failed. \ No newline at end of file