Aktivera autentisering i din egen Android-app med hjälp av Azure AD B2C

Den här artikeln visar hur du lägger till Azure Active Directory B2C-autentisering (Azure AD B2C) i ditt eget Android-mobilprogram.

Använd den här artikeln med Konfigurera autentisering i en Android-exempelapp med hjälp av Azure AD B2C och ersätt Android-exempelappen med din egen Android-app. När du har slutfört anvisningarna i den här artikeln godkänner programmet inloggningar via Azure AD B2C.

Förutsättningar

Läs igenom förutsättningarna och integreringsinstruktionerna i Konfigurera autentisering i en Android-exempelapp med hjälp av Azure AD B2C.

Skapa ett Android-appprojekt

Om du inte redan har ett Android-program konfigurerar du ett nytt projekt genom att göra följande:

  1. Välj Start a new Android Studio project (Starta ett nytt Android Studio-projekt) i Android Studio.
  2. Välj Grundläggande aktivitet och välj sedan Nästa.
  3. Namnge ditt program.
  4. Spara paketnamnet. Du anger det senare i Azure-portalen.
  5. Ändra språket från Kotlin till Java.
  6. Ange den lägsta API-nivån till API 19 eller senare och välj sedan Slutför.
  7. I projektvyn väljer du Projekt i listrutan för att visa käll- och icke-källprojektfiler, öppna app/build.gradle och ange sedan targetSdkVersion till 28.

Steg 1: Installera beroendena

I Android Studio-projektfönstret går du till app>build.gradle och lägger sedan till följande:

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")
}

Steg 2: Lägg till autentiseringskomponenterna

Exempelkoden består av följande komponenter. Lägg till dessa komponenter från Android-exempelappen i din egen app.

Komponent Typ Source beskrivning
B2CUser Klass Kotlin Java Representerar en B2C-användare. Med den här klassen kan användare logga in med flera principer.
B2CModeFragment Fragmentklass Kotlin Java Ett fragment representerar en modulär del av inloggningen med Azure AD B2C-användargränssnittet i huvudaktiviteten. Det här fragmentet innehåller det mesta av autentiseringskoden.
fragment_b2c_mode.xml Fragmentlayout Kotlin Java Definierar strukturen för ett användargränssnitt för fragmentkomponenten B2CModeFragment.
B2CConfiguration Klass Kotlin Java En konfigurationsfil innehåller information om din Azure AD B2C-identitetsprovider. Mobilappen använder den här informationen för att upprätta en förtroenderelation med Azure AD B2C, logga in och ut användare, hämta token och verifiera dem. Mer konfigurationsinställningar finns i filen auth_config_b2c.json.
auth_config_b2c.json JSON-fil Kotlin Java En konfigurationsfil innehåller information om din Azure AD B2C-identitetsprovider. Mobilappen använder den här informationen för att upprätta en förtroenderelation med Azure AD B2C, logga in och ut användare, hämta token och verifiera dem. Mer konfigurationsinställningar finns i klassen B2CConfiguration.

Steg 3: Konfigurera din Android-app

När du har lagt till autentiseringskomponenterna konfigurerar du din Android-app med dina Azure AD B2C-inställningar. Inställningarna för Azure AD B2C-identitetsprovidern konfigureras i klassen auth_config_b2c.json fil och B2CConfiguration.

Vägledning finns i Konfigurera exempelmobilappen.

Steg 4: Ange omdirigerings-URI:n

Konfigurera var ditt program lyssnar på Azure AD B2C-tokensvaret.

  1. Generera en ny hash för utvecklingssignatur. Detta ändras för varje utvecklingsmiljö.

    För Windows:

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

    För iOS:

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

    Använd följande kommando för en produktionsmiljö:

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

    Mer hjälp med att signera dina appar finns i Signera din Android-app.

  2. Välj app>src>main>AndroidManifest.xml och lägg sedan till följande BrowserTabActivity aktivitet i programtexten:

    <!--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. Ersätt Signature_Hash med den hash som du genererade.

  4. Ersätt Package_Name med ditt Android-paketnamn.

Gör följande för att uppdatera mobilappregistreringen med din appomdirigerings-URI:

  1. Logga in på Azure-portalen.
  2. Om du har åtkomst till flera klienter väljer du ikonen Inställningar på den översta menyn för att växla till din Azure AD B2C-klient från menyn Kataloger + prenumerationer.
  3. Sök efter och markera Azure AD B2C.
  4. Välj Appregistreringar och välj sedan det program som du registrerade i Steg 2.3: Registrera mobilappen.
  5. Välj Autentisering.
  6. Under Android väljer du Lägg till URI.
  7. Ange paketnamnet och signaturshashen.
  8. Välj Spara.

Din omdirigerings-URI och BrowserTabActivity aktiviteten bör se ut ungefär så här:

Omdirigerings-URL:en för androidexemplet ser ut så här:

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

Avsiktsfiltret använder samma mönster som i följande XML-kodfragment:

<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>

Steg 5: Anpassa dina kodbyggstenar

I det här avsnittet beskrivs de kodbyggstenar som aktiverar autentisering för din Android-app. I följande tabell visas metoderna B2CModeFragment och hur du anpassar koden.

Steg 5.1: Instansiera ett offentligt klientprogram

Offentliga klientprogram är inte betrodda för att bevara programhemligheter på ett säkert sätt och de har inga klienthemligheter. I onCreate or onCreateView instansierar du MSAL med hjälp av det offentliga klientprogramobjektet med flera konton.

Klassen MultipleAccountPublicClientApplication används för att skapa MSAL-baserade appar som gör att flera konton kan loggas in samtidigt. Klassen tillåter inloggning med flera Azure AD B2C-användarflöden eller anpassade principer. Användare loggar till exempel in med ett användarflöde för registrering eller inloggning och senare kör de ett användarflöde för redigeringsprofil .

Följande kodfragment visar hur du initierar MSAL-biblioteket med JSON-konfigurationsfilen auth_config_b2c.json .

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)
        }
    })

Steg 5.2: Läsa in konton

När appen kommer till förgrunden läser appen in det befintliga kontot för att avgöra om användarna är inloggade. Använd den här metoden för att uppdatera användargränssnittet med autentiseringstillståndet. Du kan till exempel aktivera eller inaktivera utloggningsknappen.

Följande kodfragment visar hur du läser in kontona.

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)
        }
    })
    }

Steg 5.3: Starta en interaktiv auktoriseringsbegäran

En interaktiv auktoriseringsbegäran är ett flöde där användare uppmanas att registrera sig eller logga in. Metoden initializeUI konfigurerar klickhändelsen runUserFlowButton . När användarna väljer knappen Kör användarflöde tar appen dem till Azure AD B2C för att slutföra inloggningsflödet.

Metoden runUserFlowButton.setOnClickListener förbereder objektet AcquireTokenParameters med relevanta data om auktoriseringsbegäran. Metoden acquireToken uppmanar sedan användarna att slutföra registrerings- eller inloggningsflödet.

Följande kodfragment visar hur du startar den interaktiva auktoriseringsbegäran:

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

b2cApp!!.acquireToken(parameters)

Steg 5.4: Gör ett återanrop för interaktiv auktoriseringsbegäran

När användarna har slutfört auktoriseringsflödet, oavsett om det lyckas eller inte, returneras resultatet till getAuthInteractiveCallback() återanropsmetoden.

Motringningsmetoden skickar AuthenticationResult objektet eller ett felmeddelande i objektet MsalException . Använd den här metoden för att:

  • Uppdatera mobilappens användargränssnitt med information när inloggningen har slutförts.
  • Ladda om kontoobjektet.
  • Anropa en webb-API-tjänst med en åtkomsttoken.
  • Hantera autentiseringsfel.

Följande kodfragment visar användningen av återanrop för interaktiv autentisering.

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.")
        }
    }

Steg 6: Anropa ett webb-API

Om du vill anropa ett webb-API för tokenbaserad auktorisering måste appen ha en giltig åtkomsttoken. Appen gör följande:

  1. Hämtar en åtkomsttoken med nödvändiga behörigheter (omfång) för webb-API-slutpunkten.
  2. Skickar åtkomsttoken som en ägartoken i auktoriseringshuvudet för HTTP-begäran med det här formatet:
Authorization: Bearer <access-token>

När användarna loggar in interaktivt får appen en åtkomsttoken i getAuthInteractiveCallback motringningsmetoden. För efterföljande webb-API-anrop använder du proceduren hämta token tyst enligt beskrivningen i det här avsnittet.

Innan du anropar ett webb-API anropar acquireTokenSilentAsync du metoden med lämpliga omfång för webb-API-slutpunkten. MSAL-biblioteket gör följande:

  1. Försöker hämta en åtkomsttoken med de begärda omfången från tokencachen. Om token finns returneras token.
  2. Om token inte finns i tokencachen försöker MSAL använda sin uppdateringstoken för att hämta en ny token.
  3. Om uppdateringstoken inte finns eller har upphört att gälla returneras ett undantag. Vi rekommenderar att du uppmanar användaren att logga in interaktivt.

Följande kodfragment visar hur du hämtar en åtkomsttoken:

Knappklickshändelsen acquireTokenSilentButton hämtar en åtkomsttoken med de angivna omfången.

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)
})

Motringningsmetoden authSilentCallback returnerar en åtkomsttoken och anropar ett webb-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 */
            }
        }
    }

I följande exempel visas hur du anropar ett skyddat webb-API med en ägartoken:

@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()
}

Lägga till behörighet för att utföra nätverksåtgärder

Om du vill utföra nätverksåtgärder i programmet lägger du till följande behörighet i manifestet. Mer information finns i Ansluta till nätverket.

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

Nästa steg

Lär dig att: