|
1 |
| -# firebase-ui-auth |
| 1 | +# FirebaseUI for Android — Auth |
2 | 2 |
|
3 |
| -// TODO(iainmcgin): AuthUI README |
| 3 | +FirebaseUI is an open-source library that offers simple, |
| 4 | +customizable UI bindings on top of the core |
| 5 | +[Firebase](https://firebase.google.com) SDKs. It aims to eliminate boilerplate |
| 6 | +code and promote best practices (both user experience and security) for |
| 7 | +authentication. |
| 8 | + |
| 9 | +A simple API is provided for drop-in user authentication which handles |
| 10 | +the flow of signing in users with Email/Password, |
| 11 | +Google Sign-In, and Facebook Login. It is built on top of the |
| 12 | +[Firebase Auth](https://firebase.google.com/docs/auth). |
| 13 | + |
| 14 | +The best practices embodied in FirebaseUI aim to maximize sign-in |
| 15 | +and sign-up conversion for your app. It integrates with |
| 16 | +[Smart Lock for Passwords](https://developers.google.com/identity/smartlock-passwords/android/) |
| 17 | +to store and retrieve credentials, enabling automatic and single-tap sign-in to |
| 18 | +your app for returning users. It also handles tricky use cases like |
| 19 | +account recovery and account linking that are security sensitive and |
| 20 | +difficult to implement correctly using the base APIs provided by Firebase Auth. |
| 21 | + |
| 22 | +FirebaseUI auth can be easily customized to fit with the rest of your app's |
| 23 | +visual style. As it is open source, you are also free to modify it to exactly |
| 24 | +fit your preferred user experience. |
| 25 | + |
| 26 | +Equivalent FirebaseUI auth libraries are also available for |
| 27 | +[iOS](https://github.com/firebase/firebaseui-ios/) |
| 28 | +and [Web](https://github.com/firebase/firebaseui-web/). |
| 29 | + |
| 30 | +## Table of Content |
| 31 | + |
| 32 | +1. [Configuration](#configuration) |
| 33 | +2. [Usage instructions](#using-firebaseui-for-authentication) |
| 34 | +3. [Customization](#ui-customization) |
| 35 | + |
| 36 | +## Configuration |
| 37 | + |
| 38 | +As a pre-requisite, ensure your application is configured for use with |
| 39 | +Firebase: see the |
| 40 | +[Firebase documentation](https://firebase.google.com/docs/android/setup). |
| 41 | +Then, add the FirebaseUI auth library dependency. If your project uses |
| 42 | +Gradle, add: |
| 43 | + |
| 44 | +``` |
| 45 | +dependencies { |
| 46 | + // ... |
| 47 | + compile 'com.firebaseui:firebase-ui-auth:0.4.0' |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +If instead your project uses Maven, add: |
| 52 | + |
| 53 | +``` |
| 54 | +<dependency> |
| 55 | + <groupId>com.firebaseui</groupId> |
| 56 | + <artifactId>firebase-ui-auth</artifactId> |
| 57 | + <version>0.4.0</version> |
| 58 | +</dependency> |
| 59 | +``` |
| 60 | + |
| 61 | +### Identity provider configuration |
| 62 | + |
| 63 | +In order to use either Google or Facebook accounts with your app, ensure that |
| 64 | +these authentication methods are first configured in the Firebase console. |
| 65 | + |
| 66 | +FirebaseUI client-side configuration for Google sign-in is then provided |
| 67 | +automatically by the |
| 68 | +[google-services gradle plugin](https://developers.google.com/android/guides/google-services-plugin). |
| 69 | +If support for Facebook Sign-in is also required, define the |
| 70 | +resource string `facebook_application_id` to match the application ID in |
| 71 | +the [Facebook developer dashboard](https://developers.facebook.com): |
| 72 | + |
| 73 | +``` |
| 74 | +<resources> |
| 75 | + <!-- ... --> |
| 76 | + <string name="facebook_application_id" translatable="false">APPID</string> |
| 77 | +</resources> |
| 78 | +``` |
| 79 | + |
| 80 | +## Using FirebaseUI for Authentication |
| 81 | + |
| 82 | +Before invoking the FirebaseUI authentication flow, your app should check |
| 83 | +whether a |
| 84 | +[user is already signed in](https://firebase.google.com/docs/auth/android/manage-users#get_the_currently_signed-in_user) from a previous session: |
| 85 | + |
| 86 | +``` |
| 87 | +FirebaseAuth auth = FirebaseAuth.getInstance(); |
| 88 | +if (auth.getCurrentUser() != null) { |
| 89 | + // already signed in |
| 90 | +} else { |
| 91 | + // not signed in |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +The entry point to the authentication flow is the |
| 96 | +`com.firebase.ui.auth.AuthUI` class. |
| 97 | +If your application uses the default `FirebaseApp` instance, an AuthUI |
| 98 | +instance can be retrieved simply by calling `AuthUI.getInstance()`. |
| 99 | +If an alternative app instance is required, call |
| 100 | +`AuthUI.getInstance(app)` instead, passing the appropriate FirebaseApp instance. |
| 101 | + |
| 102 | +### Sign in |
| 103 | + |
| 104 | +If a user is not currently signed in, as can be determined by checking |
| 105 | +`auth.getCurrentUser() != null`, where auth is the FirebaseAuth instance |
| 106 | +associated with your FirebaseApp, then the sign-in process can be started by |
| 107 | +creating a sign-in intent using `AuthUI.SignInIntentBuilder`. A builder instance |
| 108 | +can be retrieved by calling `createSignInIntentBuilder()` on the retrieved |
| 109 | +AuthUI instance. |
| 110 | + |
| 111 | +The builder provides the following customization options for the authentication flow: |
| 112 | + |
| 113 | +- The set of authentication providers can be specified. |
| 114 | +- The terms of service URL for your app can be specified, which is included as |
| 115 | + a link in the small-print of the account creation step for new users. If no |
| 116 | + terms of service URL is provided, the associated small-print is omitted. |
| 117 | + |
| 118 | +- A custom theme can specified for the flow, which is applied to all the |
| 119 | + activities in the flow for consistent customization of colors and typography. |
| 120 | + |
| 121 | +#### Sign-in examples |
| 122 | + |
| 123 | +If no customization is required, and only email authentication is required, the sign-in flow |
| 124 | +can be started as follows: |
| 125 | + |
| 126 | +``` |
| 127 | +startActivityForResult( |
| 128 | + AuthUI.getInstance(this).createSignInIntentBuilder().build(), |
| 129 | + RC_SIGN_IN); |
| 130 | +``` |
| 131 | + |
| 132 | +If Google Sign-in and Facebook Sign-in are also required, then this can be |
| 133 | +replaced with: |
| 134 | + |
| 135 | +``` |
| 136 | +startActivityForResult( |
| 137 | + AuthUI.getInstance(this) |
| 138 | + .createSignInIntentBuilder() |
| 139 | + .setProviders( |
| 140 | + AuthUI.EMAIL_PROVIDER, |
| 141 | + AuthUI.GOOGLE_PROVIDER, |
| 142 | + AuthUI.FACEBOOK_PROVIDER) |
| 143 | + .build(), |
| 144 | + RC_SIGN_IN); |
| 145 | +``` |
| 146 | + |
| 147 | +Finally, if a terms of service URL and a custom theme are required: |
| 148 | + |
| 149 | +``` |
| 150 | +startActivityForResult( |
| 151 | + AuthUI.getInstance(this) |
| 152 | + .createSignInIntentBuilder() |
| 153 | + .setProviders(...) |
| 154 | + .setTosUrl("https://superapp.example.com/terms-of-service.html") |
| 155 | + .setTheme(R.style.SuperAppTheme) |
| 156 | + .build(), |
| 157 | + RC_SIGN_IN); |
| 158 | +``` |
| 159 | + |
| 160 | +#### Handling the sign-in response |
| 161 | + |
| 162 | +The authentication flow provides only two response codes: |
| 163 | +`Activity.RESULT_OK` if a user is signed in, and `Activity.RESULT_CANCELLED` if |
| 164 | +sign in failed. No further information on failure is provided as it is not |
| 165 | +typically useful; the only recourse for most apps if sign in fails is to ask |
| 166 | +the user to sign in again later, or proceed with an anonymous account if |
| 167 | +supported. |
| 168 | + |
| 169 | +``` |
| 170 | +protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
| 171 | + super.onActivityResult(requestCode, resultCode, data); |
| 172 | + if (requestCode == RC_SIGN_IN) { |
| 173 | + if (resultCode == RESULT_OK) { |
| 174 | + // user is signed in! |
| 175 | + startActivity(new Intent(this, WelcomeBackActivity.class)); |
| 176 | + finish(); |
| 177 | + } else { |
| 178 | + // user is not signed in. Maybe just wait for the user to press |
| 179 | + // "sign in" again, or show a message |
| 180 | + } |
| 181 | + } |
| 182 | + } |
| 183 | +``` |
| 184 | + |
| 185 | +Alternatively, you can register a listener for authentication state changes; |
| 186 | +see the |
| 187 | +[Firebase Auth documentation](https://firebase.google.com/docs/auth/android/manage-users#get_the_currently_signed-in_user) |
| 188 | +for more information. |
| 189 | + |
| 190 | +### Sign out |
| 191 | + |
| 192 | +With the integrations provided by AuthUI, signing out a user is a multi-stage process: |
| 193 | + |
| 194 | +1. The user must be signed out of the FirebaseAuth instance. |
| 195 | +2. Smart Lock for Passwords must be instructed to disable automatic sign-in, in |
| 196 | + order to prevent an automatic sign-in loop that prevents the user from |
| 197 | + switching accounts. |
| 198 | +3. If the current user signed in using either Google or Facebook, the user must |
| 199 | + also be signed out using the associated API for that authentication method. |
| 200 | + This typically ensures that the user will not be automatically signed-in |
| 201 | + using the current account when using that authentication method again from |
| 202 | + the authentication method picker, which would also prevent the user from |
| 203 | + switching between accounts on the same provider. |
| 204 | + |
| 205 | +In order to make this process easier, AuthUI provides a simple `signOut` method |
| 206 | +to encapsulate this behavior. The method returns a `Task` which is marked |
| 207 | +completed once all necessary sign-out operations are completed: |
| 208 | + |
| 209 | +``` |
| 210 | +public void onClick(View v) { |
| 211 | + if (v.getId() == R.id.sign_out) { |
| 212 | + AuthUI.getInstance(this) |
| 213 | + .signOut(this) |
| 214 | + .addOnCompleteListener(new OnCompleteListener<AuthResult>() { |
| 215 | + public void onComplete(@NonNull Task<AuthResult> task) { |
| 216 | + // user is now signed out |
| 217 | + startActivity(new Intent(MyActivity.this, SignInActivity.class)); |
| 218 | + finish(); |
| 219 | + }); |
| 220 | + }); |
| 221 | + } |
| 222 | +} |
| 223 | +``` |
| 224 | + |
| 225 | +### UI customization |
| 226 | + |
| 227 | +To provide customization of the visual style of the activities that implement |
| 228 | +the flow, a new theme can be declared. Standard material design color |
| 229 | +and typography properties will take effect as expected. For example, to define |
| 230 | +a green theme: |
| 231 | + |
| 232 | +``` |
| 233 | +<style name="GreenTheme" parent="FirebaseUI"> |
| 234 | + <item name="colorPrimary">@color/material_green_500</item> |
| 235 | + <item name="colorPrimaryDark">@color/material_green_700</item> |
| 236 | + <item name="colorAccent">@color/material_purple_a700</item> |
| 237 | + <item name="colorControlNormal">@color/material_green_500</item> |
| 238 | + <item name="colorControlActivated">@color/material_lime_a700</item> |
| 239 | + <item name="colorControlHighlight">@color/material_green_a200</item> |
| 240 | + <item name="android:windowBackground">@color/material_green_50</item> |
| 241 | +</style> |
| 242 | +``` |
| 243 | + |
| 244 | +With associated colors: |
| 245 | + |
| 246 | +``` |
| 247 | +<color name="material_green_50">#E8F5E9</color> |
| 248 | +<color name="material_green_500">#4CAF50</color> |
| 249 | +<color name="material_green_700">#388E3C</color> |
| 250 | +<color name="material_green_a200">#69F0AE</color> |
| 251 | +<color name="material_lime_a700">#AEEA00</color> |
| 252 | +<color name="material_purple_a700">#AA00FF</color> |
| 253 | +``` |
| 254 | + |
| 255 | +This would then be used in the construction of the sign-in intent: |
| 256 | + |
| 257 | +``` |
| 258 | +startActivityForResult( |
| 259 | + AuthUI.getInstance(this).createSignInIntentBuilder() |
| 260 | + // ... |
| 261 | + .setTheme(R.style.GreenTheme) |
| 262 | + .build()); |
| 263 | +``` |
| 264 | + |
| 265 | +Your application theme could also simply be used, rather than defining a new |
| 266 | +one. |
| 267 | + |
| 268 | +If you wish to change the string messages, the existing strings can be |
| 269 | +easily overridden by name in your application. See |
| 270 | +[the built-in strings.xml](src/main/res/values/strings.xml) and simply |
| 271 | +redefine a string to change it, for example: |
| 272 | + |
| 273 | +``` |
| 274 | +<resources> |
| 275 | + <!-- was "Signing up..." --> |
| 276 | + <string name="progress_dialog_signing_up">Creating your shiny new account...</string> |
| 277 | +</resources> |
| 278 | +``` |
0 commit comments