There are up to one billion HUAWEI ID users across the globe. Apps with HUAWEI Account Kit integrated allow users to sign in using their HUAWEI IDs with just a tap. By integrating Account Kit, you can attract new users, by leveraging the enormous HUAWEI ID user base. Account Kit complies with the OAuth 2.0 and OpenID Connect protocols.
To use this Kit, you will need to:
In this codelab, you will use the demo project that we provide to call the APIs of Account Kit. Through the demo project, you will:
In this codelab, you will learn how to:
To integrate Account Kit, you must complete the following preparations:
For details, please refer to Preparations for Integrating HUAWEI HMS Core.
Now, you have successfully enabled Account Kit for your app.
dependencies {
implementation 'com.huawei.hms:hwid:{version}'
}
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
"R.string.hms*",
"R.string.connect_server_fail_prompt_toast",
"R.string.getting_message_fail_prompt_toast",
"R.string.no_available_network_prompt_toast",
"R.string.third_app_*",
"R.string.upsdk_*",
"R.layout.hms*",
"R.layout.upsdk_*",
"R.drawable.upsdk*",
"R.color.upsdk*",
"R.dimen.upsdk*",
"R.style.upsdk*",
"R.string.agc*"
Account Kit mainly provides APIs for sign-in, silent sign-in, sign-out, and authorization revoking. In this codelab, you can create a UI in your Android Studio project. An example is shown in the following figure.
Your app displays the ID sign-in button on the sign-in screen.
Java:
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setIdToken().createParams();
Kotlin:
val authParams : AccountAuthParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setIdToken().createParams()
Java:
AccountAuthService service = AccountAuthManager.getService(MainActivity.this, authParams);
Kotlin:
val service : AccountAuthService = AccountAuthManager.getService(this@MainActivity, authParams)
Java:
startActivityForResult(service.getSignInIntent(), 8888);
Kotlin:
startActivityForResult(service.signInIntent, 8888)
Java:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
// Process the authorization result to obtain an ID token from AuthAccount.
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 8888) {
Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
if (authAccountTask.isSuccessful()) {
// The sign-in is successful, and the user's ID information and ID token are obtained.
AuthAccount authAccount = authAccountTask.getResult();
Log.i(TAG, "idToken:" + authAccount.getIdToken());
} else {
// The sign-in failed. No processing is required. Logs are recorded for fault locating.
Log.e(TAG, "sign in failed : " +((ApiException)authAccountTask.getException()).getStatusCode());
}
}
}
Kotlin:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// Process the authorization result to obtain an ID token from AuthAccount.
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 8888) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
// The sign-in is successful, and the user's ID information and ID token are obtained.
val authAccount = authAccountTask.result
Log.i(TAG, "idToken:" + authAccount.idToken)
} else {
// The sign-in failed. No processing is required. Logs are recorded for fault locating.
Log.e(TAG, "sign in failed : " + (authAccountTask.exception as ApiException).statusCode)
}
}
}
Account Kit also allows for sign-in using an ID in authorization code mode. Use this mode when you have your own app server.
Your app displays the ID sign-in button on the sign-in screen.
Java:
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams();
Kotlin:
val authParams : AccountAuthParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams()
Java:
AccountAuthService service = AccountAuthManager.getService(MainActivity.this, authParams);
Kotlin:
val service : AccountAuthService = AccountAuthManager.getService(this@MainActivity, authParams)
Java:
startActivityForResult(service.getSignInIntent(), 8888);
Kotlin:
startActivityForResult(service.signInIntent, 8888)
Java:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
// Process the authorization result to obtain an authorization code from AuthAccount.
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 8888) {
Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
if (authAccountTask.isSuccessful()) {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
AuthAccount authAccount = authAccountTask.getResult();
Log.i(TAG, "serverAuthCode:" + authAccount.getAuthorizationCode());
} else {
// The sign-in failed.
Log.e(TAG, "sign in failed : " + ((ApiException)authAccountTask.getException()).getStatusCode());
}
}
}
Kotlin:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// Process the authorization result to obtain an authorization code from AuthAccount.
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 8888) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
val authAccount = authAccountTask.result
Log.i(TAG, "serverAuthCode:" + authAccount.authorizationCode)
} else {
// The sign-in failed.
Log.e(TAG, "sign in failed : " + (authAccountTask.exception as ApiException).statusCode)
}
}
}
Request example:
POST /oauth2/v3/token HTTP/1.1
Host: oauth-login.cloud.huawei.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=CF3L7XyCVZi52XMdsUzD7Z6ap0/N2qExcNe0AMqTselTtNd1B4DUwTsQ/23FPZasC8yI29v+N2s2jMT/T2MXiuc+178I/sYuWVoTyqwBaDqVW82KCMqaxbeWBguH4hEENxmDSUIE61Qg5R1F074PiS+qJYnbLI2IBqatS37px8pn5qnuq5oX+UX8XN3/w8HLt4GpakW5Dk1v7hGs&
client_id={app_id}&
client_secret={app_secret}&
redirect_uri=https%3A%2F%2F/www.example.com/%2Fredirect_uri
Response example:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "CFyJ21sNODl16eV9y2vu3CwQk9DBr32BkOcxxgAd7MZUR5th1giyTk5\/kA+QDAyxou+\/5U2zzBRcf3qgLkkFdtbbC+mM3zFV7xj7CCEMHc5Tw92al0Y=",
"refresh_token": "CF13G0sRaGybtYt7SIyeUILNORtTFwMgz4ao5C7j7vtgLPt6ogmXKjdI8RS\/YlyS71z4DyP6kEMnOrRlmNK0KhdOUNWd+qVLLRsEEHkqRIKpuAkPvL8=",
"expires_in": 3600,
"id_token": "eyJraWQiOiI3YTNlYjRkNTJmMDdhODM0NDU4MmRhOGQ3MWE1MGQ5MDlmNWM0YmRiZTFkNDQ3MjQ2MDNhZTA2NGM0ZTlkZGYyIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiM0hPdFZYOEdMcG1GSDBWRVlSc1BjdyIsImF1ZCI6IjEwMDczNTE2NyIsInN1YiI6Ik1ERTlYaWFoc3MwaWFFNXU2c09PaEY5Mlhvell0Rkt4bUdtbWlhNGtTaEJ3dklLR2ciLCJhenAiOiIxMDA3MzUxNjciLCJpc3MiOiJodHRwczovL2FjY291bnRzLmh1YXdlaS5jb20iLCJuYW1lIjoi6Jab5oyv5Y2OIiwiZXhwIjoxNTczMDQ2NDI4LCJnaXZlbl9uYW1lIjoi6Jab5oyv5Y2OIiwiZGlzcGxheV9uYW1lIjoi5rKh5pyJ562U5qGIIiwiaWF0IjoxNTczMDQyODI4LCJwaWN0dXJlIjoiaHR0cHM6Ly91cGZpbGUtZHJjbi5wbGF0Zm9ybS5oaWNsb3VkLmNvbS9GaWxlU2VydmVyL2ltYWdlL2IuMDI2MDA4NjAwMDIzMjQ3MjUxMS4yMDE5MDgyMDExNTQ0Mi5tbmRjWTZyN2JUT0xNcVdiNVBhZDIzZExWNXh0b1Z2WC4xMDAwLkI0QkUyQTdEM0I3NkFGMzBCMkJDNjlBQ0JFNjg3NDIxMTQwMjhEQzYwREZFOTVCMjM5QkI0QzM2OUQwOUVEMkEuanBnIn0.mqy2C3ZNYEM8FKt8r1LX0VFosJjpqVl7E7mw2N-uEhnmAJq3blBco8fp2TCEyUzi1qFMN7-cjv87mQqCEpgfozyU7xV0VXMGdcd9ZhOxtabZtQGxUXRpIPiK5iysp68d95_QJAf2YZIdA4P_1zU8ZGxH57njIXRUVdQWDB8poeuB9gOc72bufe3DmSkqYD9aKvcibpA44Iln58aj-I9xs-FpcDwE6Y9hTfLGT5vk_5hXs32qwt54kEH1JjKbzZRW7B-OaELJIzzOM49oZKrdkViG6c2Tco1xX1WcKSz298Wckj4suLBAqkam4AprQgoSETC__ORTfy9OHIS1m4_8uQ",
"scope": "openid profile email",
"token_type": "Bearer"
}
The access token has a short validity period (currently, 60 minutes). When the access token has expired or is about to expire, request a new access token from the account server by sending the refresh token through the /oauth2/v3/token API.
Request example:
POST /oauth2/v3/token HTTP/1.1
Host: oauth-login.cloud.huawei.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&
client_id=12345&
client_secret=bKaZ0VE3EYrXaXCdCe3d2k9few&
refresh_token=CF2Mm03n0aos9iZZ8nIhfyDtoXy74CXeBi50gVVhMpB0IUzlv9ZwizEvTBhVoF820ZPim0JwNR9j2p1qgEQWnIVYZRlp4T6ezMgekUnsHBkvNev5rd2MdfQMLP
Response example:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token": "CFyJ4J\/l6wuwcFqYOJG4maq2ca8RAV+g0i+mel6qCV5lvqH0PYtW0+BNwfHWg0AqMnW6ZdBvUgs7ijkxMFh1xVP\/B+vQXz3PWsivkKCuL78XtbLt7vs=",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjExOGRmMjU0YjgzNzE4OWQxYmMyYmU5NjUwYTgyMTEyYzAwZGY1YTQiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI3ODI0NTY2Njc4OTgtc2M0MzE3Y2l0NGEwMjB0NzdrbGdsbWo1ZjA4YWtnMWIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiI3ODI0NTY2Njc4OTgtN2NkNGJpYWRkaGVwNGc4cnZic2VlOGtwcDA5Zm1hNzIuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDE3MTIxMzkwMzgwNDE2MDc0MTQiLCJlbWFpbCI6Inh1ZXpoZW5odWF0anVAc2luYS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwicGljdHVyZSI6Imh0dHBzOi8vbGg1Lmdvb2dsZXVzZXJjb250ZW50LmNvbS8tMm9lTTllT09zNTAvQUFBQUFBQUFBQUkvQUFBQUFBQUFBQkkvMVpOSC0xdmxxc3cvczk2LWMvcGhvdG8uanBnIiwiaWF0IjoxNTYxNDUxMTUyLCJleHAiOjE1NjE0NTQ3NTJ9.Eo9IHMkid596jvt1YYzNsRtDq9c9K9dbougkU41Noh7TXNiko86_RuWwHID6k1kDg398AwC3wwH-t2hLcUjgrXPNd9XYU96Jp4-UxdDszP6ywEJgvvBCyTHzsi2auvKt_MnfSrs3qOKfh7noJvXq8AY-Hi3vqSUks5kGqbZKVzCHhBDO3RD9Fs9YHsB6w0XVKZojPOBDaAT_TiijoChn-Q-e8NbSGUx52OgeH-Nw5lOj6JVb_7fb6ucWRzlhiQuzFjklevLVw2pjw1MxKbl1vfRp0X699uZBVjgl9hj1L7LSDObuPzLiXF7ojji5JKYC6zIwAtZQUZ_VUmSk01GDLQ",
"expires_in": 3600,
"scope": "openid profile email",
"token_type": "Bearer"
}
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).createParams();
Kotlin:
val authParams : AccountAuthParams = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).createParams()
AccountAuthService service = AccountAuthManager.getService(MainActivity.this, authParams);
Kotlin:
val service : AccountAuthService = AccountAuthManager.getService(this@MainActivity, authParams)
Task<AuthAccount> task = service.silentSignIn();
Kotlin:
val task : Task<AuthHuaweiId> = service.silentSignIn()
task.addOnSuccessListener(new OnSuccessListener<AuthAccount>() {
@Override
public void onSuccess(AuthAccount authAccount) {
// Obtain the user's ID information.
Log.i(TAG, "displayName:" + authAccount.getDisplayName());
// Obtain the ID type (0: HUAWEI ID; 1: AppTouch ID).
Log.i(TAG, "accountFlag:" + authAccount.getAccountFlag());
}
});
Kotlin:
task.addOnSuccessListener { authAccount ->
// Obtain the user's ID information.
Log.i(TAG, "displayName:" + authAccount.displayName)
// Obtain the ID type (0: HUAWEI ID; 1: AppTouch ID).
Log.i(TAG, "accountFlag:" + authAccount.accountFlag);
}
If the authorization fails, the user may have not successfully signed in before. Your app may determine whether to call the getSignInIntent method of AccountAuthService to explicitly display the authorization screen.
Java:
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// The sign-in failed. Try to sign in explicitly using getSignInIntent().
if (e instanceof ApiException) {
ApiException apiException = (ApiException)e;
Log.i(TAG, "sign failed status:" + apiException.getStatusCode());
}
}
});
Kotlin:
task.addOnFailureListener { e ->
// The sign-in failed. Try to sign in explicitly using getSignInIntent().
if (e is ApiException) {
Log.i(TAG, "sign failed status:" + e.statusCode)
}
}
Java:
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
Task<Void> signOutTask = service.signOut();
Kotlin:
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
val signOutTask = service.signOut()
Java:
signOutTask.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
// Processing after the sign-out.
Log.i(TAG, "signOut complete");
}
});
Kotlin:
signOutTask.addOnCompleteListener { it ->
// Processing after the sign-out.
Log.i(TAG, "signOut complete")
}
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
service.cancelAuthorization().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// Processing after a successful authorization revoking.
Log.i(TAG, "onSuccess: ");
} else {
// Handle the exception.
Exception exception = task.getException();
if (exception instanceof ApiException){
int statusCode = ((ApiException) exception).getStatusCode();
Log.i(TAG, "onFailure: " + statusCode);
}
}
}
});
Kotlin:
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
service.cancelAuthorization().addOnCompleteListener { task ->
if (task.isSuccessful) {
// Processing after a successful authorization revoking.
Log.i(TAG, "onSuccess: ")
} else {
// Handle the exception.
val exception = task.exception
if (exception is ApiException) {
val statusCode = exception.statusCode
Log.i(TAG, "onFailure: $statusCode")
}
}
}
After completing your app development, click to run your Android Studio project to generate the APK and install it on your phone for testing. After launching the demo app, you'll see the following screen:
Well done. You have successfully completed this codelab and learned how to:
For more information, please click the following link:
API Reference
To download the sample code, please click the button below: