Integrate A3L Authentication SDK
Use this guide to integrate your app with the A3L Authentication SDK.
- Setup A3L Authentication sign-in
- Access user profile information
- Sign out users
- Disconnect accounts
- Authenticate with a back-end server
- Related topics
Setup A3L Authentication sign-in
To integrate A3L Authentication into your Android app, you must configure A3L Authentication and add a button to start the sign-in flow.
Initialize A3L Authentication
In your sign-in activity's onCreate()
method, initialize A3L Authentication, providing the Android client ID you got from the Google API Console, as shown in the following code.
<PREFIX>
is the part of the client ID before .apps.googleusercontent.com
. When you copy the ID from the Google API Console, remove .apps.googleusercontent.com
.try{
A3LAuth.init(<PREFIX>);
} catch(APIException e) {
e.printStackTrace();
}
The default solution for devices with Google Play services is Google Sign-In. Devices without Google Play services default to AppAuth. If you prefer to provide a similar experience to users and use AppAuth as the solution on all devices, initialize your app as shown in the following code.
try{
A3LAuth.init(<PREFIX>, true);
} catch(APIException e) {
e.printStackTrace();
}
Configure A3LSignIn and A3LSignInClient objects
Next, configure the A3LSignIn
and A3LSignInClient
objects by following these steps.
-
In the
onCreate()
method, configure A3L Authentication to request the user data that your app requires through anA3LSignInOptions
object.For example, to configure A3L Authentication to request a user's ID and basic profile information, build an
A3LSignInOptions
object using theDEFAULT_SIGN_IN
parameter. If you want to also request a user's email address, include therequestEmail()
option when you create theA3LSignInOptions
object, as shown here.// Configure sign in to request the user's ID, email address, and basic // profile. ID and basic profile are included in DEFAULT_SIGN_IN. A3LSignInOptions a3LSignInOptions = new A3LSignInOptions .Builder(A3LSignInOptions.DEFAULT_SIGN_IN) .requestEmail() .build();
Note: If you need additional scopes for your app to function as intended, use therequestScopes()
option when you create theA3LSignInOptions
object. A list of the scopes supported can be found in Scopes supported by A3L Authentication. -
In the
onCreate()
method, create anA3LSignInClient
object using the options you specified in theA3LSignInOptions
object that you created in the previous step, as shown in the following code.// Build a A3LSignInClient with the options specified by // A3LSignInOptions object created above. mA3LSignInClient = A3LSignIn.getClient(this, a3LSignInOptions);
Check for a signed-in user
Before displaying the sign-in flow, check if the user is already signed in to the app by using the getLastSignedInAccount()
method. In your activity's onStart()
method, check if the user is already signed in, as shown in this example.
// Check for existing Sign In account, if the user is already signed in
// the A3LSignInAccount will be non-null.
A3LSignInAccount account = A3LSignIn.getLastSignedInAccount(this);
updateUI(account);
If a non-null A3LSignInAccount
object is returned, it means the user is already signed in to the app and you don't have to prompt them again. You can progress the user to your app's post sign-in experience.
If null is received, that means the user is not signed in to the app. Provide the sign-in button for the user to sign in to the app.
private void updateUI(A3LSignInAccount account) {
if (account!=null) {
// provide the signed-in experience to the user
} else {
// provide sign-in button and other info for user to sign in to the app
}
}
Add a sign-in button to your app
You can create a custom sign-in button for your app, but if you want to use the default sign-in button provided by Google, follow the steps listed below.
-
Add the sign-in button in your app layout.
<com.google.android.gms.common.SignInButton android:id="@+id/sign_in_button" android:layout_width="wrap_content" android:layout_height="wrap_content" />
-
In the Android activity, add an
OnClickListener
to the button. For example, you can add the following code in theonCreate()
method.findViewById(R.id.sign_in_button).setOnClickListener(this);
When a user clicks this button, your app start the sign-in flow, described in the next section.
Handle sign-in
Sign in the user with these steps.
-
In the activity's
onClick()
method, handle the case when a user presses the sign-in button.@Override public void onClick(View v) { switch (v.getId()) { case R.id.sign_in_button: signIn(); break; // ... } }
In the
signIn()
method, create a sign-in intent using thegetSignInIntent()
method. Start the intent with thestartActivityForResult()
method as shown here.private void signIn() { Intent signInIntent = mA3LSignInClient.getSignInIntent(); startActivityForResult(signInIntent, RC_SIGN_IN); }
Starting the intent has different behavior depending on the device the app is run on. For an Android device that supports Google Play services, the user is prompted, within the app, to select an account to sign in with. For devices without Google Play services, the app opens a Custom Tab and redirects the user to Google's authentication webpage.
In both cases, the user is prompted to select a Google account to sign in with, or to enter the email address that they want to sign in with.
-
In the
onActivityResult()
method, use theA3LSignIn.getSignedInAccountFromIntent()
method to get a task that will return aA3LSignInAccount
object when successful, as shown here.@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Result returned from launching the Intent from A3LSignInClient.getSignInIntent(...); if (requestCode == RC_SIGN_IN) { Task<A3LSignInAccount> task = A3LSignIn.getSignedInAccountFromIntent(data); handleSignInResult(task); } }
The implementation of the
handleSignInResult()
method follows. The resultingA3LSignInAccount
object contains information about the signed-in user, such as their name.private void handleSignInResult(Task<A3LSignInAccount> completedTask) { completedTask.addOnCompleteListener(new OnCompleteListener<A3LSignInAccount>() { @Override public void onComplete(@NonNull Task<A3LSignInAccount> task) { try { A3LSignInAccount account = task.getResult(); updateUI(account); } catch (Exception e) { Log.e(TAG, "signInResult:failed code=" + e.getMessage()); updateUI(null); } } }); }
To access user data from the
A3LSignInAccount
object, use the following methods:getEmail()
to get the user's email addressgetId()
to get the user's Google ID for client-side usegetIdToken()
to get an ID token for the user
To pass the currently signed-in user to a back-end server, send the ID token to your back-end server and validate the token on the server.
Access user profile information
How you configured the A3LSignInOptions
object in Configure A3LSignIn and A3LSignInClient objects determines which information you can access from the signed-in user. If you configured A3LSignInOptions
with the DEFAULT_SIGN_IN
parameter or the requestProfile()
method, you can access the user's basic profile information after they sign in. If you configured A3LSignInOptions
with the requestEmail()
method, you can also access the user's email address.
To request profile information for the currently signed-in user, use the A3LSignIn.getLastSignedInAccount()
method, as shown in the following example.
A3LSignInAccount acct = A3LSignIn.getLastSignedInAccount(getActivity());
if (acct != null) {
String personName = acct.getDisplayName();
String personGivenName = acct.getGivenName();
String personFamilyName = acct.getFamilyName();
String personEmail = acct.getEmail();
String personId = acct.getId();
Uri personPhoto = acct.getPhotoUrl();
}
To see all potential fields that you can access from an A3LSignInAccount
object, see the A3L Authentication API Reference.
Sign out users
Provide a way for users to sign out of your app by adding a sign-out button. After you create a sign-out button, attach an OnClickListener
to the button and configure the onClick()
method to call the signOut()
method, as shown in the following code.
@Override
public void onClick(View v) {
switch (v.getId()) {
// ...
case R.id.button_sign_out:
signOut();
break;
// ...
}
}
private void signOut() {
mA3LSignInClient.signOut()
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
// ...
}
});
}
When your app runs this code, the user's Google account is signed out of your app. The user can choose to sign in again with their Google account without any prompts for permissions, such as requesting access to specified scopes.
Disconnect accounts
Provide users with the ability to disconnect their Google account from your app. If a user chooses to disconnect their account from your app, you must delete the information that your app obtained from Google's APIs. When you revoke access, it removes the permissions that the user has given to your app to access their data through the scopes.
To disconnect a user's account, call the revokeAccess()
method, as shown in the following example.
private void revokeAccess() {
mA3LSignInClient.revokeAccess()
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
// ...
}
});
}
In the OnCompleteListener
, your app can respond to the event and run any additional required code.
Revoking access to the app is provided in A3L Authentication, but it differs from Google's revoke access functionality. When revoking access using Google Sign-In, the app is removed from user's Google account. This is not the case in A3L Authentication. In A3L Authentication, the revoke access functionality revokes the access of user from the app and remove the permissions to access the data given to the app, but it doesn't delete the entries in the user's account. To remove the app from the entries, follow the Google developer documentation on Revocation methods.
Authenticate with a back-end server
If you're using A3L Authentication and your app communicates with a back-end server, you might need to identify the currently signed-in user on the server. To securely identify the currently signed-in user, use HTTPS to send the user's ID token to your server. On the server, verify the integrity of the ID token. Use the user data from the token to establish a session with a known user or to create a new account record for a new user.
Fetch the ID token
First, you must fetch the user's ID token when they sign in. Configure A3L Authentication with the requestIdToken()
method and pass your server's web client ID to this method, as shown here.
// Request only the user's ID token, which can be used to identify the
// user securely to your backend. This will contain the user's basic
// profile (name, profile picture URL, etc) so you should not need to
// make an additional call to personalize your app.
A3LSignInOptions a3LSignInOptions = new A3LSignInOptions.Builder(A3LSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.server_client_id))
.requestEmail()
.build();
When the user signs in, get the A3LSignInAccount
object from the activity result of the sign-in intent:
Task<A3LSignInAccount> task = A3LSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
After the user signs in, get the ID token from the A3LSignInAccount
object, as shown here.
private void handleSignInResult(@NonNull Task<A3LSignInAccount> completedTask) {
completedTask.addOnCompleteListener(new OnCompleteListener<A3LSignInAccount>() {
@Override
public void onComplete(@NonNull Task<A3LSignInAccount> task) {
try {
A3LSignInAccount account = task.getResult();
String idToken = account.getIdToken();
// handle ID Token
} catch (Exception e) {
Log.w(TAG, "signInResult:failed code=" + e.getMessage());
updateUI(null);
}
}
});
}
Send the ID token to your server
Use an HTTPS POST request to send the ID token to your server, as shown here.
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://yourbackend.example.com/tokensignin");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("idToken", idToken));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
final String responseBody = EntityUtils.toString(response.getEntity());
Log.i(TAG, "Signed in as: " + responseBody);
} catch (ClientProtocolException e) {
Log.e(TAG, "Error sending ID token to backend.", e);
} catch (IOException e) {
Log.e(TAG, "Error sending ID token to backend.", e);
}
After you fetch the ID token, validate it by following the instructions in Google's developer documentation, Verify the integrity of the ID token.
Related topics
- Integrate with Google APIs
- A3L Authentication Sample App
- A3L Authentication Reference, Troubleshooting, and FAQ
Last updated: Dec 05, 2023