다음을 통해 공유


빠른 시작: Android 앱에서 사용자 로그인 및 Microsoft Graph 호출

이 빠른 시작에서는 Android 애플리케이션이 사용자를 로그인하고 Microsoft Graph API를 호출할 액세스 토큰을 가져오는 방법을 보여주는 코드 샘플을 다운로드하고 실행합니다.

Microsoft ID 플랫폼에서 애플리케이션에 토큰을 제공할 수 있도록 Microsoft Entra ID에서 애플리케이션이 앱 개체로 표시되어야 합니다.

필수 조건

샘플 작동 방법

이 빠른 시작에서 생성된 샘플 앱의 작동 방식을 보여 주는 다이어그램.

코드는 단일 및 다중 계정 MSAL 앱을 작성하는 방법을 보여 주는 조각으로 구성됩니다. 코드 파일은 다음과 같이 구성됩니다.

파일 시연
MainActivity UI를 관리합니다.
MSGraphRequestWrapper MSAL에서 제공하는 토큰을 사용하여 Microsoft Graph API를 호출합니다.
MultipleAccountModeFragment 다중 계정 애플리케이션을 초기화하고, 사용자 계정을 로드하며, Microsoft Graph API를 호출하는 토큰을 가져옵니다.
SingleAccountModeFragment 단일 계정 애플리케이션을 초기화하고, 사용자 계정을 로드하며, Microsoft Graph API를 호출하는 토큰을 가져옵니다.
res/auth_config_multiple_account.json 다중 계정 구성 파일입니다.
res/auth_config_single_account.json 단일 계정 구성 파일입니다.
Gradle Scripts/build.grade(Module: app) 이 파일에는 MSAL 라이브러리 종속성이 추가됩니다.

이제 이러한 파일을 자세히 살펴보고, 각 파일에 있는 MSAL 관련 코드를 호출합니다.

샘플 앱 가져오기

샘플 앱 등록

이 문서의 단계는 시작하는 포털에 따라 약간 다를 수도 있습니다.

  1. 최소한 애플리케이션 개발자 자격으로 Microsoft Entra 관리 센터에 로그인합니다.

  2. 여러 테넌트에 액세스할 수 있는 경우 위쪽 메뉴의 설정 아이콘을 사용하여 디렉터리 + 구독 메뉴에서 애플리케이션을 등록하려는 테넌트로 전환합니다.

  3. ID>애플리케이션>앱 등록으로 이동합니다.

  4. 새 등록을 선택합니다.

  5. 애플리케이션의 이름을 입력합니다. 이 이름은 앱의 사용자에게 표시될 수 있으며 나중에 변경할 수 있습니다.

  6. 지원되는 계정 유형의 경우 모든 조직 디렉터리의 계정(모든 Microsoft Entra 디렉터리 - 다중 테넌트) 및 개인 Microsoft 계정(예: Skype, Xbox)을 선택합니다. 다양한 계정 유형에 대한 정보를 보려면 선택 도움말 옵션을 선택합니다.

  7. 등록을 선택합니다.

  8. 관리에서 인증>플랫폼 추가>Android를 선택합니다.

  9. 위에서 다운로드한 샘플 형식에 따라 프로젝트의 패키지 이름을 입력합니다.

    • Java 샘플 - com.azuresamples.msalandroidapp
    • Kotlin 샘플 - com.azuresamples.msalandroidkotlinapp
  10. Android 앱 구성 창의 서명 해시 섹션에서 개발 서명 해시 생성을 선택하고 KeyTool 명령을 명령줄에 복사합니다.

    • KeyTool.exe는 JDK(Java Development Kit)의 일부로 설치됩니다. 또한 OpenSSL 도구를 설치하여 KeyTool 명령도 실행해야 합니다. 자세한 내용은 키 생성에 대한 Android 설명서를 참조하세요.
  11. KeyTool에서 생성된 서명 해시를 입력합니다.

  12. 구성을 선택하고 Android 구성 창에 나타나는 MSAL 구성을 저장합니다. 그러면 나중에 앱을 구성할 때 이 구성을 입력할 수 있습니다.

  13. 완료를 선택합니다.

샘플 앱 구성

  1. Android Studio의 프로젝트 창에서 app\src\main\res로 이동합니다.

  2. res를 마우스 오른쪽 단추로 클릭하고 새로 만들기>디렉터리를 선택합니다. 새 디렉터리 이름으로 raw를 입력하고 확인을 선택합니다.

  3. app>src>main>res>raw에서 다음으로 이동합니다. auth_config_single_account.json이라는 JSON 파일에 복사하고 이전에 저장한 MSAL 구성을 붙여넣습니다.

    리디렉션 URI 아래에 다음을 복사합니다.

      "account_mode" : "SINGLE",
    

    구성 파일이 다음 예제와 비슷할 것입니다.

    {
      "client_id": "00001111-aaaa-bbbb-3333-cccc4444",
      "authorization_user_agent": "WEBVIEW",
      "redirect_uri": "msauth://com.azuresamples.msalandroidapp/00001111%cccc4444%3D",
      "broker_redirect_uri_registered": true,
      "account_mode": "SINGLE",
      "authorities": [
        {
          "type": "AAD",
          "audience": {
            "type": "AzureADandPersonalMicrosoftAccount",
            "tenant_id": "common"
          }
        }
      ]
    }
    

    이 자습서에서는 단일 계정 모드에서 앱을 구성하는 방법만 보여 주기 때문에 자세한 내용은 단일 계정 모드와 다중 계정 모드앱 구성을 참조하세요.

샘플 앱 실행

Android Studio의 사용 가능한 디바이스 드롭다운에서 에뮬레이터 또는 물리적 디바이스를 선택하고, 앱을 실행합니다.

샘플 앱은 단일 계정 모드 화면에서 시작합니다. 기본 범위인 user.read는 기본적으로 제공되며, Microsoft Graph API 호출 중에 사용자 고유의 프로필 데이터를 읽을 때 사용됩니다. Microsoft Graph API 호출에 대한 URL은 기본적으로 제공됩니다. 원하는 경우 이 두 가지를 모두 변경할 수 있습니다.

단일 및 다중 계정 사용을 보여 주는 MSAL 샘플 앱의 스크린샷.

앱 메뉴를 사용하여 단일 계정 모드 및 다중 계정 모드 간에 변경합니다.

단일 계정 모드에서 작업 또는 홈 계정을 사용하여 로그인합니다.

  1. 사용자에게 자격 증명을 입력하라는 메시지를 표시하려면 대화형으로 그래프 데이터 가져오기를 선택합니다. 화면의 아래쪽에 Microsoft Graph API 호출의 출력이 표시됩니다.
  2. 로그인한 후에 사용자에게 자격 증명을 다시 입력하라는 메시지를 표시하지 않고 Microsoft Graph API를 호출하려면 자동으로 그래프 데이터 가져오기를 선택합니다. 화면의 아래쪽에 Microsoft Graph API 호출의 출력이 표시됩니다.

다중 계정 모드에서는 동일한 단계를 반복할 수 있습니다. 또한 로그인한 계정을 제거할 수 있으며, 해당 계정에 대해 캐시된 토큰도 제거할 수 있습니다.

추가 정보

이 빠른 시작에 대한 자세한 내용은 다음 섹션을 참조하세요.

앱에 MSAL 추가

MSAL(com.microsoft.identity.client)은 사용자를 로그인하고 Microsoft ID 플랫폼으로 보호되는 API 액세스에 사용되는 토큰을 요청할 때 사용되는 라이브러리입니다. Gradle 3.0 이상에서는 다음을 Gradle Scripts>build.gradle(Module: app)Dependencies(종속성) 아래에 추가하면 라이브러리를 설치합니다.

dependencies {
    ...
    implementation 'com.microsoft.identity.client:msal:5.1.0'
    implementation 'com.android.volley:volley:1.2.1'
    ...
}

여기서는 maven central에서 MSAL을 다운로드하고 빌드하도록 Gradle에 지시합니다.

또한 dependencyResolutionManagement: 아래에 있는 settings.gradle(모듈: 앱)allprojects>repositories 부분에 maven에 대한 참조를 추가해야 합니다.

dependencyResolutionManagement {
...
maven 
{
 url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
}
... 
}

MSAL 가져오기

MSAL 라이브러리와 관련된 가져오기는 com.microsoft.identity.client.*입니다. 예를 들어 퍼블릭 클라이언트 애플리케이션을 나타내는 PublicClientApplication 클래스의 네임스페이스인 import com.microsoft.identity.client.PublicClientApplication;이 표시됩니다.

SingleAccountModeFragment.java

이 파일은 단일 계정 MSAL 앱을 만들고 Microsoft Graph API를 호출하는 방법을 보여 줍니다.

단일 계정 앱은 단일 사용자만 사용합니다. 예를 들어 매핑 앱에 로그인하는 하나의 계정만 있을 수 있습니다.

단일 계정 MSAL 초기화

SingleAccountModeFragment.javaonCreateView() 메서드에서 auth_config_single_account.json 파일에 저장된 구성 정보를 사용하여 단일 계정 PublicClientApplication이 만들어집니다. 단일 계정 MSAL 앱에서 사용할 수 있도록 MSAL 라이브러리를 초기화하는 방법은 다음과 같습니다.

...
// Creates a PublicClientApplication object with res/raw/auth_config_single_account.json
PublicClientApplication.createSingleAccountPublicClientApplication(getContext(),
        R.raw.auth_config_single_account,
        new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
            @Override
            public void onCreated(ISingleAccountPublicClientApplication application) {
                /**
                 * This test app assumes that the app is only going to support one account.
                 * This requires "account_mode" : "SINGLE" in the config json file.
                 **/
                mSingleAccountApp = application;
                loadAccount();
            }

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

사용자 로그인

SingleAccountModeFragment.java에서 사용자를 로그인하는 코드는 initializeUI()signInButton 클릭 처리기에 있습니다.

토큰 획득을 시도하기 전에 signIn()을 호출합니다. acquireToken()이 호출된 것처럼 signIn()이 작동하여 사용자가 로그인할 수 있는 대화형 프롬프트가 표시됩니다.

사용자 로그인은 비동기 작업입니다. 사용자가 로그인하면 Microsoft Graph API를 호출하고 UI를 업데이트하는 콜백이 전달됩니다.

mSingleAccountApp.signIn(getActivity(), null, getScopes(), getAuthInteractiveCallback());

사용자 로그아웃

SingleAccountModeFragment.java에서 사용자를 로그아웃하는 코드는 initializeUI()signOutButton 클릭 처리기에 있습니다. 사용자 로그아웃은 비동기 작업입니다. 사용자가 로그아웃하면 해당 계정에 대한 토큰 캐시도 지워집니다. 사용자 계정이 로그아웃되면 UI를 업데이트하는 콜백이 만들어집니다.

mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() {
    @Override
    public void onSignOut() {
        updateUI(null);
        performOperationOnSignOut();
    }

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

대화형 또는 자동으로 토큰 가져오기

사용자에게 가장 적은 수의 프롬프트를 표시하려면 일반적으로 토큰을 자동으로 가져옵니다. 그런 다음 오류가 있으면 대화형으로 토큰 가져오기를 시도합니다. 앱에서 signIn()을 처음 호출하면 acquireToken()에 대한 호출로 효과적으로 작동하여 사용자에게 자격 증명을 입력하라는 메시지가 표시됩니다.

사용자에게 계정을 선택하거나, 자격 증명을 입력하거나, 앱에서 요청한 권한에 동의하라는 메시지가 표시될 수 있는 몇 가지 상황은 다음과 같습니다.

  • 사용자가 애플리케이션에 처음 로그인하는 경우
  • 사용자가 자신의 암호를 다시 설정하는 경우 해당 자격 증명을 입력해야 합니다.
  • 동의가 해지된 경우
  • 앱에서 동의를 명시적으로 요구하는 경우
  • 애플리케이션에서 처음으로 리소스에 대한 액세스를 요청하는 경우
  • MFA 또는 기타 조건부 액세스 정책이 필요한 경우

사용자와 관련한 UI를 사용하여 대화형으로 토큰을 가져오는 코드는 SingleAccountModeFragment.java에서 initializeUI()callGraphApiInteractiveButton 클릭 처리기에 있습니다.

/**
 * If acquireTokenSilent() returns an error that requires an interaction (MsalUiRequiredException),
 * invoke acquireToken() to have the user resolve the interrupt interactively.
 *
 * Some example scenarios are
 *  - password change
 *  - the resource you're acquiring a token for has a stricter set of requirement than your Single Sign-On refresh token.
 *  - you're introducing a new scope which the user has never consented for.
 **/
mSingleAccountApp.acquireToken(getActivity(), getScopes(), getAuthInteractiveCallback());

사용자가 이미 로그인한 경우 acquireTokenSilentAsync()를 통해 initializeUI()callGraphApiSilentButton 클릭 처리기에서 표시한 대로 앱에서 토큰을 자동으로 요청할 수 있습니다.

/**
 * Once you've signed the user in,
 * you can perform acquireTokenSilent to obtain resources without interrupting the user.
 **/
  mSingleAccountApp.acquireTokenSilentAsync(getScopes(), AUTHORITY, getAuthSilentCallback());

계정 로드

계정을 로드하는 코드는 loadAccount()SingleAccountModeFragment.java에 있습니다. 사용자 계정을 로드하는 것은 비동기 작업이므로 계정 로드, 변경 또는 오류가 발생하는 경우를 처리할 콜백이 MSAL에 전달됩니다. 다음 코드는 계정이 제거되고, 사용자가 다른 계정으로 변경되는 등의 경우에 발생하는 onAccountChanged()도 처리합니다.

private void loadAccount() {
    ...

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

Microsoft Graph 호출

사용자가 로그인하면 SingleAccountModeFragment.java에 정의된 callGraphAPI()의 HTTP 요청을 통해 Microsoft Graph에 대한 호출이 수행됩니다. 이 함수는 authenticationResult에서 액세스 토큰을 가져오고, MSGraphRequestWrapper에 대한 호출을 패키지하고, 호출 결과를 표시하는 것과 같은 몇 가지 작업을 수행하여 샘플을 간소화하는 래퍼입니다.

private void callGraphAPI(final IAuthenticationResult authenticationResult) {
    MSGraphRequestWrapper.callGraphAPIUsingVolley(
            getContext(),
            graphResourceTextView.getText().toString(),
            authenticationResult.getAccessToken(),
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    /* Successfully called graph, process data and send to UI */
                    ...
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    ...
                }
            });
}

auth_config_single_account.json

단일 계정을 사용하는 MSAL 앱에 대한 구성 파일입니다.

해당 필드에 대한 설명은 Android MSAL 구성 파일 이해를 참고하세요.

이 앱에서 단일 계정을 사용하도록 구성하는 "account_mode" : "SINGLE"이 있는지 확인합니다.

"client_id"는 Microsoft에서 유지 관리하는 앱 개체 등록을 사용하도록 미리 구성되어 있습니다. "redirect_uri"는 코드 샘플과 함께 제공되는 서명 키를 사용하도록 미리 구성되어 있습니다.

{
  "client_id": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "authorization_user_agent": "WEBVIEW",
  "redirect_uri": "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
  "account_mode": "SINGLE",
  "broker_redirect_uri_registered": true,
  "authorities": [
    {
      "type": "AAD",
      "audience": {
        "type": "AzureADandPersonalMicrosoftAccount",
        "tenant_id": "common"
      }
    }
  ]
}

MultipleAccountModeFragment.java

이 파일은 다중 계정 MSAL 앱을 만들고 Microsoft Graph API를 호출하는 방법을 보여 줍니다.

다중 계정 앱의 예로 여러 사용자 계정(예: 회사 계정 및 개인 계정)을 사용할 수 있는 메일 앱이 있습니다.

다중 계정 MSAL 초기화

MultipleAccountModeFragment.java 파일의 onCreateView()에서 auth_config_multiple_account.json file에 저장된 구성 정보를 사용하여 다중 계정 앱 개체(IMultipleAccountPublicClientApplication)를 만듭니다.

// Creates a PublicClientApplication object with res/raw/auth_config_multiple_account.json
PublicClientApplication.createMultipleAccountPublicClientApplication(getContext(),
        R.raw.auth_config_multiple_account,
        new IPublicClientApplication.IMultipleAccountApplicationCreatedListener() {
            @Override
            public void onCreated(IMultipleAccountPublicClientApplication application) {
                mMultipleAccountApp = application;
                loadAccounts();
            }

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

만든 MultipleAccountPublicClientApplication 개체는 MSAL 라이브러리와 상호 작용하여 토큰을 획득하고 사용자 계정을 로드 및 제거하는 데 사용할 수 있도록 클래스 멤버 변수에 저장됩니다.

계정 로드

다중 계정 앱은 일반적으로 getAccounts()를 호출하여 MSAL 작업에 사용할 계정을 선택합니다. 계정을 로드하는 코드는 loadAccounts()MultipleAccountModeFragment.java 파일에 있습니다. 사용자 계정을 로드하는 것은 비동기 작업입니다. 따라서 콜백은 계정이 로드되거나 변경되거나 오류가 발생하는 상황을 처리합니다.

/**
 * Load currently signed-in accounts, if there's any.
 **/
private void loadAccounts() {
    if (mMultipleAccountApp == null) {
        return;
    }

    mMultipleAccountApp.getAccounts(new IPublicClientApplication.LoadAccountsCallback() {
        @Override
        public void onTaskCompleted(final List<IAccount> result) {
            // You can use the account data to update your UI or your app database.
            accountList = result;
            updateUI(accountList);
        }

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

대화형 또는 자동으로 토큰 가져오기

사용자에게 계정을 선택하거나, 자격 증명을 입력하거나, 앱에서 요청한 권한에 동의하라는 메시지가 표시될 수 있는 몇 가지 상황은 다음과 같습니다.

  • 처음으로 사용자가 애플리케이션에 로그인한 경우
  • 사용자가 자신의 암호를 다시 설정하는 경우 해당 자격 증명을 입력해야 합니다.
  • 동의가 해지된 경우
  • 앱에서 동의를 명시적으로 요구하는 경우
  • 애플리케이션에서 처음으로 리소스에 대한 액세스를 요청하는 경우
  • MFA 또는 기타 조건부 액세스 정책이 필요한 경우

다중 계정 앱은 일반적으로 대화형으로, 즉 사용자가 참여하는 UI를 사용하여 acquireToken()에 대한 호출을 통해 토큰을 획득해야 합니다. 토큰을 대화형으로 가져오는 코드는 initializeUI()MultipleAccountModeFragment.java 파일에 있는 callGraphApiInteractiveButton 클릭 처리기에 있습니다.

/**
 * Acquire token interactively. It will also create an account object for the silent call as a result (to be obtained by getAccount()).
 *
 * If acquireTokenSilent() returns an error that requires an interaction,
 * invoke acquireToken() to have the user resolve the interrupt interactively.
 *
 * Some example scenarios are
 *  - password change
 *  - the resource you're acquiring a token for has a stricter set of requirement than your SSO refresh token.
 *  - you're introducing a new scope which the user has never consented for.
 **/
mMultipleAccountApp.acquireToken(getActivity(), getScopes(), getAuthInteractiveCallback());

앱에서 사용자가 토큰을 요청할 때마다 로그인하도록 요구하지 않아야 합니다. 사용자가 이미 로그인한 경우 acquireTokenSilentAsync()를 통해 MultipleAccountModeFragment.java 파일에 있는 initializeUI()callGraphApiSilentButton 클릭 처리기에서 표시한 대로 앱에서 사용자에게 메시지를 표시하지 않고 토큰을 요청할 수 있습니다.

/**
 * Performs acquireToken without interrupting the user.
 *
 * This requires an account object of the account you're obtaining a token for.
 * (can be obtained via getAccount()).
 */
mMultipleAccountApp.acquireTokenSilentAsync(getScopes(),
    accountList.get(accountListSpinner.getSelectedItemPosition()),
    AUTHORITY,
    getAuthSilentCallback());

계정 제거

계정을 제거하는 코드와 계정에 캐시된 모든 토큰은 MultipleAccountModeFragment.java 파일의 initializeUI()에 있는 계정 제거 단추 처리기에 있습니다. 계정을 제거하려면 먼저 getAccounts()acquireToken()과 같은 MSAL 메서드에서 가져오는 계정 개체가 필요합니다. 계정을 제거하는 것은 비동기 작업이므로 UI를 업데이트하는 onRemoved 콜백이 제공됩니다.

/**
 * Removes the selected account and cached tokens from this app (or device, if the device is in shared mode).
 **/
mMultipleAccountApp.removeAccount(accountList.get(accountListSpinner.getSelectedItemPosition()),
        new IMultipleAccountPublicClientApplication.RemoveAccountCallback() {
            @Override
            public void onRemoved() {
                ...
                /* Reload account asynchronously to get the up-to-date list. */
                loadAccounts();
            }

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

auth_config_multiple_account.json

다중 계정을 사용하는 MSAL 앱에 대한 구성 파일입니다.

다양한 필드에 대한 설명은 Android MSAL 구성 파일 이해를 참고하세요.

다중 계정 앱이므로 이 구성 파일에는 auth_config_single_account.json 구성 파일과 달리 "account_mode" : "SINGLE" 대신 "account_mode" : "MULTIPLE"이 있습니다.

"client_id"는 Microsoft에서 유지 관리하는 앱 개체 등록을 사용하도록 미리 구성되어 있습니다. "redirect_uri"는 코드 샘플과 함께 제공되는 서명 키를 사용하도록 미리 구성되어 있습니다.

{
  "client_id": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "authorization_user_agent": "WEBVIEW",
  "redirect_uri": "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
  "account_mode": "MULTIPLE",
  "broker_redirect_uri_registered": true,
  "authorities": [
    {
      "type": "AAD",
      "audience": {
        "type": "AzureADandPersonalMicrosoftAccount",
        "tenant_id": "common"
      }
    }
  ]
}

도움말 및 지원 

도움이 필요하거나, 문제를 보고하거나, 지원 옵션에 대해 알아보려면 개발자를 위한 도움말 및 지원을 참조하세요.

다음 단계

Microsoft ID 플랫폼에서 액세스 토큰을 가져오고, 이를 사용하여 Microsoft Graph API를 호출하는 Android 앱을 빌드하는 Android 자습서로 이동합니다.