diff --git a/app/build.gradle b/app/build.gradle
index c840f0f..d6efb79 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,31 +1,48 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 27
- buildToolsVersion "28.0.3"
+ compileSdkVersion 28
defaultConfig {
applicationId "com.azuresamples.msalandroidapp"
minSdkVersion 21
- targetSdkVersion 27
+ targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
+ debug{
+
+ }
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ flavorDimensions "main"
+ productFlavors {
+ local {
+ applicationIdSuffix ".local"
+ versionNameSuffix "-local"
+ resValue("string", "application_name", "msal-local")
+ }
+ dist {
+ applicationIdSuffix ".dist"
+ versionNameSuffix "-dist"
+ resValue("string", "application_name", "msal-dist")
+ }
+ }
}
dependencies {
+ implementation project(':msal')
implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "com.android.support:appcompat-v7:28.0.0"
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.android.volley:volley:1.1.1'
- implementation 'com.microsoft.identity.client:msal:0.3.+'
+
testImplementation 'junit:junit:4.12'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9060b41..518ab50 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -30,8 +30,8 @@
+ android:host= "com.azuresamples.msalandroidapp"
+ android:path= "/hk4Z0/bBPPUC8ll5PHC83WbD65k=" />
diff --git a/app/src/main/java/com/azuresamples/msalandroidapp/MainActivity.java b/app/src/main/java/com/azuresamples/msalandroidapp/MainActivity.java
index 8a3e00c..d9cff61 100644
--- a/app/src/main/java/com/azuresamples/msalandroidapp/MainActivity.java
+++ b/app/src/main/java/com/azuresamples/msalandroidapp/MainActivity.java
@@ -1,28 +1,44 @@
package com.azuresamples.msalandroidapp;
import android.app.Activity;
-import android.content.Intent;
-import android.support.v7.app.AppCompatActivity;
+import android.content.Context;
+import android.os.AsyncTask;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.volley.*;
+
+import com.android.volley.DefaultRetryPolicy;
+import com.android.volley.Request;
+import com.android.volley.RequestQueue;
+import com.android.volley.Response;
+import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
+import com.microsoft.identity.client.AuthenticationCallback;
+import com.microsoft.identity.client.IAccount;
+import com.microsoft.identity.client.IAuthenticationResult;
+import com.microsoft.identity.client.ISingleAccountPublicClientApplication;
+import com.microsoft.identity.client.PublicClientApplication;
+import com.microsoft.identity.client.exception.MsalClientException;
+import com.microsoft.identity.client.exception.MsalException;
+import com.microsoft.identity.client.exception.MsalServiceException;
+import com.microsoft.identity.client.exception.MsalUiRequiredException;
+
import org.json.JSONObject;
+
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import com.microsoft.identity.client.*;
-import com.microsoft.identity.client.exception.*;
public class MainActivity extends AppCompatActivity {
/* Azure AD v2 Configs */
- final static String[] SCOPES = {"https://graph.microsoft.com/User.Read"};
+ final static String[] SCOPES = {"User.Read"};
final static String MSGRAPH_URL = "https://graph.microsoft.com/v1.0/me";
/* UI & Debugging Variables */
@@ -31,7 +47,7 @@ public class MainActivity extends AppCompatActivity {
Button signOutButton;
/* Azure AD Variables */
- private PublicClientApplication sampleApp;
+ private ISingleAccountPublicClientApplication sampleApp;
private IAuthenticationResult authResult;
@Override
@@ -54,29 +70,66 @@ public void onClick(View v) {
}
});
- /* Configure your sample app and save state for this activity */
- sampleApp = new PublicClientApplication(
- this.getApplicationContext(),
- R.raw.auth_config);
+ new CreateSingleAccountPublicClientApplication().execute(this.getApplicationContext());
+ }
- /* Attempt to get a user and acquireTokenSilent
- * If this fails we do an interactive request
- */
- sampleApp.getAccounts(new PublicClientApplication.AccountsLoadedCallback() {
+ //
+
+ private class CreateSingleAccountPublicClientApplication extends AsyncTask {
+
+ @Override
+ protected ISingleAccountPublicClientApplication doInBackground(Context... contexts) {
+
+ ISingleAccountPublicClientApplication app = null;
+ try {
+ app = PublicClientApplication.createSingleAccountPublicClientApplication(contexts[0], R.raw.auth_config);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (MsalException e) {
+ e.printStackTrace();
+ }
+ return app;
+ }
+
+ @Override
+ protected void onPostExecute(ISingleAccountPublicClientApplication app){
+ sampleApp = app;
+ checkForAccountAndSignInSilently();
+ }
+
+ }
+
+ private void checkForAccountAndSignInSilently(){
+
+ sampleApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
@Override
- public void onAccountsLoaded(final List accounts) {
+ public void onAccountLoaded(@Nullable IAccount activeAccount) {
+ if(activeAccount != null) {
+ getSilentToken();
+ }
+ }
- if (!accounts.isEmpty()) {
- /* This sample doesn't support multi-account scenarios, use the first account */
- sampleApp.acquireTokenSilentAsync(SCOPES, accounts.get(0), getAuthSilentCallback());
- } else {
- /* No accounts or >1 account */
+ @Override
+ public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) {
+ if(currentAccount != null) {
+ getSilentToken();
}
}
+
+ @Override
+ public void onError(@NonNull Exception exception) {
+
+ }
});
}
+ private void getSilentToken(){
+
+ sampleApp.acquireTokenSilentAsync(SCOPES, getDefaultAuthority(), false, getAuthSilentCallback());
+
+ }
+
//
// Core Identity methods used by MSAL
// ==================================
@@ -89,7 +142,23 @@ public void onAccountsLoaded(final List accounts) {
* Callback will call Graph api w/ access token & update UI
*/
private void onCallGraphClicked() {
- sampleApp.acquireToken(getActivity(), SCOPES, getAuthInteractiveCallback());
+ //sampleApp.acquireToken(getActivity(), SCOPES, getAuthInteractiveCallback());
+ sampleApp.signIn(getActivity(), SCOPES, new AuthenticationCallback() {
+ @Override
+ public void onSuccess(IAuthenticationResult authenticationResult) {
+ getSilentToken();
+ }
+
+ @Override
+ public void onError(MsalException exception) {
+
+ }
+
+ @Override
+ public void onCancel() {
+
+ }
+ });
}
/* Clears an account's tokens from the cache.
@@ -97,36 +166,49 @@ private void onCallGraphClicked() {
* User will get interactive SSO if trying to sign back-in.
*/
private void onSignOutClicked() {
+
+
/* Attempt to get a user and acquireTokenSilent
* If this fails we do an interactive request
*/
- sampleApp.getAccounts(new PublicClientApplication.AccountsLoadedCallback() {
+ sampleApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
@Override
- public void onAccountsLoaded(final List accounts) {
-
- if (accounts.isEmpty()) {
- /* No accounts to remove */
-
- } else {
- for (final IAccount account : accounts) {
- sampleApp.removeAccount(
- account,
- new PublicClientApplication.AccountsRemovedCallback() {
- @Override
- public void onAccountsRemoved(Boolean isSuccess) {
- if (isSuccess) {
- /* successfully removed account */
- } else {
- /* failed to remove account */
- }
- }
- });
- }
+ public void onAccountLoaded(@Nullable IAccount activeAccount) {
+ if(activeAccount != null){
+ signOut();
}
+ }
+ @Override
+ public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) {
+ if(currentAccount != null){
+ signOut();
+ }
+ }
+
+ @Override
+ public void onError(@NonNull Exception exception) {
+
+ }
+ });
+
+
+ }
+
+ private void signOut(){
+
+ sampleApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() {
+ @Override
+ public void onSignOut() {
updateSignedOutUI();
}
+
+ @Override
+ public void onError(@NonNull MsalException exception) {
+
+ }
});
+
}
/* Use Volley to make an HTTP request to the /me endpoint from MS Graph using an access token */
@@ -196,7 +278,7 @@ private void updateSuccessUI() {
signOutButton.setVisibility(View.VISIBLE);
findViewById(R.id.welcome).setVisibility(View.VISIBLE);
((TextView) findViewById(R.id.welcome)).setText("Welcome, " +
- authResult.getAccount().getUsername());
+ authResult.getAccount().getClaims().get("preferred_username"));
findViewById(R.id.graphData).setVisibility(View.VISIBLE);
}
@@ -224,6 +306,14 @@ public Activity getActivity() {
return this;
}
+ private String getDefaultAuthority(){
+ if(sampleApp != null){
+ return sampleApp.getConfiguration().getDefaultAuthority().getAuthorityURL().toString();
+ }else{
+ return "";
+ }
+ }
+
/* Callback used in for silent acquireToken calls.
* Looks if tokens are in the cache (refreshes if necessary and if we don't forceRefresh)
* else errors that we need to do an interactive request.
@@ -278,7 +368,7 @@ private AuthenticationCallback getAuthInteractiveCallback() {
public void onSuccess(IAuthenticationResult authenticationResult) {
/* Successfully got a token, call graph now */
Log.d(TAG, "Successfully authenticated");
- Log.d(TAG, "ID Token: " + authenticationResult.getIdToken());
+ Log.d(TAG, "ID Token: " + authenticationResult.getAccount().getClaims().get("id_token"));
/* Store the auth result */
authResult = authenticationResult;
diff --git a/app/src/main/res/raw/auth_config.json b/app/src/main/res/raw/auth_config.json
index 1e4339f..18408f2 100644
--- a/app/src/main/res/raw/auth_config.json
+++ b/app/src/main/res/raw/auth_config.json
@@ -1,7 +1,8 @@
{
- "client_id" : "Register your app at https://aka.ms/MobileAppReg",
+ "client_id" : "24be1a19-6d3b-49bc-940e-6e5ead8f4fbf",
"authorization_user_agent" : "DEFAULT",
- "redirect_uri" : "Register your app at https://aka.ms/MobileAppReg",
+ "redirect_uri" : "msauth://com.azuresamples.msalandroidapp/hk4Z0%2FbBPPUC8ll5PHC83WbD65k%3D",
+ "account_mode" : "SINGLE",
"authorities" : [
{
"type": "AAD",