Skip to content

Add Twitter as an IDP #268

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion app/src/main/java/com/firebase/uidemo/auth/AuthUiActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import com.google.firebase.auth.FirebaseAuth;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
Expand Down Expand Up @@ -69,6 +71,9 @@ public class AuthUiActivity extends AppCompatActivity {
@BindView(R.id.facebook_provider)
CheckBox mUseFacebookProvider;

@BindView(R.id.twitter_provider)
CheckBox mUseTwitterProvider;

@BindView(R.id.google_tos)
RadioButton mUseGoogleTos;

Expand Down Expand Up @@ -118,9 +123,16 @@ public void onCreate(Bundle savedInstanceState) {
mUseFacebookProvider.setText(R.string.facebook_label_missing_config);
}

if (!isGoogleConfigured() || !isFacebookConfigured()) {
if (!isTwitterConfigured()) {
mUseTwitterProvider.setChecked(false);
mUseTwitterProvider.setEnabled(false);
mUseTwitterProvider.setText(R.string.twitter_label_missing_config);
}

if (!isGoogleConfigured() || !isFacebookConfigured() || !isTwitterConfigured()) {
showSnackbar(R.string.configuration_required);
}

}

@OnClick(R.id.sign_in)
Expand Down Expand Up @@ -204,6 +216,10 @@ private String[] getSelectedProviders() {
selectedProviders.add(AuthUI.GOOGLE_PROVIDER);
}

if (mUseTwitterProvider.isChecked()) {
selectedProviders.add(AuthUI.TWITTER_PROVIDER);
}

return selectedProviders.toArray(new String[selectedProviders.size()]);
}

Expand All @@ -228,6 +244,16 @@ private boolean isFacebookConfigured() {
getResources().getString(R.string.facebook_application_id));
}

@MainThread
private boolean isTwitterConfigured() {
List<String> twitterConfigs = Arrays.asList(
getResources().getString(R.string.twitter_consumer_key),
getResources().getString(R.string.twitter_consumer_secret)
);

return !twitterConfigs.contains(UNCHANGED_CONFIG_VALUE);
}

@MainThread
private void showSnackbar(@StringRes int errorMessageRes) {
Snackbar.make(mRootView, errorMessageRes, Snackbar.LENGTH_LONG).show();
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/res/layout/auth_ui_layout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@
android:layout_height="wrap_content"
android:text="@string/google_label" />

<CheckBox
android:id="@+id/twitter_provider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/twitter_label" />

<TextView
style="@style/Base.TextAppearance.AppCompat.Subhead"
android:layout_width="wrap_content"
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/values/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,17 @@
Facebook Application ID, prefixed by 'fb'. Enables Chrome Custom tabs.
-->
<string name="facebook_login_protocol_scheme" translatable="false">fbYOUR_APP_ID</string>



<!--
Your Twitter Consumer Key. To use Twitter accounts with the demo application, register an
application with Twitter and provide the following two values.
-->
<string name="twitter_consumer_key" translatable="false">CHANGE-ME</string>

<!--
Your Twitter Consumer Secret
-->
<string name="twitter_consumer_secret" translatable="false">CHANGE-ME</string>
</resources>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
<string name="email_label">Email</string>
<string name="facebook_label">Facebook</string>
<string name="facebook_label_missing_config">Facebook - configuration missing</string>
<string name="twitter_label">Twitter</string>
<string name="twitter_label_missing_config">Twitter - configuration missing</string>
<string name="google_label">Google</string>
<string name="google_label_missing_config">Google - configuration missing</string>
<string name="google_tos_label">Google TOS</string>
Expand Down
14 changes: 13 additions & 1 deletion auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ If instead your project uses Maven, add:

### Identity provider configuration

In order to use either Google or Facebook accounts with your app, ensure that
In order to use either Google, Facebook or Twitter accounts with your app, ensure that
these authentication methods are first configured in the Firebase console.

FirebaseUI client-side configuration for Google sign-in is then provided
Expand All @@ -77,6 +77,18 @@ the [Facebook developer dashboard](https://developers.facebook.com):
</resources>
```

If support for Twitter Sign-in is also required, define the resource strings
twitter_consumer_key and twitter_consumer_secret to match the values of your Twitter app as
reported by the [Twitter application manager](https://dev.twitter.com/apps).

```
<resources>
<string name="twitter_consumer_key" translatable="false">YOURCONSUMERKEY</string>
<string name="twitter_consumer_secret" translatable="false">YOURCONSUMERSECRET</string>
</resources>

```

## Using FirebaseUI for Authentication

Before invoking the FirebaseUI authentication flow, your app should check
Expand Down
4 changes: 4 additions & 0 deletions auth/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
apply plugin: 'com.android.library'
apply plugin: 'checkstyle'
apply plugin: 'io.fabric'

android {
compileSdkVersion project.ext.compileSdk
Expand Down Expand Up @@ -34,6 +35,9 @@ dependencies {
testCompile "org.robolectric:robolectric:3.1.1"
compile "com.android.support:appcompat-v7:${project.ext.support_library_version}"
compile 'com.facebook.android:facebook-android-sdk:4.14.1'
compile("com.twitter.sdk.android:twitter:2.0.0@aar") {
transitive = true;
}
compile "com.android.support:design:${project.ext.support_library_version}"

compile "com.google.firebase:firebase-auth:${project.ext.firebase_version}"
Expand Down
1 change: 0 additions & 1 deletion auth/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,5 @@
<data android:scheme="@string/facebook_login_protocol_scheme" />
</intent-filter>
</activity>

</application>
</manifest>
8 changes: 7 additions & 1 deletion auth/src/main/java/com/firebase/ui/auth/AuthUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ public class AuthUI {
*/
public static final String FACEBOOK_PROVIDER = "facebook";

/**
* Provider identifier for Twitter, for use with {@link SignInIntentBuilder#setProviders}.
*/
public static final String TWITTER_PROVIDER = "twitter";

/**
* Default value for logo resource, omits the logo from the
* {@link AuthMethodPickerActivity}
Expand All @@ -243,7 +248,8 @@ public class AuthUI {
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
EMAIL_PROVIDER,
GOOGLE_PROVIDER,
FACEBOOK_PROVIDER
FACEBOOK_PROVIDER,
TWITTER_PROVIDER
)));

private static final IdentityHashMap<FirebaseApp, AuthUI> INSTANCES = new IdentityHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.firebase.ui.auth.provider;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.firebase.ui.auth.R;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.TwitterAuthProvider;
import com.twitter.sdk.android.Twitter;
import com.twitter.sdk.android.core.Callback;
import com.twitter.sdk.android.core.Result;
import com.twitter.sdk.android.core.TwitterAuthConfig;
import com.twitter.sdk.android.core.TwitterException;
import com.twitter.sdk.android.core.TwitterSession;
import com.twitter.sdk.android.core.identity.TwitterAuthClient;

import io.fabric.sdk.android.Fabric;

public class TwitterProvider extends Callback<TwitterSession> implements IDPProvider {
public static final String EXTRA_AUTH_TOKEN = "extra_auth_token";
public static final String EXTRA_AUTH_SECRET = "extra_auth_secret";
private static final String EXTRA_CONSUMER_KEY = "extra_consumer_key";
private static final String EXTRA_CONSUMER_SECRET = "extra_consumer_secret";
private IDPCallback mCallbackObject;
private TwitterAuthClient mTwitterAuthClient;

public TwitterProvider(Context appContext, IDPProviderParcel twitterParcel) {
TwitterAuthConfig authConfig = new TwitterAuthConfig(
appContext.getString(R.string.twitter_consumer_key),
appContext.getString(R.string.twitter_consumer_secret));
Fabric.with(appContext, new Twitter(authConfig));
mTwitterAuthClient = new TwitterAuthClient();
}

public static IDPProviderParcel createTwitterParcel(String consumerKey, String consumerSecret) {
Bundle extra = new Bundle();
extra.putString(EXTRA_CONSUMER_KEY, consumerKey);
extra.putString(EXTRA_CONSUMER_SECRET, consumerSecret);
return new IDPProviderParcel(TwitterAuthProvider.PROVIDER_ID, extra);
}

@Override
public String getName(Context context) {
return context.getString(R.string.idp_name_twitter);
}

@Override
public String getProviderId() {
return TwitterAuthProvider.PROVIDER_ID;
}

@Override
public void setAuthenticationCallback(IDPCallback callback) {
this.mCallbackObject = callback;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mTwitterAuthClient.onActivityResult(requestCode, resultCode, data);
}

@Override
public void startLogin(Activity activity) {
mTwitterAuthClient.authorize(activity, this);
}

@Override
public void success(Result<TwitterSession> result) {
mCallbackObject.onSuccess(createIDPResponse(result.data));
}

@Override
public void failure(TwitterException exception) {
mCallbackObject.onFailure(new Bundle());
}

public static AuthCredential createAuthCredential(IDPResponse response) {
if (!response.getProviderType().equalsIgnoreCase(TwitterAuthProvider.PROVIDER_ID)){
return null;
}
return TwitterAuthProvider.getCredential(
response.getResponse().getString(EXTRA_AUTH_TOKEN),
response.getResponse().getString(EXTRA_AUTH_SECRET));
}


private IDPResponse createIDPResponse(TwitterSession twitterSession) {
Bundle response = new Bundle();
response.putString(EXTRA_AUTH_TOKEN, twitterSession.getAuthToken().token);
response.putString(EXTRA_AUTH_SECRET, twitterSession.getAuthToken().secret);
return new IDPResponse(TwitterAuthProvider.PROVIDER_ID, twitterSession.getUserName(), response);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.firebase.ui.auth.provider.IDPProvider;
import com.firebase.ui.auth.provider.IDPProviderParcel;
import com.firebase.ui.auth.provider.IDPResponse;
import com.firebase.ui.auth.provider.TwitterProvider;
import com.firebase.ui.auth.ui.ActivityHelper;
import com.firebase.ui.auth.ui.FlowParameters;
import com.firebase.ui.auth.ui.TaskFailureLogger;
Expand All @@ -41,6 +42,7 @@
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.auth.TwitterAuthProvider;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -97,6 +99,9 @@ private void populateIdpList(List<IDPProviderParcel> providers) {
case EmailAuthProvider.PROVIDER_ID:
findViewById(R.id.email_provider).setVisibility(View.VISIBLE);
break;
case TwitterAuthProvider.PROVIDER_ID:
mIdpProviders.add(new TwitterProvider(this, providerParcel));
break;
default:
if (BuildConfig.DEBUG) {
Log.d(TAG, "Encountered unknown IDPProvider parcel with type: "
Expand All @@ -116,6 +121,10 @@ private void populateIdpList(List<IDPProviderParcel> providers) {
loginButton = getLayoutInflater()
.inflate(R.layout.idp_button_facebook, btnHolder, false);
break;
case TwitterAuthProvider.PROVIDER_ID:
loginButton = getLayoutInflater()
.inflate(R.layout.idp_button_twitter, btnHolder, false);
break;
default:
Log.e(TAG, "No button for provider " + provider.getProviderId());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
import com.firebase.ui.auth.provider.FacebookProvider;
import com.firebase.ui.auth.provider.GoogleProvider;
import com.firebase.ui.auth.provider.IDPResponse;
import com.firebase.ui.auth.provider.TwitterProvider;
import com.firebase.ui.auth.ui.AppCompatBase;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.auth.TwitterAuthProvider;

public class IDPBaseActivity extends AppCompatBase {
protected AuthCredential createCredential(IDPResponse idpSignInResponse) {
Expand All @@ -29,6 +31,10 @@ protected AuthCredential createCredential(IDPResponse idpSignInResponse) {
} else if (idpSignInResponse.getProviderType().equalsIgnoreCase(GoogleAuthProvider
.PROVIDER_ID)) {
return GoogleProvider.createAuthCredential(idpSignInResponse);
} else if (idpSignInResponse
.getProviderType()
.equalsIgnoreCase(TwitterAuthProvider.PROVIDER_ID)) {
return TwitterProvider.createAuthCredential(idpSignInResponse);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.firebase.ui.auth.provider.FacebookProvider;
import com.firebase.ui.auth.provider.GoogleProvider;
import com.firebase.ui.auth.provider.IDPProviderParcel;
import com.firebase.ui.auth.provider.TwitterProvider;
import com.google.firebase.auth.EmailAuthProvider;

import java.util.ArrayList;
Expand All @@ -39,6 +40,10 @@ public static List<IDPProviderParcel> getProviderParcels(
} else if (provider.equalsIgnoreCase(AuthUI.GOOGLE_PROVIDER)) {
providerInfo.add(GoogleProvider.createParcel(
context.getString(R.string.default_web_client_id)));
} else if (provider.equalsIgnoreCase(AuthUI.TWITTER_PROVIDER)) {
providerInfo.add(TwitterProvider.createTwitterParcel(
context.getString(R.string.twitter_consumer_key),
context.getString(R.string.twitter_consumer_secret)));
} else if (provider.equalsIgnoreCase(AuthUI.EMAIL_PROVIDER)) {
providerInfo.add(
new IDPProviderParcel(EmailAuthProvider.PROVIDER_ID, new Bundle())
Expand Down
9 changes: 9 additions & 0 deletions auth/src/main/res/drawable/idp_button_background_twitter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item >
<shape android:shape="rectangle" >
<corners android:radius="3dp" />
<solid android:color="@color/tw__blue_default"/>
</shape>
</item>
</selector>
6 changes: 6 additions & 0 deletions auth/src/main/res/layout/idp_button_twitter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/FirebaseUI.Button.AccountChooser.TwitterButton"
android:text="@string/sign_in_with_twitter"
android:id="@+id/twitter_button"
/>
12 changes: 12 additions & 0 deletions auth/src/main/res/values/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,16 @@
https://developers.google.com/android/guides/google-services-plugin
-->
<string name="default_web_client_id" translatable="false">CHANGE-ME</string>


<!--
Your Twitter Consumer Key. To use Twitter accounts with the demo application, register an
application with Twitter and provide the following two values.
-->
<string name="twitter_consumer_key" translatable="false">CHANGE-ME</string>

<!--
Your Twitter Consumer Secret
-->
<string name="twitter_consumer_secret" translatable="false">CHANGE-ME</string>
</resources>
Loading