Włączanie uwierzytelniania we własnej aplikacji systemu Android przy użyciu usługi Azure AD B2C

W tym artykule pokazano, jak dodać uwierzytelnianie usługi Azure Active Directory B2C (Azure AD B2C) do własnej aplikacji mobilnej systemu Android.

Użyj tego artykułu z tematem Konfigurowanie uwierzytelniania w przykładowej aplikacji systemu Android przy użyciu usługi Azure AD B2C, zastępując przykładową aplikację systemu Android własną aplikacją systemu Android. Po wykonaniu instrukcji w tym artykule aplikacja zaakceptuje logowania za pośrednictwem usługi Azure AD B2C.

Wymagania wstępne

Zapoznaj się z instrukcjami dotyczącymi wymagań wstępnych i integracji w temacie Konfigurowanie uwierzytelniania w przykładowej aplikacji systemu Android przy użyciu usługi Azure AD B2C.

Tworzenie projektu aplikacji systemu Android

Jeśli nie masz jeszcze aplikacji dla systemu Android, skonfiguruj nowy projekt, wykonując następujące czynności:

  1. W programie Android Studio wybierz pozycję Start a new Android Studio project (Utwórz nowy projekt programu Android Studio).
  2. Wybierz pozycję Podstawowe działanie, a następnie wybierz pozycję Dalej.
  3. Nadaj nazwę aplikacji.
  4. Zapisz nazwę pakietu. Wprowadź go później w witrynie Azure Portal.
  5. Zmień język z Kotlin na Java.
  6. Ustaw minimalny poziom interfejsu API na interfejs API 19 lub nowszy, a następnie wybierz pozycję Zakończ.
  7. W widoku projektu wybierz pozycję Project na liście rozwijanej, aby wyświetlić pliki projektów źródłowych i nieźródle, otworzyć plik app/build.gradle, a następnie ustawić wartość targetSdkVersion na 28.

Krok 1. Instalowanie zależności

W oknie projektu programu Android Studio przejdź do pozycji app>build.gradle, a następnie dodaj następujące polecenie:

apply plugin: 'com.android.application'

allprojects {
    repositories {
    mavenCentral()
    google()
    mavenLocal()
    maven {
        url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
    }
    maven {
        name "vsts-maven-adal-android"
        url "https://identitydivision.pkgs.visualstudio.com/_packaging/AndroidADAL/maven/v1"
        credentials {
            username System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") : project.findProperty("vstsUsername")
            password System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") : project.findProperty("vstsMavenAccessToken")
        }
    }
    jcenter()
    }
}
dependencies{
    implementation 'com.microsoft.identity.client:msal:2.+'
    }
packagingOptions{
    exclude("META-INF/jersey-module-version")
}

Krok 2. Dodawanie składników uwierzytelniania

Przykładowy kod składa się z następujących składników. Dodaj te składniki z przykładowej aplikacji systemu Android do własnej aplikacji.

Składnik Type Lokalizacja źródłowa opis
B2CUser Klasa KotlinJava Reprezentuje użytkownika B2C. Ta klasa umożliwia użytkownikom logowanie się przy użyciu wielu zasad.
B2CModeFragment Fragment, klasa KotlinJava Fragment reprezentuje modułową część logowania za pomocą interfejsu użytkownika usługi Azure AD B2C w ramach głównej aktywności. Ten fragment zawiera większość kodu uwierzytelniania.
fragment_b2c_mode.xml Układ fragmentu KotlinJava Definiuje strukturę interfejsu użytkownika dla składnika fragmentu B2CModeFragment.
B2CConfiguration Klasa KotlinJava Plik konfiguracji zawiera informacje o dostawcy tożsamości usługi Azure AD B2C. Aplikacja mobilna używa tych informacji do ustanowienia relacji zaufania z usługą Azure AD B2C, logowania użytkowników i wylogowywanie ich, uzyskiwanie tokenów i ich weryfikowanie. Aby uzyskać więcej ustawień konfiguracji, zobacz plik auth_config_b2c.json.
auth_config_b2c.json Plik JSON KotlinJava Plik konfiguracji zawiera informacje o dostawcy tożsamości usługi Azure AD B2C. Aplikacja mobilna używa tych informacji do ustanowienia relacji zaufania z usługą Azure AD B2C, logowania użytkowników i wylogowywanie ich, uzyskiwanie tokenów i ich weryfikowanie. Aby uzyskać więcej ustawień konfiguracji, zobacz klasę B2CConfiguration.

Krok 3. Konfigurowanie aplikacji dla systemu Android

Po dodaniu składników uwierzytelniania skonfiguruj aplikację systemu Android przy użyciu ustawień usługi Azure AD B2C. Ustawienia dostawcy tożsamości usługi Azure AD B2C są konfigurowane w pliku auth_config_b2c.json i klasie B2CConfiguration.

Aby uzyskać wskazówki, zobacz Konfigurowanie przykładowej aplikacji mobilnej.

Krok 4. Ustawianie identyfikatora URI przekierowania

Skonfiguruj miejsce, w którym aplikacja nasłuchuje odpowiedzi tokenu usługi Azure AD B2C.

  1. Wygeneruj nowy skrót sygnatury programistycznej. Spowoduje to zmianę dla każdego środowiska deweloperskiego.

    System Windows:

    keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
    

    Dla iOS:

    keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
    

    W środowisku produkcyjnym użyj następującego polecenia:

    keytool -exportcert -alias SIGNATURE_ALIAS -keystore PATH_TO_KEYSTORE | openssl sha1 -binary | openssl base64
    

    Aby uzyskać więcej pomocy dotyczącej podpisywania aplikacji, zobacz Podpisywanie aplikacji dla systemu Android.

  2. Wybierz pozycję app>src>main>AndroidManifest.xml, a następnie dodaj następujące BrowserTabActivity działanie do treści aplikacji:

    <!--Intent filter to capture System Browser or Authenticator calling back to our app after sign-in-->
    <activity
        android:name="com.microsoft.identity.client.BrowserTabActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="msauth"
                android:host="Package_Name"
                android:path="/Signature_Hash" />
        </intent-filter>
    </activity>
    
  3. Zastąp Signature_Hash ciąg wygenerowaną wartością skrótu.

  4. Zastąp Package_Name ciąg nazwą pakietu systemu Android.

Aby zaktualizować rejestrację aplikacji mobilnej przy użyciu identyfikatora URI przekierowania aplikacji, wykonaj następujące czynności:

  1. Zaloguj się w witrynie Azure Portal.
  2. Jeśli masz dostęp do wielu dzierżaw, wybierz ikonę Ustawienia w górnym menu, aby przełączyć się do dzierżawy usługi Azure AD B2C z menu Katalogi i subskrypcje.
  3. Wyszukaj i wybierz Azure AD B2C.
  4. Wybierz Rejestracje aplikacji, a następnie wybierz aplikację zarejestrowaną w kroku 2.3: Rejestrowanie aplikacji mobilnej.
  5. Wybierz Uwierzytelnianie.
  6. W obszarze Android wybierz pozycję Dodaj identyfikator URI.
  7. Wprowadź nazwę pakietu i skrót podpisu.
  8. Wybierz pozycję Zapisz.

Identyfikator URI przekierowania i BrowserTabActivity działanie powinny wyglądać podobnie do następującego przykładu:

Adres URL przekierowania przykładowego systemu Android wygląda następująco:

msauth://com.azuresamples.msalandroidkotlinapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D

Filtr intencji używa tego samego wzorca, jak pokazano w poniższym fragmencie kodu XML:

<activity android:name="com.microsoft.identity.client.BrowserTabActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="com.azuresamples.msalandroidkotlinapp"
            android:path="/1wIqXSqBj7w+h11ZifsnqwgyKrY="
            android:scheme="msauth" />
    </intent-filter>
</activity>

Krok 5. Dostosowywanie bloków konstrukcyjnych kodu

W tej sekcji opisano bloki konstrukcyjne kodu, które umożliwiają uwierzytelnianie aplikacji systemu Android. W poniższej tabeli wymieniono metody B2CModeFragment i sposób dostosowywania kodu.

Krok 5.1. Tworzenie wystąpienia publicznej aplikacji klienckiej

Publiczne aplikacje klienckie nie są zaufane, aby bezpiecznie przechowywać wpisy tajne aplikacji i nie mają wpisów tajnych klienta. W obszarze OnCreate lub onCreateView utwórz wystąpienie biblioteki MSAL przy użyciu obiektu aplikacji klienckiej z wieloma kontami.

Klasa MultipleAccountPublicClientApplication służy do tworzenia aplikacji opartych na protokole MSAL, które umożliwiają logowanie wielu kont jednocześnie. Klasa umożliwia logowanie przy użyciu wielu przepływów użytkowników usługi Azure AD B2C lub zasad niestandardowych. Na przykład użytkownicy logują się przy użyciu przepływu użytkownika rejestracji lub logowania , a później uruchamiają przepływ użytkownika profilu edycji.

Poniższy fragment kodu pokazuje, jak zainicjować bibliotekę MSAL przy auth_config_b2c.json użyciu pliku JSON konfiguracji.

PublicClientApplication.createMultipleAccountPublicClientApplication(context!!,
    R.raw.auth_config_b2c,
    object : IMultipleAccountApplicationCreatedListener {
        override fun onCreated(application: IMultipleAccountPublicClientApplication) {
            // Set the MultipleAccountPublicClientApplication to the class member b2cApp
            b2cApp = application
            // Load the account (if there is any)
            loadAccounts()
        }

        override fun onError(exception: MsalException) {
            // Error handling
            displayError(exception)
        }
    })

Krok 5.2. Ładowanie kont

Gdy aplikacja pojawi się na pierwszym planie, aplikacja ładuje istniejące konto, aby określić, czy użytkownicy są zalogowani. Użyj tej metody, aby zaktualizować interfejs użytkownika przy użyciu stanu uwierzytelniania. Możesz na przykład włączyć lub wyłączyć przycisk wylogowywanie.

Poniższy fragment kodu przedstawia sposób ładowania kont.

private fun loadAccounts() {
    if (b2cApp == null) {
        return
    }
    b2cApp!!.getAccounts(object : LoadAccountsCallback {
        override fun onTaskCompleted(result: List<IAccount>) {
            users = B2CUser.getB2CUsersFromAccountList(result)
            updateUI(users)
        }
    
        override fun onError(exception: MsalException) {
            displayError(exception)
        }
    })
    }

Krok 5.3. Uruchamianie interakcyjnego żądania autoryzacji

Interakcyjne żądanie autoryzacji to przepływ, w którym użytkownicy są monitowani o zarejestrowanie się lub zalogowanie. Metoda initializeUI konfiguruje runUserFlowButton zdarzenie kliknięcia. Po wybraniu przycisku Uruchom przepływ użytkownika aplikacja przeniesie ich do usługi Azure AD B2C, aby ukończyć przepływ logowania.

Metoda runUserFlowButton.setOnClickListener przygotowuje AcquireTokenParameters obiekt z odpowiednimi danymi dotyczącymi żądania autoryzacji. Następnie acquireToken metoda monituje użytkowników o ukończenie przepływu rejestracji lub logowania.

Poniższy fragment kodu przedstawia sposób uruchamiania interakcyjnego żądania autoryzacji:

val parameters = AcquireTokenParameters.Builder()
        .startAuthorizationFromActivity(activity)
        .fromAuthority(getAuthorityFromPolicyName(policy_list.getSelectedItem().toString()))
        .withScopes(B2CConfiguration.scopes)
        .withPrompt(Prompt.LOGIN)
        .withCallback(authInteractiveCallback)
        .build()

b2cApp!!.acquireToken(parameters)

Krok 5.4. Tworzenie wywołania zwrotnego żądania autoryzacji interaktywnej

Po zakończeniu przepływu autoryzacji przez użytkowników, niezależnie od tego, czy pomyślnie, czy bez powodzenia, wynik zostanie zwrócony do metody wywołania zwrotnego getAuthInteractiveCallback() .

Metoda wywołania zwrotnego przekazuje AuthenticationResult obiekt lub komunikat o błędzie w MsalException obiekcie. Użyj tej metody, aby:

  • Zaktualizuj interfejs użytkownika aplikacji mobilnej przy użyciu informacji po zakończeniu logowania.
  • Załaduj ponownie obiekt kont.
  • Wywoływanie usługi internetowego interfejsu API przy użyciu tokenu dostępu.
  • Obsługa błędów uwierzytelniania.

Poniższy fragment kodu przedstawia użycie wywołania zwrotnego uwierzytelniania interakcyjnego.

private val authInteractiveCallback: AuthenticationCallback
    private get() = object : AuthenticationCallback {
        override fun onSuccess(authenticationResult: IAuthenticationResult) {
            /* Successfully got a token, use it to call a protected resource; web API  */
            Log.d(TAG, "Successfully authenticated")

            /* display result info */
            displayResult(authenticationResult)

            /* Reload account asynchronously to get the up-to-date list. */
            loadAccounts()
        }

        override fun onError(exception: MsalException) {
            val B2C_PASSWORD_CHANGE = "AADB2C90118"
            if (exception.message!!.contains(B2C_PASSWORD_CHANGE)) {
                txt_log!!.text = """
                    Users click the 'Forgot Password' link in a sign-up or sign-in user flow.
                    Your application needs to handle this error code by running a specific user flow that resets the password.
                    """.trimIndent()
                return
            }

            /* Failed to acquireToken */Log.d(TAG, "Authentication failed: $exception")
            displayError(exception)
            if (exception is MsalClientException) {
                /* Exception inside MSAL, more info inside MsalError.java */
            } else if (exception is MsalServiceException) {
                /* Exception when communicating with the STS, likely config issue */
            }
        }

        override fun onCancel() {
            /* User canceled the authentication */
            Log.d(TAG, "User cancelled login.")
        }
    }

Krok 6. Wywoływanie internetowego interfejsu API

Aby wywołać internetowy interfejs API autoryzacji opartej na tokenach, aplikacja musi mieć prawidłowy token dostępu. Aplikacja wykonuje następujące czynności:

  1. Uzyskuje token dostępu z wymaganymi uprawnieniami (zakresami) dla internetowego punktu końcowego interfejsu API.
  2. Przekazuje token dostępu jako token elementu nośnego w nagłówku autoryzacji żądania HTTP przy użyciu następującego formatu:
Authorization: Bearer <access-token>

Gdy użytkownicy logują się interaktywnie, aplikacja uzyskuje token dostępu w metodzie wywołania zwrotnego getAuthInteractiveCallback . W przypadku kolejnych wywołań internetowego interfejsu API użyj procedury uzyskiwania tokenu dyskretnego zgodnie z opisem w tej sekcji.

Przed wywołaniem internetowego interfejsu API wywołaj metodę acquireTokenSilentAsync z odpowiednimi zakresami dla internetowego punktu końcowego interfejsu API. Biblioteka biblioteki MSAL wykonuje następujące czynności:

  1. Próbuje pobrać token dostępu z żądanymi zakresami z pamięci podręcznej tokenu. Jeśli token jest obecny, zostanie zwrócony token.
  2. Jeśli token nie jest obecny w pamięci podręcznej tokenów, biblioteka MSAL próbuje użyć tokenu odświeżania w celu uzyskania nowego tokenu.
  3. Jeśli token odświeżania nie istnieje lub wygasł, zwracany jest wyjątek. Zalecamy wyświetlenie monitu użytkownika o zalogowanie się interaktywnie.

Poniższy fragment kodu przedstawia sposób uzyskiwania tokenu dostępu:

Kliknięcie acquireTokenSilentButton przycisku zdarzenie uzyskuje token dostępu z podanymi zakresami.

btn_acquireTokenSilently.setOnClickListener(View.OnClickListener {
    if (b2cApp == null) {
        return@OnClickListener
    }
    val selectedUser = users!![user_list.getSelectedItemPosition()]
    selectedUser.acquireTokenSilentAsync(b2cApp!!,
            policy_list.getSelectedItem().toString(),
            B2CConfiguration.scopes,
            authSilentCallback)
})

Metoda authSilentCallback wywołania zwrotnego zwraca token dostępu i wywołuje internetowy interfejs API:

private val authSilentCallback: SilentAuthenticationCallback
    private get() = object : SilentAuthenticationCallback {
        override fun onSuccess(authenticationResult: IAuthenticationResult) {
            Log.d(TAG, "Successfully authenticated")

            /* Call your web API here*/
            callWebAPI(authenticationResult)
        }

        override fun onError(exception: MsalException) {
            /* Failed to acquireToken */
            Log.d(TAG, "Authentication failed: $exception")
            displayError(exception)
            if (exception is MsalClientException) {
                /* Exception inside MSAL, more info inside MsalError.java */
            } else if (exception is MsalServiceException) {
                /* Exception when communicating with the STS, likely config issue */
            } else if (exception is MsalUiRequiredException) {
                /* Tokens expired or no session, retry with interactive */
            }
        }
    }

W poniższym przykładzie pokazano, jak wywołać chroniony internetowy interfejs API przy użyciu tokenu elementu nośnego:

@Throws(java.lang.Exception::class)
private fun callWebAPI(authenticationResult: IAuthenticationResult) {
    val accessToken = authenticationResult.accessToken
    val thread = Thread {
        try {
            val url = URL("https://your-app-service.azurewebsites.net/helo")
            val conn = url.openConnection() as HttpsURLConnection
            conn.setRequestProperty("Accept", "application/json")
            
            // Set the bearer token
            conn.setRequestProperty("Authorization", "Bearer $accessToken")
            if (conn.responseCode == HttpURLConnection.HTTP_OK) {
                val br = BufferedReader(InputStreamReader(conn.inputStream))
                var strCurrentLine: String?
                while (br.readLine().also { strCurrentLine = it } != null) {
                    Log.d(TAG, strCurrentLine)
                }
            }
            conn.disconnect()
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
    thread.start()
}

Dodawanie uprawnień do wykonywania operacji sieciowych

Aby wykonać operacje sieciowe w aplikacji, dodaj następujące uprawnienie do manifestu. Aby uzyskać więcej informacji, zobacz Połączenie do sieci.

<uses-permission android:name="android.permission.INTERNET"/>

Następne kroki

Instrukcje: