Skip to content

Commit 3703f85

Browse files
amandlesamtstern
authored andcommitted
Add Twitter as an IDP (firebase#268)
1 parent 9fb5779 commit 3703f85

File tree

20 files changed

+368
-5
lines changed

20 files changed

+368
-5
lines changed

app/src/main/java/com/firebase/uidemo/auth/AuthUiActivity.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import com.google.firebase.auth.FirebaseAuth;
3434

3535
import java.util.ArrayList;
36+
import java.util.Arrays;
37+
import java.util.List;
3638

3739
import butterknife.BindView;
3840
import butterknife.ButterKnife;
@@ -69,6 +71,9 @@ public class AuthUiActivity extends AppCompatActivity {
6971
@BindView(R.id.facebook_provider)
7072
CheckBox mUseFacebookProvider;
7173

74+
@BindView(R.id.twitter_provider)
75+
CheckBox mUseTwitterProvider;
76+
7277
@BindView(R.id.google_tos)
7378
RadioButton mUseGoogleTos;
7479

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

121-
if (!isGoogleConfigured() || !isFacebookConfigured()) {
126+
if (!isTwitterConfigured()) {
127+
mUseTwitterProvider.setChecked(false);
128+
mUseTwitterProvider.setEnabled(false);
129+
mUseTwitterProvider.setText(R.string.twitter_label_missing_config);
130+
}
131+
132+
if (!isGoogleConfigured() || !isFacebookConfigured() || !isTwitterConfigured()) {
122133
showSnackbar(R.string.configuration_required);
123134
}
135+
124136
}
125137

126138
@OnClick(R.id.sign_in)
@@ -204,6 +216,10 @@ private String[] getSelectedProviders() {
204216
selectedProviders.add(AuthUI.GOOGLE_PROVIDER);
205217
}
206218

219+
if (mUseTwitterProvider.isChecked()) {
220+
selectedProviders.add(AuthUI.TWITTER_PROVIDER);
221+
}
222+
207223
return selectedProviders.toArray(new String[selectedProviders.size()]);
208224
}
209225

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

247+
@MainThread
248+
private boolean isTwitterConfigured() {
249+
List<String> twitterConfigs = Arrays.asList(
250+
getResources().getString(R.string.twitter_consumer_key),
251+
getResources().getString(R.string.twitter_consumer_secret)
252+
);
253+
254+
return !twitterConfigs.contains(UNCHANGED_CONFIG_VALUE);
255+
}
256+
231257
@MainThread
232258
private void showSnackbar(@StringRes int errorMessageRes) {
233259
Snackbar.make(mRootView, errorMessageRes, Snackbar.LENGTH_LONG).show();

app/src/main/res/layout/auth_ui_layout.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@
9191
android:layout_height="wrap_content"
9292
android:text="@string/google_label" />
9393

94+
<CheckBox
95+
android:id="@+id/twitter_provider"
96+
android:layout_width="wrap_content"
97+
android:layout_height="wrap_content"
98+
android:text="@string/twitter_label" />
99+
94100
<TextView
95101
style="@style/Base.TextAppearance.AppCompat.Subhead"
96102
android:layout_width="wrap_content"

app/src/main/res/values/config.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,17 @@
1010
Facebook Application ID, prefixed by 'fb'. Enables Chrome Custom tabs.
1111
-->
1212
<string name="facebook_login_protocol_scheme" translatable="false">fbYOUR_APP_ID</string>
13+
14+
15+
16+
<!--
17+
Your Twitter Consumer Key. To use Twitter accounts with the demo application, register an
18+
application with Twitter and provide the following two values.
19+
-->
20+
<string name="twitter_consumer_key" translatable="false">CHANGE-ME</string>
21+
22+
<!--
23+
Your Twitter Consumer Secret
24+
-->
25+
<string name="twitter_consumer_secret" translatable="false">CHANGE-ME</string>
1326
</resources>

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
<string name="email_label">Email</string>
2323
<string name="facebook_label">Facebook</string>
2424
<string name="facebook_label_missing_config">Facebook - configuration missing</string>
25+
<string name="twitter_label">Twitter</string>
26+
<string name="twitter_label_missing_config">Twitter - configuration missing</string>
2527
<string name="google_label">Google</string>
2628
<string name="google_label_missing_config">Google - configuration missing</string>
2729
<string name="google_tos_label">Google TOS</string>

auth/README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ If instead your project uses Maven, add:
6060

6161
### Identity provider configuration
6262

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

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

80+
If support for Twitter Sign-in is also required, define the resource strings
81+
twitter_consumer_key and twitter_consumer_secret to match the values of your Twitter app as
82+
reported by the [Twitter application manager](https://dev.twitter.com/apps).
83+
84+
```
85+
<resources>
86+
<string name="twitter_consumer_key" translatable="false">YOURCONSUMERKEY</string>
87+
<string name="twitter_consumer_secret" translatable="false">YOURCONSUMERSECRET</string>
88+
</resources>
89+
90+
```
91+
8092
## Using FirebaseUI for Authentication
8193

8294
Before invoking the FirebaseUI authentication flow, your app should check

auth/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
apply plugin: 'com.android.library'
22
apply plugin: 'checkstyle'
3+
apply plugin: 'io.fabric'
34

45
android {
56
compileSdkVersion project.ext.compileSdk
@@ -34,6 +35,9 @@ dependencies {
3435
testCompile "org.robolectric:robolectric:3.1.1"
3536
compile "com.android.support:appcompat-v7:${project.ext.support_library_version}"
3637
compile 'com.facebook.android:facebook-android-sdk:4.14.1'
38+
compile("com.twitter.sdk.android:twitter:2.0.0@aar") {
39+
transitive = true;
40+
}
3741
compile "com.android.support:design:${project.ext.support_library_version}"
3842

3943
compile "com.google.firebase:firebase-auth:${project.ext.firebase_version}"

auth/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,5 @@
7676
<data android:scheme="@string/facebook_login_protocol_scheme" />
7777
</intent-filter>
7878
</activity>
79-
8079
</application>
8180
</manifest>

auth/src/main/java/com/firebase/ui/auth/AuthUI.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,11 @@ public class AuthUI {
230230
*/
231231
public static final String FACEBOOK_PROVIDER = "facebook";
232232

233+
/**
234+
* Provider identifier for Twitter, for use with {@link SignInIntentBuilder#setProviders}.
235+
*/
236+
public static final String TWITTER_PROVIDER = "twitter";
237+
233238
/**
234239
* Default value for logo resource, omits the logo from the
235240
* {@link AuthMethodPickerActivity}
@@ -243,7 +248,8 @@ public class AuthUI {
243248
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
244249
EMAIL_PROVIDER,
245250
GOOGLE_PROVIDER,
246-
FACEBOOK_PROVIDER
251+
FACEBOOK_PROVIDER,
252+
TWITTER_PROVIDER
247253
)));
248254

249255
private static final IdentityHashMap<FirebaseApp, AuthUI> INSTANCES = new IdentityHashMap<>();
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package com.firebase.ui.auth.provider;
2+
3+
import android.app.Activity;
4+
import android.content.Context;
5+
import android.content.Intent;
6+
import android.os.Bundle;
7+
8+
import com.firebase.ui.auth.R;
9+
import com.google.firebase.auth.AuthCredential;
10+
import com.google.firebase.auth.TwitterAuthProvider;
11+
import com.twitter.sdk.android.Twitter;
12+
import com.twitter.sdk.android.core.Callback;
13+
import com.twitter.sdk.android.core.Result;
14+
import com.twitter.sdk.android.core.TwitterAuthConfig;
15+
import com.twitter.sdk.android.core.TwitterException;
16+
import com.twitter.sdk.android.core.TwitterSession;
17+
import com.twitter.sdk.android.core.identity.TwitterAuthClient;
18+
19+
import io.fabric.sdk.android.Fabric;
20+
21+
public class TwitterProvider extends Callback<TwitterSession> implements IDPProvider {
22+
public static final String EXTRA_AUTH_TOKEN = "extra_auth_token";
23+
public static final String EXTRA_AUTH_SECRET = "extra_auth_secret";
24+
private static final String EXTRA_CONSUMER_KEY = "extra_consumer_key";
25+
private static final String EXTRA_CONSUMER_SECRET = "extra_consumer_secret";
26+
private IDPCallback mCallbackObject;
27+
private TwitterAuthClient mTwitterAuthClient;
28+
29+
public TwitterProvider(Context appContext, IDPProviderParcel twitterParcel) {
30+
TwitterAuthConfig authConfig = new TwitterAuthConfig(
31+
appContext.getString(R.string.twitter_consumer_key),
32+
appContext.getString(R.string.twitter_consumer_secret));
33+
Fabric.with(appContext, new Twitter(authConfig));
34+
mTwitterAuthClient = new TwitterAuthClient();
35+
}
36+
37+
public static IDPProviderParcel createTwitterParcel(String consumerKey, String consumerSecret) {
38+
Bundle extra = new Bundle();
39+
extra.putString(EXTRA_CONSUMER_KEY, consumerKey);
40+
extra.putString(EXTRA_CONSUMER_SECRET, consumerSecret);
41+
return new IDPProviderParcel(TwitterAuthProvider.PROVIDER_ID, extra);
42+
}
43+
44+
@Override
45+
public String getName(Context context) {
46+
return context.getString(R.string.idp_name_twitter);
47+
}
48+
49+
@Override
50+
public String getProviderId() {
51+
return TwitterAuthProvider.PROVIDER_ID;
52+
}
53+
54+
@Override
55+
public void setAuthenticationCallback(IDPCallback callback) {
56+
this.mCallbackObject = callback;
57+
}
58+
59+
@Override
60+
public void onActivityResult(int requestCode, int resultCode, Intent data) {
61+
mTwitterAuthClient.onActivityResult(requestCode, resultCode, data);
62+
}
63+
64+
@Override
65+
public void startLogin(Activity activity) {
66+
mTwitterAuthClient.authorize(activity, this);
67+
}
68+
69+
@Override
70+
public void success(Result<TwitterSession> result) {
71+
mCallbackObject.onSuccess(createIDPResponse(result.data));
72+
}
73+
74+
@Override
75+
public void failure(TwitterException exception) {
76+
mCallbackObject.onFailure(new Bundle());
77+
}
78+
79+
public static AuthCredential createAuthCredential(IDPResponse response) {
80+
if (!response.getProviderType().equalsIgnoreCase(TwitterAuthProvider.PROVIDER_ID)){
81+
return null;
82+
}
83+
return TwitterAuthProvider.getCredential(
84+
response.getResponse().getString(EXTRA_AUTH_TOKEN),
85+
response.getResponse().getString(EXTRA_AUTH_SECRET));
86+
}
87+
88+
89+
private IDPResponse createIDPResponse(TwitterSession twitterSession) {
90+
Bundle response = new Bundle();
91+
response.putString(EXTRA_AUTH_TOKEN, twitterSession.getAuthToken().token);
92+
response.putString(EXTRA_AUTH_SECRET, twitterSession.getAuthToken().secret);
93+
return new IDPResponse(TwitterAuthProvider.PROVIDER_ID, twitterSession.getUserName(), response);
94+
}
95+
96+
}

auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.firebase.ui.auth.provider.IDPProvider;
3131
import com.firebase.ui.auth.provider.IDPProviderParcel;
3232
import com.firebase.ui.auth.provider.IDPResponse;
33+
import com.firebase.ui.auth.provider.TwitterProvider;
3334
import com.firebase.ui.auth.ui.ActivityHelper;
3435
import com.firebase.ui.auth.ui.FlowParameters;
3536
import com.firebase.ui.auth.ui.TaskFailureLogger;
@@ -40,6 +41,7 @@
4041
import com.google.firebase.auth.FacebookAuthProvider;
4142
import com.google.firebase.auth.FirebaseAuth;
4243
import com.google.firebase.auth.GoogleAuthProvider;
44+
import com.google.firebase.auth.TwitterAuthProvider;
4345

4446
import java.util.ArrayList;
4547
import java.util.List;
@@ -95,6 +97,9 @@ private void populateIdpList(List<IDPProviderParcel> providers) {
9597
case EmailAuthProvider.PROVIDER_ID:
9698
findViewById(R.id.email_provider).setVisibility(View.VISIBLE);
9799
break;
100+
case TwitterAuthProvider.PROVIDER_ID:
101+
mIdpProviders.add(new TwitterProvider(this, providerParcel));
102+
break;
98103
default:
99104
if (BuildConfig.DEBUG) {
100105
Log.d(TAG, "Encountered unknown IDPProvider parcel with type: "
@@ -115,6 +120,10 @@ private void populateIdpList(List<IDPProviderParcel> providers) {
115120
loginButton = getLayoutInflater()
116121
.inflate(R.layout.idp_button_facebook, btnHolder, false);
117122
break;
123+
case TwitterAuthProvider.PROVIDER_ID:
124+
loginButton = getLayoutInflater()
125+
.inflate(R.layout.idp_button_twitter, btnHolder, false);
126+
break;
118127
default:
119128
Log.e(TAG, "No button for provider " + provider.getProviderId());
120129
}

auth/src/main/java/com/firebase/ui/auth/ui/idp/IDPBaseActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
import com.firebase.ui.auth.provider.FacebookProvider;
1818
import com.firebase.ui.auth.provider.GoogleProvider;
1919
import com.firebase.ui.auth.provider.IDPResponse;
20+
import com.firebase.ui.auth.provider.TwitterProvider;
2021
import com.firebase.ui.auth.ui.AppCompatBase;
2122
import com.google.firebase.auth.AuthCredential;
2223
import com.google.firebase.auth.FacebookAuthProvider;
2324
import com.google.firebase.auth.GoogleAuthProvider;
25+
import com.google.firebase.auth.TwitterAuthProvider;
2426

2527
public class IDPBaseActivity extends AppCompatBase {
2628
protected AuthCredential createCredential(IDPResponse idpSignInResponse) {
@@ -29,6 +31,10 @@ protected AuthCredential createCredential(IDPResponse idpSignInResponse) {
2931
} else if (idpSignInResponse.getProviderType().equalsIgnoreCase(GoogleAuthProvider
3032
.PROVIDER_ID)) {
3133
return GoogleProvider.createAuthCredential(idpSignInResponse);
34+
} else if (idpSignInResponse
35+
.getProviderType()
36+
.equalsIgnoreCase(TwitterAuthProvider.PROVIDER_ID)) {
37+
return TwitterProvider.createAuthCredential(idpSignInResponse);
3238
}
3339
return null;
3440
}

auth/src/main/java/com/firebase/ui/auth/util/ProviderHelper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.firebase.ui.auth.provider.FacebookProvider;
2323
import com.firebase.ui.auth.provider.GoogleProvider;
2424
import com.firebase.ui.auth.provider.IDPProviderParcel;
25+
import com.firebase.ui.auth.provider.TwitterProvider;
2526
import com.google.firebase.auth.EmailAuthProvider;
2627

2728
import java.util.ArrayList;
@@ -39,6 +40,10 @@ public static List<IDPProviderParcel> getProviderParcels(
3940
} else if (provider.equalsIgnoreCase(AuthUI.GOOGLE_PROVIDER)) {
4041
providerInfo.add(GoogleProvider.createParcel(
4142
context.getString(R.string.default_web_client_id)));
43+
} else if (provider.equalsIgnoreCase(AuthUI.TWITTER_PROVIDER)) {
44+
providerInfo.add(TwitterProvider.createTwitterParcel(
45+
context.getString(R.string.twitter_consumer_key),
46+
context.getString(R.string.twitter_consumer_secret)));
4247
} else if (provider.equalsIgnoreCase(AuthUI.EMAIL_PROVIDER)) {
4348
providerInfo.add(
4449
new IDPProviderParcel(EmailAuthProvider.PROVIDER_ID, new Bundle())
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
3+
<item >
4+
<shape android:shape="rectangle" >
5+
<corners android:radius="3dp" />
6+
<solid android:color="@color/tw__blue_default"/>
7+
</shape>
8+
</item>
9+
</selector>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<Button
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
style="@style/FirebaseUI.Button.AccountChooser.TwitterButton"
4+
android:text="@string/sign_in_with_twitter"
5+
android:id="@+id/twitter_button"
6+
/>

auth/src/main/res/values/config.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,16 @@
5656
https://developers.google.com/android/guides/google-services-plugin
5757
-->
5858
<string name="default_web_client_id" translatable="false">CHANGE-ME</string>
59+
60+
61+
<!--
62+
Your Twitter Consumer Key. To use Twitter accounts with the demo application, register an
63+
application with Twitter and provide the following two values.
64+
-->
65+
<string name="twitter_consumer_key" translatable="false">CHANGE-ME</string>
66+
67+
<!--
68+
Your Twitter Consumer Secret
69+
-->
70+
<string name="twitter_consumer_secret" translatable="false">CHANGE-ME</string>
5971
</resources>

0 commit comments

Comments
 (0)