Öğretici: Android uygulamasından kullanıcıların oturum açmasını Graph Microsoft Graph API'sini çağırma

Bu öğreticide, kullanıcıların oturum açmasını ve Microsoft Microsoft kimlik platformu API'sini çağıran bir erişim belirteci almak için Graph oluşturursınız.

Bu öğreticiyi tamamlandıktan sonra, uygulamanız kişisel Microsoft hesaplarının (outlook.com, live.com ve diğerleri dahil) oturum açmalarını ve bu hesapları kullanan herhangi bir şirket veya kuruluştan iş veya okul Azure Active Directory.

Bu öğreticide:

  • Android Studio'de Android uygulama projesi oluşturma
  • Uygulamayı Azure portal
  • Kullanıcı oturum açma ve oturum açma desteği için kod ekleme
  • Microsoft Graph API'sini çağırmaya kod ekleme
  • Uygulamayı test etme

Önkoşullar

  • Android Studio 3.5+

Bu öğretici nasıl çalışır?

Bu öğretici tarafından oluşturulan örnek uygulamanın nasıl çalıştığını gösterir

Bu öğreticide yer alan uygulama kullanıcıların oturum açmasını ve kendi adına veri aldıracak. Bu verilere yetkilendirme gerektiren ve veri kaynağı tarafından korunan korumalı bir API (Microsoft Graph API) Microsoft kimlik platformu.

Daha ayrıntılı belirtmek gerekirse:

  • Uygulamanız, kullanıcının oturum açmasını bir tarayıcı veya Microsoft Authenticator Intune Şirket Portalı.
  • Son kullanıcı, uygulamanıza istenen izinleri kabul eder.
  • Uygulamanıza Microsoft Graph API'si için bir erişim belirteci gönderilir.
  • Erişim belirteci web API'sine HTTP isteğine dahil edilir.
  • Microsoft Graph işle.

Bu örnek, Kimlik Doğrulaması uygulamak için Android için Microsoft Kimlik Doğrulama Kitaplığı'nın (MSAL) kullanır: com.microsoft.identity.client.

MSAL belirteçleri otomatik olarak yeniler, cihaza diğer uygulamalar arasında çoklu oturum açma (SSO) sağlar ve Hesapları yönetir.

Bu öğreticide, Android için MSAL ile çalışmayla ilgili basitleştirilmiş örnekler verilmiştir. Kolaylık olması için yalnızca Tek Hesap Modu kullanır. Daha karmaşık senaryoları keşfetmek için aşağıdaki tamamlanmış çalışma kodu örneğine GitHub.

Proje oluşturma

Henüz bir Android uygulama yoksa, yeni bir proje ayarlamak için bu adımları izleyin.

  1. Yeni Android Studio projesini başlat'ı Android Studio seçin.
  2. Temel Etkinlik'i ve ardından Sonraki'yi seçin.
  3. Uygulamanızı adlandırın.
  4. Paket adını kaydedin. Daha sonra bu kodu daha sonra Azure portal.
  5. Kotlin dilini Java olarak değiştirme.
  6. Minimum API düzeyini API 19 veya daha yüksek bir değere ayarlayın ve Son'a tıklayın.
  7. Proje görünümünde, kaynak Project olmayan proje dosyalarını görüntülemek, app/build.gradle'ı açmak ve olarak ayarlamak için açılan liste içinde Yer Aç'ı targetSdkVersion 28 seçin.

Microsoft Kimlik Doğrulama Kitaplığı ile tümleştirin

Uygulamanızı kaydetme

  1. Azure portalında oturum açın.

  2. Birden çok kiracıya erişiminiz varsa, uygulamayı kaydetmek istediğiniz kiracıya geçmek için üst menüde Dizinler + abonelikler filtresini kullanın.

  3. Azure Active Directory'yi bulun ve seçin.

  4. Yönet'in altında Yeni Uygulama kayıtları > seçeneğini seçin.

  5. Uygulamanıza bir Ad girin. Uygulama kullanıcıları bu adı görebilir ve daha sonra değiştirebilirsiniz.

  6. Kaydet’i seçin.

  7. Yönet'in altında Kimlik Doğrulaması > Platform ekle > Android'i seçin.

  8. Projenizin Paket Adını girin. Kodu indirdiyebilirsiniz, bu değer com.azuresamples.msalandroidapp olur.

  9. Android uygulamanızı yapılandırma sayfasının İmza karması bölümünde Geliştirme İmza Karması Oluştur'u seçin. ve platform için kullanmak üzere KeyTool komutunu kopyalayın.

    KeyTool.exe, Java Geliştirme Seti'nin (JDK) bir parçası olarak yüklenir. KeyTool komutunu yürütmek için OpenSSL aracını da yüklemeniz gerekir. Daha fazla bilgi için anahtar oluşturma hakkında Android belgelerine bakın.

  10. KeyTool tarafından oluşturulan İmza karması girin.

  11. Yapılandır'ı seçin ve android yapılandırma sayfasında görüntülenen MSAL Yapılandırmasını daha sonra yapılandırarak girebilirsiniz.

  12. Bitti seçeneğini belirleyin.

Uygulamanızı yapılandırma

  1. Uygulamanın Android Studio bölmesinde app\src\main\res dizinine gidin.

  2. res'e sağ tıklayın ve Yeni Dizin'i > seçin. Yeni raw dizin adı olarak girin ve Tamam'a tıklayın.

  3. src main res raw uygulamasında adlı yeni bir JSON dosyası oluşturun ve daha önce kaydedilen > > > > auth_config_single_account.json MSAL Yapılandırmasını yapıştırın.

    Yeniden yönlendirme URI'sini altına yapıştırın:

      "account_mode" : "SINGLE",
    

    Yapılandırma dosyanız şu örnekteki gibi olmalı:

    {
      "client_id" : "0984a7b6-bc13-4141-8b0d-8f767e136bb7",
      "authorization_user_agent" : "DEFAULT",
      "redirect_uri" : "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
      "broker_redirect_uri_registered" : true,
      "account_mode" : "SINGLE",
      "authorities" : [
        {
          "type": "AAD",
          "audience": {
            "type": "AzureADandPersonalMicrosoftAccount",
            "tenant_id": "common"
          }
        }
      ]
    }
    

    Bu öğreticide, bir uygulamanın yalnızca Tek Hesap modunda nasıl yapılandırıldığından emin olun. Tek veya birden çok hesap modu ve uygulama yapılandırma hakkında daha fazla bilgi için belgeleri görüntüleme

  4. uygulama > src > main > AndroidManifest.xml, aşağıdaki BrowserTabActivity etkinliği uygulama gövdesine ekleyin. Bu giriş, Kimlik doğrulaması tamamlandıktan sonra Microsoft'un uygulamanıza geri aramasını sağlar:

    <!--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="Enter_the_Package_Name"
                android:path="/Enter_the_Signature_Hash" />
        </intent-filter>
    </activity>
    

    Değerin yerine, Azure portal paket adını android:host= yazın. Değerin yerine, Azure portal anahtarı karması android:path= kullanın. İmza Karması URL ile kodlanmış olmalıdır. İmza Karması'nizin / başında bir önde olduğundan emin olmak.

    Değerini ile değiştirecek "Paket android:host Adı" şuna benzer: com.azuresamples.msalandroidapp . Değerinizi ile değiştirecek "İmza android:path Karması" şuna benzer: /1wIqXSqBj7w+h11ZifsnqwgyKrY= .

    Ayrıca bu değerleri uygulama kaydınızı kimlik doğrulaması dikey penceresinde de bulabilirsiniz. Yeniden yönlendirme URI'nizin şuna benzer olduğunu unutmayın: msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D . İmza Karması bu değerin sonunda URL ile kodlanmış durumdayken, İmza Karması değeriniz içinde URL ile kodlanmamış android:path olmalıdır.

MSAL kullanma

Projenize MSAL ekleme

  1. Uygulama Android Studio app > build.gradle'a gidin ve şunları ekleyin:

    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.+'
     implementation 'com.microsoft.graph:microsoft-graph:1.5.+'
     }
    packagingOptions{
     exclude("META-INF/jersey-module-version")
    }
    

    Microsoft Graph SDK'sı hakkında daha fazla bilgi

Gerekli İçeri Aktarmalar

Uygulama src main > > > java > com.example(yourapp) > MainActivity.java'nın en üstüne aşağıdakini ekleyin

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.gson.JsonObject;
import com.microsoft.graph.authentication.IAuthenticationProvider; //Imports the Graph sdk Auth interface
import com.microsoft.graph.concurrency.ICallback;
import com.microsoft.graph.core.ClientException;
import com.microsoft.graph.http.IHttpRequest;
import com.microsoft.graph.models.extensions.*;
import com.microsoft.graph.requests.extensions.GraphServiceClient;
import com.microsoft.identity.client.AuthenticationCallback; // Imports MSAL auth methods
import com.microsoft.identity.client.*;
import com.microsoft.identity.client.exception.*;

PublicClientApplication örneği

Değişkenleri Başlatma

private final static String[] SCOPES = {"Files.Read"};
/* Azure AD v2 Configs */
final static String AUTHORITY = "https://login.microsoftonline.com/common";
private ISingleAccountPublicClientApplication mSingleAccountApp;

private static final String TAG = MainActivity.class.getSimpleName();

/* UI & Debugging Variables */
Button signInButton;
Button signOutButton;
Button callGraphApiInteractiveButton;
Button callGraphApiSilentButton;
TextView logTextView;
TextView currentUserTextView;

Oncreate

sınıfının MainActivity içinde, kullanarak MSAL örneği için aşağıdaki onCreate() yöntemine SingleAccountPublicClientApplication bakın.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initializeUI();

    PublicClientApplication.createSingleAccountPublicClientApplication(getApplicationContext(),
            R.raw.auth_config_single_account, new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
                @Override
                public void onCreated(ISingleAccountPublicClientApplication application) {
                    mSingleAccountApp = application;
                    loadAccount();
                }
                @Override
                public void onError(MsalException exception) {
                    displayError(exception);
                }
            });
}

loadAccount

//When app comes to the foreground, load existing account to determine if user is signed in
private void loadAccount() {
    if (mSingleAccountApp == null) {
        return;
    }

    mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
        @Override
        public void onAccountLoaded(@Nullable IAccount activeAccount) {
            // You can use the account data to update your UI or your app database.
            updateUI(activeAccount);
        }

        @Override
        public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) {
            if (currentAccount == null) {
                // Perform a cleanup task as the signed-in account changed.
                performOperationOnSignOut();
            }
        }

        @Override
        public void onError(@NonNull MsalException exception) {
            displayError(exception);
        }
    });
}

initializeUI

Düğmeleri ve çağrı yöntemlerini dinleme veya hataları buna göre günlüğe ekleme.

private void initializeUI(){
        signInButton = findViewById(R.id.signIn);
        callGraphApiSilentButton = findViewById(R.id.callGraphSilent);
        callGraphApiInteractiveButton = findViewById(R.id.callGraphInteractive);
        signOutButton = findViewById(R.id.clearCache);
        logTextView = findViewById(R.id.txt_log);
        currentUserTextView = findViewById(R.id.current_user);

        //Sign in user
        signInButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v) {
                if (mSingleAccountApp == null) {
                    return;
                }
                mSingleAccountApp.signIn(MainActivity.this, null, SCOPES, getAuthInteractiveCallback());
            }
        });

        //Sign out user
        signOutButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSingleAccountApp == null){
                    return;
                }
                mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() {
                    @Override
                    public void onSignOut() {
                        updateUI(null);
                        performOperationOnSignOut();
                    }
                    @Override
                    public void onError(@NonNull MsalException exception){
                        displayError(exception);
                    }
                });
            }
        });

        //Interactive
        callGraphApiInteractiveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSingleAccountApp == null) {
                    return;
                }
                mSingleAccountApp.acquireToken(MainActivity.this, SCOPES, getAuthInteractiveCallback());
            }
        });

        //Silent
        callGraphApiSilentButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSingleAccountApp == null){
                    return;
                }
                mSingleAccountApp.acquireTokenSilentAsync(SCOPES, AUTHORITY, getAuthSilentCallback());
            }
        });
    }

Önemli

MSAL oturumu açıkken, bir kullanıcıyla ilgili bilinen tüm bilgiler uygulamanın dışındadır, ancak kullanıcının cihazında hala etkin bir oturumu olur. Kullanıcı yeniden oturum açma girişiminde bulunsa, oturum açma kullanıcı arabirimini görebilir, ancak cihaz oturumu hala etkin olduğundan kimlik bilgilerini yeniden girmeniz gerekebilir.

getAuthInteractiveCallback

Etkileşimli istekler için kullanılan geri çağırma.

private AuthenticationCallback getAuthInteractiveCallback() {
    return new AuthenticationCallback() {
        @Override
        public void onSuccess(IAuthenticationResult authenticationResult) {
            /* Successfully got a token, use it to call a protected resource - MSGraph */
            Log.d(TAG, "Successfully authenticated");
            /* Update UI */
            updateUI(authenticationResult.getAccount());
            /* call graph */
            callGraphAPI(authenticationResult);
        }

        @Override
        public void onError(MsalException exception) {
            /* Failed to acquireToken */
            Log.d(TAG, "Authentication failed: " + exception.toString());
            displayError(exception);
        }
        @Override
        public void onCancel() {
            /* User canceled the authentication */
            Log.d(TAG, "User cancelled login.");
        }
    };
}

getAuthSilentCallback

Sessiz istekler için kullanılan geri çağırma

private SilentAuthenticationCallback getAuthSilentCallback() {
    return new SilentAuthenticationCallback() {
        @Override
        public void onSuccess(IAuthenticationResult authenticationResult) {
            Log.d(TAG, "Successfully authenticated");
            callGraphAPI(authenticationResult);
        }
        @Override
        public void onError(MsalException exception) {
            Log.d(TAG, "Authentication failed: " + exception.toString());
            displayError(exception);
        }
    };
}

Microsoft Graph API'si çağırma

Aşağıdaki kod, Graph SDK'sını kullanarak GraphAPI'nin nasıl çağrıl Graph gösterir.

callGraphAPI

private void callGraphAPI(IAuthenticationResult authenticationResult) {

    final String accessToken = authenticationResult.getAccessToken();

    IGraphServiceClient graphClient =
            GraphServiceClient
                    .builder()
                    .authenticationProvider(new IAuthenticationProvider() {
                        @Override
                        public void authenticateRequest(IHttpRequest request) {
                            Log.d(TAG, "Authenticating request," + request.getRequestUrl());
                            request.addHeader("Authorization", "Bearer " + accessToken);
                        }
                    })
                    .buildClient();
    graphClient
            .me()
            .drive()
            .buildRequest()
            .get(new ICallback<Drive>() {
                @Override
                public void success(final Drive drive) {
                    Log.d(TAG, "Found Drive " + drive.id);
                    displayGraphResult(drive.getRawObject());
                }

                @Override
                public void failure(ClientException ex) {
                    displayError(ex);
                }
            });
}

Kullanıcı arabirimi ekleme

Etkinlik

Bu öğreticide kullanıcı arabiriminizi modellemek için aşağıdaki yöntemler metni güncelleştirme ve düğmeleri dinleme hakkında bir kılavuz sağlar.

updateUI

Oturum açma durumuna göre düğmeleri etkinleştirin/devre dışı bırakma ve metin ayarlama.

private void updateUI(@Nullable final IAccount account) {
    if (account != null) {
        signInButton.setEnabled(false);
        signOutButton.setEnabled(true);
        callGraphApiInteractiveButton.setEnabled(true);
        callGraphApiSilentButton.setEnabled(true);
        currentUserTextView.setText(account.getUsername());
    } else {
        signInButton.setEnabled(true);
        signOutButton.setEnabled(false);
        callGraphApiInteractiveButton.setEnabled(false);
        callGraphApiSilentButton.setEnabled(false);
        currentUserTextView.setText("");
        logTextView.setText("");
    }
}

displayError

private void displayError(@NonNull final Exception exception) {
       logTextView.setText(exception.toString());
   }

displayGraphResult

private void displayGraphResult(@NonNull final JsonObject graphResponse) {
      logTextView.setText(graphResponse.toString());
  }

performOperationOnSignOut

Kullanıcı arabiriminde metni oturum açmayı yansıtacak şekilde güncelleştirme yöntemi.

private void performOperationOnSignOut() {
    final String signOutText = "Signed Out.";
    currentUserTextView.setText("");
    Toast.makeText(getApplicationContext(), signOutText, Toast.LENGTH_SHORT)
            .show();
}

Layout

Düğmeleri activity_main.xml ve metin kutularını görüntülemek için örnek dosya.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:weightSum="10">

        <Button
            android:id="@+id/signIn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="5"
            android:gravity="center"
            android:text="Sign In"/>

        <Button
            android:id="@+id/clearCache"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="5"
            android:gravity="center"
            android:text="Sign Out"
            android:enabled="false"/>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">

        <Button
            android:id="@+id/callGraphInteractive"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="5"
            android:text="Get Graph Data Interactively"
            android:enabled="false"/>

        <Button
            android:id="@+id/callGraphSilent"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="5"
            android:text="Get Graph Data Silently"
            android:enabled="false"/>
    </LinearLayout>

    <TextView
        android:text="Getting Graph Data..."
        android:textColor="#3f3f3f"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:id="@+id/graphData"
        android:visibility="invisible"/>

    <TextView
        android:id="@+id/current_user"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="20dp"
        android:layout_weight="0.8"
        android:text="Account info goes here..." />

    <TextView
        android:id="@+id/txt_log"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="20dp"
        android:layout_weight="0.8"
        android:text="Output goes here..." />
</LinearLayout>

Uygulamanızı test etme

Yerel olarak çalıştırma

Uygulamayı derleme ve test cihazına veya öykünücüye dağıtma. Azure AD veya kişisel Microsoft hesapları için oturum açma ve belirteçleri alasınız.

Oturum açma sonrasında, uygulama Microsoft Graph uç noktadan döndürülen verileri /me görüntüler. PR 4

Herhangi bir kullanıcı uygulamanıza ilk kez oturum açdiğinde, microsoft kimliği tarafından istenen izinleri onaylar. Bazı Azure AD kiracıları, yöneticilerin tüm kullanıcılar adına onaylarını gerektiren kullanıcı onaylarını devre dışı bırakılmıştır. Bu senaryoyu desteklemek için kendi kiracınızı oluşturmanız veya yönetici onayı alasınız.

Kaynakları temizleme

Artık gerekli değilken, Uygulamanızı kaydetme adımını kullanarak oluşturduğunuz uygulama nesnesini silin.

Yardım ve destek

Yardıma ihtiyacınız varsa, bir sorun bildirmek veya Destek seçenekleriniz hakkında bilgi edinmek istiyorsanız, bkz. geliştiriciler Için yardım ve destek.

Sonraki adımlar

Çok parçalı senaryo serimizde korumalı web API'lerini çağıran mobil uygulamalar hakkında daha fazla bilgi edinin.