Wear OS apps can run standalone, without a companion app. This means that a Wear OS app needs to manage authentication on its own when accessing data from the internet. But the watch's small screen size and reduced input capabilities limit the authentication options that a Wear OS app can use.
This guide covers the recommended authentication methods for Wear OS apps as well as alternatives when those methods don't fit an app's use case.
To learn more about how to design a good sign-in experience, view the Sign-in UX guide.
Guest mode
Don't require authentication for all functionality. Instead, provide as many features as possible to the user without requiring them to sign in.
Users might discover and install your Wear app without having used the mobile app, so they might not have an account and might not know what features it offers. Make sure the guest mode functionality accurately showcases your app's features.
Some devices might stay unlocked longer
On supported devices that run Wear OS 5 or higher, the system detects whether the user is wearing the device on their wrist. If the user turns off wrist detection and then takes the device off of their wrist, the system keeps the device unlocked for a longer period of time than it would otherwise.
If your app requires a higher level of security—such as when displaying potentially sensitive or private data—first check whether wrist detection is enabled:
val wristDetectionEnabled =
isWristDetectionAutoLockingEnabled(applicationContext)
If the return value of this method is false
, prompt the user to sign into an
account in your app before displaying user-specific content.
Recommended authentication methods
Use the following authentication methods to enable standalone Wear OS apps to obtain user authentication credentials.
Pass tokens using the data layer
The phone companion app can securely transfer authentication data to the Wear OS app using the Wearable Data Layer. Transfer credentials as messages or data items.
This type of authentication typically doesn't require any action from the user. However, avoid performing authentication without informing the user that they are being signed in. You can inform the user using a simple, dismissible screen that shows them their account is being transferred from mobile.
Important: Your Wear app must offer at least one other authentication method, because this option works only on Android-paired watches when the corresponding mobile app is installed. Provide an alternate authentication method for users who don't have the corresponding mobile app or whose Wear OS device is paired with an iOS device.
Pass tokens using the data layer from the mobile app, as shown in the following example:
val token = "..." // Auth token to transmit to the wearable device. val dataClient: DataClient = Wearable.getDataClient(context) val putDataReq: PutDataRequest = PutDataMapRequest.create("/auth").run { dataMap.putString("token", token) asPutDataRequest() } val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)
Listen for data change events on the watch app as shown in the following example:
val dataClient: DataClient = Wearable.getDataClient(context) dataClient.addListener{ dataEvents -> dataEvents.forEach { event -> if (event.type == DataEvent.TYPE_CHANGED) { val dataItemPath = event.dataItem.uri.path ?: "" if (dataItemPath.startsWith("/auth")) { val token = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("token") // Display interstitial screen to notify the user they are being signed in. // Then, store the token and use it in network requests. } } } }
For more information on using the Wearable Data Layer, see Send and sync data on Wear OS.
Use OAuth 2.0
Wear OS supports two OAuth 2.0-based flows, which are described in the sections that follow:
- Authorization Code Grant with Proof Key for Code Exchange (PKCE), as defined in RFC 7636
- Device Authorization Grant, as defined in RFC 8628
Note: To help ensure that your app doesn’t shut down when the watch goes into ambient
mode, enable Always-on using
AmbientModeSupport.attach
in the activity performing authentication. For more information about best practices in Ambient Mode,
see Keep your app visible on Wear.
Proof Key for Code Exchange (PKCE)
To effectively use PKCE, use
RemoteAuthClient
.
To perform an auth request from your Wear OS app to an OAuth provider, create an
OAuthRequest
object. This object consists of a URL to your OAuth endpoint for getting a token and a
CodeChallenge
object. The following code shows an example of creating an auth request:
val request = OAuthRequest.Builder(this.applicationContext) .setAuthProviderUrl(Uri.parse("https://....")) .setClientId(clientId) .setCodeChallenge(codeChallenge) .build()
After you build the auth request, send it to the companion app using the
sendAuthorizationRequest()
method:
val client = RemoteAuthClient.create(this) client.sendAuthorizationRequest(request, { command -> command?.run() }, object : RemoteAuthClient.Callback() { override fun onAuthorizationResponse( request: OAuthRequest, response: OAuthResponse ) { // Extract the token from the response, store it and use it in network requests. } override fun onAuthorizationError(errorCode: Int) { // Handle error } } )
This request triggers a call to the companion app, which then presents an authorization UI in a web browser on the user's mobile phone. The OAuth 2.0 provider authenticates the user and obtains the user's consent for the requested permissions. The response is sent to the automatically generated redirect URL.
After a successful or failed authorization, the OAuth 2.0 server redirects to the URL specified in the request. If the user approves the access request, then the response contains an authorization code. If the user doesn't approve the request, the response contains an error message.
The response is in the form of a query string and looks like one of the following examples:
https://wear.googleapis.com/3p_auth/com.your.package.name?code=xyz https://wear.googleapis-cn.com/3p_auth/com.your.package.name?code=xyz
This loads a page that directs the user to the companion app. The companion app verifies the
response URL and relays the response to the third-party watch app using the
onAuthorizationResponse
API.
The watch app can then exchange the authorization code for an access token.
Note: Once the OAuthRequest
is built, you can find your redirect URL by accessing
redirectUrl.
Device Authorization Grant
When using Device Authorization Grant, the user opens the verification URI on another device. Then the authorization server asks them to approve or deny the request.
To make this process easier, use a
RemoteActivityHelper
to open a web page on the user's paired mobile device, as shown in the following example:
// Request access from the authorization server and receive Device Authorization Response. val verificationUri = "..." // Extracted from the Device Authorization Response. RemoteActivityHelper.startRemoteActivity( this, Intent(Intent.ACTION_VIEW) .addCategory(Intent.CATEGORY_BROWSABLE) .setData(Uri.parse(verificationUri)), null ) // Poll the authorization server to find out if the user completed the user authorization // step on their mobile device.
If you have an iOS app, use universal links to intercept this intent in your app instead of relying on the browser to authorize the token.
Other authentication methods
Wear OS supports additional sign-in methods, described in the following sections.
Google Sign-In
Google Sign-In lets the user sign in with their existing Google account. It offers the best user experience and is easy to support, especially if you already implement it in your handheld apps.
After the recommended authentication methods described previously, Google Sign-In is the next preferred solution because it also works well on iOS. The following section describes how to complete a basic Google Sign-In integration.
Prerequisites
Before you can start integrating Google Sign-In in your Wear OS app, you must configure a Google API Console project and set up your Android Studio project. For more information, see Start Integrating Google Sign-In into Your Android App.
If you use Google Sign-In with an app or site that communicates with a backend server, there are two additional prerequisites:
- Create an OAuth 2.0 web application client ID for your backend server. This client ID is different from your app's client ID. For more information, see Enabling Server-Side Access.
- Identify the currently signed-in user securely on the server by sending the user's ID token using HTTPS. To learn how to authenticate your user on the backend server, see Authenticate with a backend server.
Integrate Google Sign-In into your app
Review and implement the following steps, which are detailed in the sections that follow, to integrate Google Sign-In into your Wear OS app:
- Configure Google Sign-In.
- Add a Google Sign-In button.
- Start the sign-in flow when the sign-in button is tapped.
Configure Google Sign-In and build the GoogleApiClient object
In your sign-in activity's onCreate()
method, configure Google Sign-In to request
the user data required by your app. Then, create a GoogleApiClient
object with
access to the Google Sign-In API and the options you specified. These steps
are shown in the following example:
public class MyNewActivity extends AppCompatActivity { private static final int RC_SIGN_IN = 9001; private GoogleSignInClient mSignInClient; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); GoogleSignInOptions options = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .build(); mSignInClient = GoogleSignIn.getClient(this, options); } }
Add a Google Sign-In button to your app
Complete the following steps to add a Google Sign-In button:
-
Add the
SignInButton
to your app's layout: -
In your app's
onCreate()
method, register your button'sOnClickListener
to sign the user in when tapped:
<com.google.android.gms.common.SignInButton android:id="@+id/sign_in_button" android:layout_width="wrap_content" android:layout_height="wrap_content" />
Kotlin
findViewById<View>(R.id.sign_in_button).setOnClickListener(this)
Java
findViewById(R.id.sign_in_button).setOnClickListener(this);
Create a sign-in intent and start the sign-in flow
Handle sign-in button taps in your onCLick()
method by creating a sign-in intent with the
getSignInIntent()
method. Then start the intent with the
startActivityForResult()
method.
Intent intent = mSignInClient.getSignInIntent(); startActivityForResult(intent, RC_SIGN_IN);
The user is prompted to select a Google account to sign in with. If you requested scopes beyond profile, email, and open ID, the user is also prompted to grant access to those resources.
Finally, in the activity's
onActivityResult
method, retrieve the sign-in result with
getSignInResultFromIntent
. After you retrieve the sign-in result, you can
check whether the sign-in succeeded using the
isSuccess
method. If sign-in succeeds, you can call the
getSignInAccount
method to get a
GoogleSignInAccount
object that contains information about the signed-in
user, such as the user's name. These steps are shown in the following example:
Kotlin
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { super.onActivityResult(requestCode, resultCode, data) // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...). if (requestCode == RC_SIGN_IN) { Auth.GoogleSignInApi.getSignInResultFromIntent(data)?.apply { if (isSuccess) { // Get account information. fullName = signInAccount?.displayName mGivenName = signInAccount?.givenName mFamilyName = signInAccount?.familyName mEmail = signInAccount?.email } } } }
Java
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...). if (requestCode == RC_SIGN_IN) { GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data); if (signInResult.isSuccess()) { GoogleSignInAccount acct = signInResult.getSignInAccount(); // Get account information. fullName = acct.getDisplayName(); givenName = acct.getGivenName(); familyName = acct.getFamilyName(); email = acct.getEmail(); } } }
To see a sample app that implements Google Sign-In, see the Horologist Google Sign-In Sample on GitHub.
Custom code authentication
As an alternative to the authentication methods described previously, you can require the user to authenticate from another device, such as a mobile phone or tablet, and obtain a short-lived numeric code. The user then enters the code on their Wear OS device to confirm their identity and receives an auth token.
This authentication flow either uses your app’s login module, or manually integrates a third-party auth provider sign-in method into your app’s code. Although this authentication method requires manual work and additional effort to make it more secure, you can use this method if you need authentication earlier in your standalone Wear OS apps.
The auth flow for this setup works as follows:
- The user performs an action with the Wear OS app requiring authorization.
- The Wear OS app presents an authentication screen to the user and instructs the user to enter a code from a specified URL.
- The user switches to a mobile device, tablet, or PC, and then launches a browser, navigates to the URL specified on the Wear OS app, and logs in.
- The user receives a short-lived numeric code that they enter into the Wear OS app
authentication screen using the onboard keyboard in Wear OS:
- From this point, you can use the entered code as proof that this is the correct user and exchange the code for an auth token stored and secured on the Wear OS device for authenticated calls going forward.
Note: The code that the user generates must be purely numerical and can't contain any alphabetic characters.
This auth flow is depicted in the following chart:
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2024-11-20 UTC.