ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Using Jetpack Credential Manager to save and retrieve passwords in-app

Photo by Scott Webb

Saving user credentials has traditionally been a bit hit-and-miss in Android, but a new library released earlier this month looks like a promising way to address that.

What we want is straightforward:

  • A way of saving a user’s username/password (or other credential) on registration or first sign in
  • A one-tap way to sign in using a saved password
  • For a user’s saved passwords to be securely saved to their Google account, so they survive app reinstallation and are accessible across all their devices

The new Jetpack Credential Manager library offers all the above in an easy-to-use package. This article shows how you can add this to your app.

Here is a demo of what we’re going to build:

Screen recording showing Credential Manager in action, saving and using saved credentials
On first sign in, the user gets the option to save their credentials. On subsequent sign ins, they can just use the saved credentials.

In this demo we’re using username/password credentials. But one of the important assets of this library is its flexible support for whatever authentication method the user chooses. So it supports federated login tokens, passkeys (FIDO2 / private key authentication), or anything else.

The code for this article is available on my GitHub.

Setting up Jetpack Credential Manager

Adding the library to your project is done with Gradle:

//Credentials support
implementation("androidx.credentials:credentials:1.2.0-alpha01")

// optional - needed for credentials support from play services, for devices running
// Android 13 and below.
implementation("androidx.credentials:credentials-play-services-auth:1.2.0-alpha01")

To do anything with this library, you need an instance of CredentialManager. It’s helpful to create this lazily (so it’s instantiated only when needed). Here application is an instance of my Application class, available inside my AndroidViewModel:

Now we can refer to credentialManager throughout the view model, with the confidence it’ll be there when we need it, and only created once.

Saving a credential

When the user registers or signs in successfully, we want to offer to save those credentials to their store. That’s straightforward:

That activity parameter is the current activity. In a Compose function you can get that using LocalContext.current.getActivity(). It’s needed because the OS is going to display an overlay on your app, asking the user whether they want to save the credential:

Screenshot showing the Save password? dialog in an Android app
The user will be asked to save their password after successful authentication

The above code needs:

  1. Error handling, as there’s lots of different exceptions that credentialManager.createCredential() can throw.
  2. To be run asynchronously.

Putting all that together, we get:

Note how this is a suspend fun so that it runs in the coroutine of the calling code.

Also note how we separately catch CreateCredentialCancellationException and promptly ignore it. That exception is thrown when the user chooses not to save the password (say, by dismissing the popup). It doesn’t make sense to report that back to the UI, since the user already knows.

How this fits into the sign in / registration process

You call saveCredential(…) above when the user has successfully registered, or when they have successfully signed in by manually entering a username or password.

In the demo app, I’ve written the function signInOrSignUpWithEnteredCredential(…) to demonstrate:

This also shows how the sign in process and the save credential process can both be run in the same coroutine (and why, therefore, we made saveCredential(…) a suspend fun).

Getting a credential

Once the credential has been saved, you can use it to log in next time. To get a saved credential, use this code:

This is a two-step process. Firstly we formulate a GetCredentialRequest, which tells the library what sorts of credentials we want (in our case only GetPasswordOption(), i.e. username/password). Then we show the dialog allowing the user to pick which credential to use using CredentialManager.getCredential(…).

Screenshot showing overlay asking user if they want to sign in with a saved credential
Offering the user to sign in using their saved credential. If there are multiple credentials available, the user will get to choose from a list.

As before this needs to be run asynchronously, and it needs error handling as there are lots of different types of exceptions which may result.

Putting it all together, we get:

As before we’re using suspend fun so that it runs in the caller’s coroutine.

There are two potential exceptions of note:

  • GetCredentialCancellationException indicates that the user chose not to grant you permission to access any credentials, for example by dismissing the dialog
  • NoCredentialException indicates that the user has no credentials stored for your app

There are plenty of more complex exceptions described in the API docs. Here we’re just rethrowing them so the calling code can decide what to do.

Incidentally, you can see why there’s no need for the app to request any permissions here. It’s totally safe for the user, since they will manually pick which credentials the app can have access to.

And the saved credential will even be available on the user’s other devices, so long as they’re logged into Android with the same Google account.

How this fits into the sign in process

When the user clicks the Sign In With Saved Credentials button, we try and get the saved credentials and then use them to sign in.

As before, this is all done in a single coroutine which shows why it’s helpful to make getCredential(…) a suspend function.

Making it even simpler than that

You could go one step further, and make it so the user doesn’t even have to tap a Sign In With Saved Credentials button.

To do so, attempt a getCredential() as soon as the login screen is shown in your app. The user may not have any credentials saved — but if so, you haven’t bothered them as no popups will have been shown. And if they do have credentials saved, and they grant you permission to use one, you can sign in straight away.

Passkeys, FIDO2, private keys and other kinds of credential

Jetpack Credential Manager supports almost any kind of credential:

  • To save a passkey (FIDO2, private key credentials), create a CreatePublicKeyCredentialRequest object, passing in your WebAuthn JSON spec to the constructor. Then use this object as the request argument of credentialManager.createCredential().
  • To retrieve a passkey, the list passed to GetCredentialRequest’s constructor should contain a GetPublicKeyCredentialOption instance (constructed using the server’s request JSON spec).
  • To save any other type of credential — including something proprietary — instantiate a CreateCustomCredentialRequest and pass it to credentialManager.createCredential(). To retrieve it, instantiate a GetCustomCredentialOption and add it to the list passed to GetCredentialRequest.

For more information on using passkeys with Jetpack Credential Manager, there is a developer guide.

The code for this article is available on my GitHub.

So that’s how we save and re-use users’ passwords. I found the Credential Manager library a little confusing to start with, but in the end the flow became clear enough. It’s currently in Alpha but when it reaches maturity there’s no reason not to use it in every app that uses authentication.

I hope this guide has been helpful. If you have any thoughts or questions please leave a comment.

Tom Colvin is an Android and security specialist. He is available as a freelancer. He is the co-founder of the app development specialists Apptaura, where he still mentors new developers.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Tom Colvin

Android developer / consultant; freelancer or through my agency Apptaura. Google Developer Expert in Android. tomcolvin.co.uk Articles 100% me, no AI.

Responses (1)

Write a response