Skip to content

Commit 1f146d0

Browse files
authored
Add native auth to MSAL test app (#2001)
### For MSAL team: In order to let the native auth team execute (manual) release tests, an application is needed that supports the various use flows that are part of the release tests. Changes: - The existing MSAL test app is extended with a Native Auth section, which is accessed from the side menu. - Updated CODEOWNERS to reflect native auth ownership of the newly added classes. ### For native auth team: Changes compared to previous versions of this application: - Sign up attributes are no longer hardcoded to `country` and `city`, but taken dynamically from the UI (through new key and value text fields). - AttributesRequired` state will navigate to the new, generic AttributesFragment. Logs need to be checked for details about which attributes are required, and thus which keys need to be supplied. - `CodeFragment` displays API's `channel`, `sentTo` and `codeLength` fields, which can now be used for validation for correct behaviour. Note: This application is not in a state where it can be used as a CI-generated artefact by the native auth team. Developers using this application will need to change the config JSON file and update it to one of several tenant configurations, recompile and run it. Support for native auth in the Labs environment is needed to make this application usable as a CI-generated artefact. Once Labs support is added, the native auth screens will need config selection UI, similar to the Fragment dedicated to testing `acquireToken()`.
1 parent aad08a3 commit 1f146d0

35 files changed

+3234
-2
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
msal/src/main/java/com/microsoft/identity/nativeauth/ @AzureAD/NativeAuthTeam
1515
msal/src/test/java/com/microsoft/identity/nativeauth/ @AzureAD/NativeAuthTeam
1616
msal/src/androidTest/java/com/microsoft/identity/nativeauth/ @AzureAD/NativeAuthTeam
17+
msal/testapps/testapp/src/main/java/com/microsoft/identity/client/testapp/nativeauth @AzureAD/NativeAuthTeam
1718

1819
# If you are interested in reviewing or getting notified of changes in a particular area
1920
# Please add your alias against that specific path below

testapps/testapp/build.gradle

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@
2525

2626
apply plugin: 'com.android.application'
2727

28-
def msalVersion = "5.0.0"
28+
apply plugin: 'kotlin-android'
29+
30+
apply plugin: 'kotlin-android-extensions'
31+
32+
def msalVersion = "5.+"
2933

3034
if (project.hasProperty("distMsalVersion")) {
3135
msalVersion = distMsalVersion
@@ -83,6 +87,9 @@ android {
8387
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
8488
}
8589
}
90+
buildFeatures {
91+
viewBinding true
92+
}
8693
lintOptions {
8794
abortOnError false
8895
}
@@ -111,6 +118,8 @@ dependencies {
111118
localImplementation project(':msal')
112119
distImplementation "com.microsoft.identity.client:msal:${msalVersion}"
113120
implementation "com.google.code.gson:gson:$rootProject.ext.gsonVersion"
121+
implementation "androidx.constraintlayout:constraintlayout:$rootProject.ext.constraintLayoutVersion"
122+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$rootProject.ext.kotlinXCoroutinesVersion"
114123
implementation "androidx.appcompat:appcompat:$rootProject.ext.appCompatVersion"
115124
implementation "androidx.legacy:legacy-support-v4:$rootProject.ext.legacySupportV4Version"
116125
implementation "com.google.android.material:material:$rootProject.ext.materialVersion"

testapps/testapp/src/main/java/com/microsoft/identity/client/testapp/Constants.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,12 @@ public enum AuthScheme {
113113
BEARER,
114114
POP
115115
}
116+
117+
/**
118+
* Constants used in native auth flows.
119+
*/
120+
public static final String STATE = "state";
121+
public static final String CODE_LENGTH = "code_length";
122+
public static final String SENT_TO = "sent_to";
123+
public static final String CHANNEL = "channel";
116124
}

testapps/testapp/src/main/java/com/microsoft/identity/client/testapp/MainActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ public boolean onNavigationItemSelected(final MenuItem item) {
208208
return false;
209209
}
210210
fragment = new AcquireTokenFragment();
211+
} else if ( menuItemId == R.id.nav_native) {
212+
if (getCurrentFragment() instanceof NativeAuthFragment){
213+
return false;
214+
}
215+
fragment = new NativeAuthFragment();
211216
} else if (menuItemId == R.id.nav_result) {
212217
if (getCurrentFragment() instanceof ResultFragment){
213218
return false;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// All rights reserved.
3+
//
4+
// This code is licensed under the MIT License.
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files(the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions :
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
// THE SOFTWARE.
23+
package com.microsoft.identity.client.testapp
24+
25+
import android.os.Bundle
26+
import android.view.LayoutInflater
27+
import android.view.View
28+
import android.view.ViewGroup
29+
import androidx.appcompat.app.AppCompatActivity
30+
import androidx.fragment.app.Fragment
31+
import com.google.android.material.bottomnavigation.BottomNavigationView
32+
import com.microsoft.identity.client.testapp.nativeauth.AuthClient
33+
import com.microsoft.identity.client.testapp.nativeauth.EmailAttributeSignUpFragment
34+
import com.microsoft.identity.client.testapp.nativeauth.EmailPasswordSignInSignUpFragment
35+
import com.microsoft.identity.client.testapp.nativeauth.EmailSignInSignUpFragment
36+
import com.microsoft.identity.client.testapp.nativeauth.PasswordResetFragment
37+
38+
/**
39+
* Fragment used for starting various native auth flows.
40+
*/
41+
class NativeAuthFragment : Fragment() {
42+
companion object {
43+
private val TAG = MainActivity::class.java.simpleName
44+
}
45+
46+
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
47+
val view = inflater.inflate(R.layout.fragment_native, container, false)
48+
49+
AuthClient.initialize(requireContext())
50+
51+
val emailSignInSignUpFragment = EmailSignInSignUpFragment()
52+
val emailPasswordSignInSignUpFragment = EmailPasswordSignInSignUpFragment()
53+
val emailAttributeSignUpFragment = EmailAttributeSignUpFragment()
54+
val passwordResetFragment = PasswordResetFragment()
55+
56+
val bottomNavigationView = view.findViewById<BottomNavigationView>(R.id.bottom_navigation_view)
57+
58+
setFragment(emailSignInSignUpFragment, R.string.title_email_oob_sisu)
59+
60+
bottomNavigationView.setOnNavigationItemSelectedListener {
61+
when (it.itemId) {
62+
R.id.email_oob_sisu -> setFragment(emailSignInSignUpFragment, R.string.title_email_oob_sisu)
63+
R.id.email_password_sisu -> setFragment(emailPasswordSignInSignUpFragment, R.string.title_email_password_sisu)
64+
R.id.email_attribute_sisu -> setFragment(emailAttributeSignUpFragment, R.string.title_email_attribute_oob_sisu)
65+
R.id.email_oob_sspr -> setFragment(passwordResetFragment, R.string.title_email_oob_sspr)
66+
}
67+
true
68+
}
69+
70+
return view
71+
}
72+
73+
private fun setFragment(fragment: Fragment, title: Int) {
74+
(this.context as AppCompatActivity).supportFragmentManager.beginTransaction().apply {
75+
replace(R.id.scenario_fragment, fragment)
76+
commit()
77+
}
78+
}
79+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// All rights reserved.
3+
//
4+
// This code is licensed under the MIT License.
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files(the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions :
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
// THE SOFTWARE.
23+
package com.microsoft.identity.client.testapp.nativeauth
24+
25+
import android.app.Application
26+
import android.content.Context
27+
import com.microsoft.identity.client.PublicClientApplication
28+
import com.microsoft.identity.client.testapp.R
29+
import com.microsoft.identity.nativeauth.INativeAuthPublicClientApplication
30+
31+
/**
32+
* Utility for managing MSAL SDK instance INativeAuthPublicClientApplication.
33+
*/
34+
object AuthClient : Application() {
35+
private lateinit var authClient: INativeAuthPublicClientApplication
36+
37+
fun getAuthClient(): INativeAuthPublicClientApplication {
38+
return authClient
39+
}
40+
41+
fun initialize(context: Context) {
42+
authClient = PublicClientApplication.createNativeAuthPublicClientApplication(
43+
context,
44+
R.raw.msal_config_native
45+
)
46+
}
47+
}

0 commit comments

Comments
 (0)