diff --git a/README.md b/README.md index a8a428d..421c8bd 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ -# Bluemix App ID -Android SDK for the Bluemix App ID service +# IBM Cloud App ID Android SDK [![Bluemix powered][img-bluemix-powered]][url-bluemix] [![Travis][img-travis-master]][url-travis-master] -[![Coveralls][img-coveralls-master]][url-coveralls-master] -[![Codacy][img-codacy]][url-codacy] +[![Coverage Status][img-coveralls-master]][url-coveralls-master] +[![Codacy Badge][img-codacy]][url-codacy] [![Release](https://jitpack.io/v/ibm-cloud-security/appid-clientsdk-android.svg)](https://jitpack.io/#ibm-cloud-security/appid-clientsdk-android) [![License][img-license]][url-bintray] @@ -13,11 +12,14 @@ Android SDK for the Bluemix App ID service [![GithubForks][img-github-forks]][url-github-forks] ## Requirements -API 25 or above, Java 8.x, Android SDK tools 25.2.5 or above, Android SDK Platform Tools 25.0.3 or above, Android Build Tools version 25.0.2 +* API 25 or above +* Java 8.x +* Android SDK tools 25.2.5 or above +* Android SDK Platform Tools 25.0.3 or above +* Android Build Tools version 25.0.2 ## Installing the SDK: -1. Add the JitPack repository to your build file, - Add it in your root build.gradle at the end of repositories: +1. Add the JitPack repository to the your root `build.gradle` file at the end of the repository. ```gradle allprojects { @@ -31,7 +33,7 @@ API 25 or above, Java 8.x, Android SDK tools 25.2.5 or above, Android SDK Platfo 2. Add the dependency for the App ID client SDK: ```gradle dependencies { - compile 'com.github.ibm-cloud-security:appid-clientsdk-android:1.+' + compile 'com.github.ibm-cloud-security:appid-clientsdk-android:2.+' } ``` @@ -43,9 +45,7 @@ API 25 or above, Java 8.x, Android SDK tools 25.2.5 or above, Android SDK Platfo } ``` -## Using the SDK: - -### Initializing the App ID client SDK +## Initializing the App ID client SDK Initialize the client SDK by passing the context, tenantId and region parameters to the initialize method. A common, though not mandatory, place to put the initialization code is in the onCreate method of the main activity in your Android application. ```java @@ -54,8 +54,8 @@ AppID.getInstance().initialize(getApplicationContext(), , AppID.REGION * Replace "tenantId" with the App ID service tenantId. * Replace the AppID.REGION_UK with your App ID region (AppID.REGION_US_SOUTH, AppID.REGION_SYDNEY). -### Using Login Widget -Use LoginWidget class to start the authorization flow. +## Using the Login Widget +Use the LoginWidget class to start the authorization flow. ```java LoginWidget loginWidget = AppID.getInstance().getLoginWidget(); @@ -78,27 +78,130 @@ loginWidget.launch(this, new AuthorizationListener() { ``` **Note**: -The Login widget default configuration use Facebook and Google as authentication options. -If you configure only one of them the login widget will NOT launch and the user will be redirect to the configured idp authentication screen. - -### Anonymous Login + public void onAuthorizationFailure (AuthorizationException exception) { + //Exception occurred + } + + @Override + public void onAuthorizationSuccess (AccessToken accessToken, IdentityToken identityToken) { + //User authenticated + } + }); + ``` + ### Sign Up +Make sure to set **Allow users to sign up and reset their password** to **ON**, in the settings for Cloud Directory. +Use the LoginWidget class to start the sign up flow. + + ```java + LoginWidget loginWidget = AppID.getInstance().getLoginWidget(); + loginWidget.launchSignUp(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure (AuthorizationException exception) { + //Exception occurred + } + + @Override + public void onAuthorizationCanceled () { + //Sign up canceled by the user + } + + @Override + public void onAuthorizationSuccess (AccessToken accessToken, IdentityToken identityToken) { + if (accessToken != null && identityToken != null) { + //User authenticated + } else { + //email verification is required + } + + } + }); + ``` + ### Forgot Password + Make sure to set **Allow users to sign up and reset their password** and **Forgot password email** to **ON**, in the settings for Cloud Directory + + Use LoginWidget class to start the forgot password flow. + ```java + LoginWidget loginWidget = AppID.getInstance().getLoginWidget(); + loginWidget.launchForgotPassword(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure (AuthorizationException exception) { + //Exception occurred + } + + @Override + public void onAuthorizationCanceled () { + //forogt password canceled by the user + } + + @Override + public void onAuthorizationSuccess (AccessToken accessToken, IdentityToken identityToken) { + //forgot password finished, in this case accessToken and identityToken will be null. + + } + }); + ``` + ### Change Details + Make sure to set **Allow users to sign up and reset their password** to **ON**, in Cloud Directory settings that are in AppID dashboard. Use LoginWidget class to start the change details flow. This API can be used only when the user is logged in using Cloud Directory identity provider. + + ```java + LoginWidget loginWidget = AppID.getInstance().getLoginWidget(); + loginWidget.launchChangeDetails(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure (AuthorizationException exception) { + //Exception occurred + } + + @Override + public void onAuthorizationCanceled () { + //changed details canceled by the user + } + + @Override + public void onAuthorizationSuccess (AccessToken accessToken, IdentityToken identityToken) { + //User authenticated, and fresh tokens received + } + }); + ``` + ### Change Password + Make sure to set **Allow users to sign up and reset their password** to **ON**, in the settings for Cloud Directory. + + Use LoginWidget class to start the change password flow. This API can be used only when the user logged in by using Cloud Directory as their identity provider. + + ```java + LoginWidget loginWidget = AppID.getInstance().getLoginWidget(); + loginWidget.launchChangePassword(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure (AuthorizationException exception) { + //Exception occurred + } + + @Override + public void onAuthorizationCanceled () { + //change password canceled by the user + } + + @Override + public void onAuthorizationSuccess (AccessToken accessToken, IdentityToken identityToken) { + //User authenticated, and fresh tokens received + } + }); + ``` + +## Anonymous Login ```java AppID.getInstance().loginAnonymously(getApplicationContext(), new AuthorizationListener() { @Override @@ -118,7 +221,7 @@ AppID.getInstance().loginAnonymously(getApplicationContext(), new AuthorizationL }); ``` -### User profile attributes +## User profile attributes ```java AppID appId = AppID.getInstance(); String name = "name"; @@ -172,7 +275,7 @@ appId.getUserAttributeManager().deleteAttribute(name, new UserAttributeResponseL }); ``` -### Invoking protected resources +## Invoking protected resources ```java BMSClient bmsClient = BMSClient.getInstance(); bmsClient.initialize(getApplicationContext(), AppID.REGION_UK); @@ -199,7 +302,7 @@ public void onFailure (Response response, Throwable t, JSONObject extendedInfo) }); ``` -### License +## License This package contains code licensed under the Apache License, Version 2.0 (the "License"). You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 and may also view the License in the LICENSE file within this package. [img-bluemix-powered]: https://img.shields.io/badge/bluemix-powered-blue.svg @@ -218,8 +321,8 @@ This package contains code licensed under the Apache License, Version 2.0 (the " [img-travis-master]: https://travis-ci.org/ibm-cloud-security/appid-clientsdk-android.svg [url-travis-master]: https://travis-ci.org/ibm-cloud-security/appid-clientsdk-android -[img-coveralls-master]: https://coveralls.io/repos/github/ibm-cloud-security/appid-clientsdk-android/badge.svg -[url-coveralls-master]: https://coveralls.io/github/ibm-cloud-security/appid-clientsdk-android +[img-coveralls-master]: https://coveralls.io/repos/github/ibm-cloud-security/appid-clientsdk-android/badge.svg?branch=master +[url-coveralls-master]: https://coveralls.io/github/ibm-cloud-security/appid-clientsdk-android?branch=master -[img-codacy]: https://api.codacy.com/project/badge/Grade/d41f8f069dd343769fcbdb55089561fc?branch=master -[url-codacy]: https://www.codacy.com/app/ibm-cloud-security/appid-clientsdk-android +[img-codacy]: https://api.codacy.com/project/badge/Grade/be6f5f4cdae446909279d014bc650b1b +[url-codacy]: https://www.codacy.com/app/rotembr/appid-clientsdk-android?utm_source=github.com&utm_medium=referral&utm_content=ibm-cloud-security/appid-clientsdk-android&utm_campaign=Badge_Grad diff --git a/app/src/main/java/com/ibm/mobilefirstplatform/appid/MainActivity.java b/app/src/main/java/com/ibm/mobilefirstplatform/appid/MainActivity.java index 4b9fc94..cbca033 100644 --- a/app/src/main/java/com/ibm/mobilefirstplatform/appid/MainActivity.java +++ b/app/src/main/java/com/ibm/mobilefirstplatform/appid/MainActivity.java @@ -117,6 +117,108 @@ public void onAuthorizationCanceled() { @Override public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identityToken) { logger.info("onAuthorizationSuccess"); + if (accessToken != null && identityToken != null) { + logger.info("access_token: " + accessToken.getRaw()); + logger.info("id_token: " + identityToken.getRaw()); + logger.info("access_token isExpired: " + accessToken.isExpired()); + logger.info("id_token isExpired: " + identityToken.isExpired()); + identifiedAccessToken = accessToken; + extractAndDisplayDataFromIdentityToken(identityToken); + } else { + //in case we are in strict mode + hideProgress(); + } + + } + }, anonymousAccessToken != null ? anonymousAccessToken.getRaw() : null); + } + + public void onSignUpClick(View v) { + logger.debug("onSignUpClick"); + showProgress(); + LoginWidget loginWidget = appId.getLoginWidget(); + loginWidget.launchSignUp(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure(AuthorizationException exception) { + logger.info("sign up: onAuthorizationFailure: " + exception.getMessage()); + showResponse(exception.getMessage()); + hideProgress(); + } + + @Override + public void onAuthorizationCanceled() { + logger.info("sign up: onAuthorizationCanceled"); + hideProgress(); + } + + @Override + public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identityToken) { + logger.info("sign up: onAuthorizationSuccess"); + if (accessToken != null && identityToken != null) { + logger.info("access_token: " + accessToken.getRaw()); + logger.info("id_token: " + identityToken.getRaw()); + logger.info("access_token isExpired: " + accessToken.isExpired()); + logger.info("id_token isExpired: " + identityToken.isExpired()); + identifiedAccessToken = accessToken; + extractAndDisplayDataFromIdentityToken(identityToken); + } else { + //in case we are in strict mode + hideProgress(); + } + + + } + }); + } + + public void onForgotPasswordClick(View v) { + logger.debug("onForgotPasswordClick"); + showProgress(); + LoginWidget loginWidget = appId.getLoginWidget(); + loginWidget.launchForgotPassword(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure(AuthorizationException exception) { + logger.info("Forgot Password: onAuthorizationFailure: " + exception.getMessage()); + showResponse(exception.getMessage()); + hideProgress(); + } + + @Override + public void onAuthorizationCanceled() { + logger.info("Forgot Password: onAuthorizationCanceled"); + hideProgress(); + } + + @Override + public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identityToken) { + logger.info("Forgot Password: onAuthorizationSuccess"); + hideProgress(); + } + }); + } + + public void onChangePasswordClick(View v) { + logger.debug("onChangePasswordClick"); + showResponse(""); + showProgress(); + LoginWidget loginWidget = appId.getLoginWidget(); + loginWidget.launchChangePassword(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure(AuthorizationException exception) { + logger.info("Change Password: onAuthorizationFailure: " + exception.getMessage()); + showResponse(exception.getMessage()); + hideProgress(); + } + + @Override + public void onAuthorizationCanceled() { + logger.info("Change Password: onAuthorizationCanceled"); + hideProgress(); + } + + @Override + public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identityToken) { + logger.info("Change Password: onAuthorizationSuccess"); logger.info("access_token: " + accessToken.getRaw()); logger.info("id_token: " + identityToken.getRaw()); logger.info("access_token isExpired: " + accessToken.isExpired()); @@ -124,7 +226,39 @@ public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identi identifiedAccessToken = accessToken; extractAndDisplayDataFromIdentityToken(identityToken); } - }, anonymousAccessToken != null ? anonymousAccessToken.getRaw() : null); + }); + } + + public void onChangeDetailsClick(View v) { + logger.debug("onChangeDetailsClick"); + showResponse(""); + showProgress(); + LoginWidget loginWidget = appId.getLoginWidget(); + loginWidget.launchChangeDetails(this, new AuthorizationListener() { + @Override + public void onAuthorizationFailure(AuthorizationException exception) { + logger.info("Change Details: onAuthorizationFailure: " + exception.getMessage()); + showResponse(exception.getMessage()); + hideProgress(); + } + + @Override + public void onAuthorizationCanceled() { + logger.info("Change Details: onAuthorizationCanceled"); + hideProgress(); + } + + @Override + public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identityToken) { + logger.info("Change Details: onAuthorizationSuccess"); + logger.info("access_token: " + accessToken.getRaw()); + logger.info("id_token: " + identityToken.getRaw()); + logger.info("access_token isExpired: " + accessToken.isExpired()); + logger.info("id_token isExpired: " + identityToken.isExpired()); + identifiedAccessToken = accessToken; + extractAndDisplayDataFromIdentityToken(identityToken); + } + }); } public void onGetTokenUsingRoP(View v) { @@ -164,7 +298,7 @@ public void onAuthorizationSuccess(AccessToken accessToken, IdentityToken identi identifiedAccessToken = accessToken; extractAndDisplayDataFromIdentityToken(identityToken); } - }); + }, anonymousAccessToken != null ? anonymousAccessToken.getRaw() : null); } } @@ -349,6 +483,7 @@ public void run() { findViewById(R.id.loginButton).setEnabled(false); findViewById(R.id.ropButton).setEnabled(false); findViewById(R.id.protectedRequestButton).setEnabled(false); + findViewById(R.id.signUpButton).setEnabled(false); findViewById(R.id.deleteAttribute).setEnabled(false); findViewById(R.id.anonloginButton).setEnabled(false); findViewById(R.id.getAllAttributes).setEnabled(false); @@ -357,6 +492,9 @@ public void run() { findViewById(R.id.putAttribute).setEnabled(false); findViewById(R.id.editAttrName).setEnabled(false); findViewById(R.id.editAttrValue).setEnabled(false); + findViewById(R.id.changePasswordButton).setEnabled(false); + findViewById(R.id.changeDetailsButton).setEnabled(false); + findViewById(R.id.forgotPassword).setEnabled(false); } }); } @@ -369,6 +507,7 @@ public void run() { findViewById(R.id.loginButton).setEnabled(true); findViewById(R.id.ropButton).setEnabled(true); findViewById(R.id.protectedRequestButton).setEnabled(true); + findViewById(R.id.signUpButton).setEnabled(true); findViewById(R.id.deleteAttribute).setEnabled(true); findViewById(R.id.anonloginButton).setEnabled(true); findViewById(R.id.getAllAttributes).setEnabled(true); @@ -377,6 +516,9 @@ public void run() { findViewById(R.id.putAttribute).setEnabled(true); findViewById(R.id.editAttrName).setEnabled(true); findViewById(R.id.editAttrValue).setEnabled(true); + findViewById(R.id.changePasswordButton).setEnabled(true); + findViewById(R.id.changeDetailsButton).setEnabled(true); + findViewById(R.id.forgotPassword).setEnabled(true); } }); } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 984e70a..0cb6456 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -24,7 +24,7 @@