다음을 통해 공유


Android 앱에 인증 추가

요약

이 자습서에서는 지원되는 ID 공급자를 사용하여 Android의 할 일 모음 빠른 시작 프로젝트에 인증을 추가합니다. 이 자습서는 Mobile Apps 시작 자습서를 기반으로 하며 이를 먼저 완료해야 합니다.

인증을 위한 앱 등록 및 Azure App Service 구성

우선 ID 공급자 사이트에서 앱을 등록한 다음 Mobile Apps 백 엔드에서 공급자가 생성한 자격 증명을 설정합니다.

  1. 공급자 관련 지침에 따라 기본 설정된 ID 공급자를 구성합니다.

  2. 앱에서 지원하려는 각 공급자에 대해 이전 단계를 반복합니다.

허용되는 외부 리디렉션 URL에 앱 추가

보안 인증을 위해서는 앱에 대한 새로운 URL 체계를 정의해야 합니다. 이를 통해 인증 시스템은 인증 프로세스가 완료되면 앱으로 다시 리디렉션될 수 있습니다. 이 자습서에서는 전체적으로 URL 체계 appname을 사용합니다. 그러나 선택한 어떤 URL 체계도 사용 가능합니다. 이 체계는 모바일 애플리케이션에 고유해야 합니다. 서버 쪽에서 리디렉션을 사용하도록 설정하려면:

  1. Azure Portal에서 해당 App Service를 선택합니다.

  2. 인증/권한 부여 메뉴 옵션을 클릭합니다.

  3. 허용되는 외부 리디렉션 URL에서 appname://easyauth.callback을 입력합니다. 이 문자열의 appname은 모바일 애플리케이션에 대한 URL 체계입니다. 이 체계는 프로토콜에 대한 일반 URL 사양을 따라야 합니다(문자 및 숫자만 사용하고 문자로 시작). 여러 위치에서 URL 체계에 따라 모바일 애플리케이션 코드를 조정해야 할 경우 선택한 문자열을 적어두어야 합니다.

  4. 확인을 클릭합니다.

  5. 저장을 클릭합니다.

사용 권한을 인증된 사용자로 제한

기본적으로 Mobile Apps 백 엔드의 API는 익명으로 호출할 수 있습니다. 다음으로, 인증된 클라이언트로만 액세스를 제한해야 합니다.

  • Node.js 백 엔드(Azure Portal을 통해):

    Mobile Apps 설정에서 간편한 테이블을 클릭하고 테이블을 선택합니다. 사용 권한 변경을 클릭하고 모든 사용 권한에 대해 인증된 액세스만을 선택한 다음 저장을 클릭합니다.

  • .NET 백 엔드(C#):

    서버 프로젝트에서 ControllersTodoItemController.cs>로 이동합니다. 다음과 같이 TodoItemController 클래스에 [Authorize] 특성을 추가합니다. 특정 메서드로만 액세스를 제한하기 위해 이 특성을 클래스 대신 해당 메서드에만 적용할 수도 있습니다. 서버 프로젝트를 다시 게시합니다.

      [Authorize]
      public class TodoItemController : TableController<TodoItem>
    
  • (Node.js 코드를 통해) Node.js 백 엔드 :

    테이블 액세스에 대한 인증을 요청하려면 Node.js 서버 스크립트에 다음 줄을 추가합니다.

      table.access = 'authenticated';
    

    자세한 내용은 방법: 테이블에 대한 액세스 인증 요구를 참조하세요. 사이트에서 빠른 시작 코드 프로젝트를 다운로드하는 방법을 알아보려면 방법: Git를 사용하여 Node.js 백 엔드 빠른 시작 코드 프로젝트 다운로드를 참조하세요.

  • Android Studio에서 Mobile Apps 시작 자습서를 완료한 프로젝트를 엽니다. 실행 메뉴에서 앱 실행을 클릭하여 앱이 시작된 후 상태 코드 401(인증되지 않음)의 처리되지 않은 예외가 발생하는지 확인합니다.

    이 예외는 앱이 인증되지 않은 사용자로 백 엔드에 액세스하려고 시도하지만 할 일 모음 테이블에서 이제 인증을 요구하기 때문에 발생합니다.

다음으로 앱을 업데이트하여 Mobile Apps 백 엔드에서 리소스를 요청하기 전에 사용자를 인증하도록 합니다.

앱에 인증 추가

  1. Android Studio에서 프로젝트를 엽니다.

  2. Android Studio의 프로젝트 탐색기에서 ToDoActivity.java 파일을 열고 다음 import 문을 추가합니다.

    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.atomic.AtomicBoolean;
    
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    
    import com.microsoft.windowsazure.mobileservices.authentication.MobileServiceAuthenticationProvider;
    import com.microsoft.windowsazure.mobileservices.authentication.MobileServiceUser;
    
  3. ToDoActivity 클래스에 다음 메서드를 추가합니다.

    // You can choose any unique number here to differentiate auth providers from each other. Note this is the same code at login() and onActivityResult().
    public static final int GOOGLE_LOGIN_REQUEST_CODE = 1;
    
    private void authenticate() {
        // Sign in using the Google provider.
        mClient.login(MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // When request completes
        if (resultCode == RESULT_OK) {
            // Check the request code matches the one we send in the login request
            if (requestCode == GOOGLE_LOGIN_REQUEST_CODE) {
                MobileServiceActivityResult result = mClient.onActivityResult(data);
                if (result.isLoggedIn()) {
                    // sign-in succeeded
                    createAndShowDialog(String.format("You are now signed in - %1$2s", mClient.getCurrentUser().getUserId()), "Success");
                    createTable();
                } else {
                    // sign-in failed, check the error message
                    String errorMessage = result.getErrorMessage();
                    createAndShowDialog(errorMessage, "Error");
                }
            }
        }
    }
    

    이 코드는 Google 인증 프로세스를 처리하는 메서드를 만듭니다. 대화 상자는 인증된 사용자의 ID를 표시합니다. 성공적으로 인증을 진행할 수 있습니다.

    참고

    Google 이외의 ID 공급자를 사용하는 경우 login 메서드에 전달된 값을 MicrosoftAccount, Facebook, Twitter 또는 windowsazureactivedirectory 중 하나의 값으로 변경합니다.

  4. OnCreate 메서드에서 MobileServiceClient 개체를 인스턴스화하는 코드 다음에 다음 코드 줄을 추가합니다.

    authenticate();
    

    이 호출을 인증 프로세스를 시작합니다.

  5. onCreate 메서드의 나머지 코드를 authenticate();createTable 메서드로 이동합니다.

    private void createTable() {
    
        // Get the table instance to use.
        mToDoTable = mClient.getTable(ToDoItem.class);
    
        mTextNewToDo = (EditText) findViewById(R.id.textNewToDo);
    
        // Create an adapter to bind the items with the view.
        mAdapter = new ToDoItemAdapter(this, R.layout.row_list_to_do);
        ListView listViewToDo = (ListView) findViewById(R.id.listViewToDo);
        listViewToDo.setAdapter(mAdapter);
    
        // Load the items from Azure.
        refreshItemsFromTable();
    }
    
  6. 리디렉션이 예상대로 작동하도록 RedirectUrlActivity라는 다음 코드 조각을 AndroidManifest.xml에 추가합니다.

    <activity android:name="com.microsoft.windowsazure.mobileservices.authentication.RedirectUrlActivity">
        <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="{url_scheme_of_your_app}"
                android:host="easyauth.callback"/>
        </intent-filter>
    </activity>
    
  7. Android 애플리케이션의 build.gradleredirectUriScheme를 추가합니다.

    android {
        buildTypes {
            release {
                // ...
                manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
            }
            debug {
                // ...
                manifestPlaceholders = ['redirectUriScheme': '{url_scheme_of_your_app}://easyauth.callback']
            }
        }
    }
    
  8. build.gradle의 종속성에 com.android.support:customtabs:23.0.1을 추가합니다.

    dependencies {
        // ...
        compile 'com.android.support:customtabs:23.0.1'
    }
    
  9. 실행 메뉴에서 앱 실행을 클릭하여 앱을 시작하고 원하는 ID 공급자로 로그인합니다.

경고

언급한 URL 구성표는 대/소문자를 구분합니다. {url_scheme_of_you_app}의 모든 항목이 동일한 사례를 사용해야 합니다.

로그인하고 나면 앱이 오류 없이 실행되며 백 엔드 서비스를 쿼리하고 데이터를 업데이트할 수 있게 됩니다.

클라이언트에 인증 토큰 캐시

이전 예제에서는 앱이 시작될 때마다 클라이언트가 ID 공급자와 백 엔드 Azure 서비스 둘 다에 접근해야 하는 표준 로그인을 보여 주었습니다. 이 메서드는 비효율적이며 많은 고객이 동시에 앱을 시작하려고 하는 경우 사용 관련 문제가 발생할 수 있습니다. 더 나은 접근 방법은 Azure 서비스에서 반환된 권한 부여 토큰을 캐시한 다음 공급자 기반 로그인을 사용하기 전에 이 토큰을 먼저 사용하는 것입니다.

참고

클라이언트 관리 인증 또는 서비스 관리 인증을 사용하는지에 관계없이 백 엔드 Azure 서비스에서 발급된 토큰을 캐시할 수 있습니다. 이 자습서에서는 서비스 관리 인증을 사용합니다.

  1. ToDoActivity.java 파일을 열고 다음 import 문을 추가합니다.

    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    
  2. 다음 멤버를 ToDoActivity 클래스에 추가합니다.

    public static final String SHAREDPREFFILE = "temp";
    public static final String USERIDPREF = "uid";
    public static final String TOKENPREF = "tkn";
    
  3. ToDoActivity.java 파일에 cacheUserToken 메서드에 대한 다음 정의를 추가합니다.

    private void cacheUserToken(MobileServiceUser user)
    {
        SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
        Editor editor = prefs.edit();
        editor.putString(USERIDPREF, user.getUserId());
        editor.putString(TOKENPREF, user.getAuthenticationToken());
        editor.commit();
    }
    

    이 메서드는 프라이빗으로 표시된 기본 설정 파일에 사용자 ID와 토큰을 저장합니다. 이렇게 하면 디바이스의 다른 앱이 토큰에 액세스할 수 없도록 캐시 액세스가 보호됩니다. 기본 설정이 앱에 대해 샌드박스됩니다. 그러나 다른 사람이 디바이스에 액세스하게 되면 다른 수단을 통해 토큰 캐시에 액세스할 수도 있습니다.

    참고

    데이터에 대한 토큰 액세스가 매우 중요하며 다른 사람이 디바이스에 액세스할 수 있는 경우 암호화를 사용하여 토큰을 추가로 보호할 수 있습니다. 그러나 완전히 안전한 솔루션은 이 자습서의 범위를 벗어나며 보안 요구 사항에 따라 달라집니다.

  4. ToDoActivity.java 파일에 loadUserTokenCache 메서드에 대한 다음 정의를 추가합니다.

    private boolean loadUserTokenCache(MobileServiceClient client)
    {
        SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
        String userId = prefs.getString(USERIDPREF, null);
        if (userId == null)
            return false;
        String token = prefs.getString(TOKENPREF, null);
        if (token == null)
            return false;
    
        MobileServiceUser user = new MobileServiceUser(userId);
        user.setAuthenticationToken(token);
        client.setCurrentUser(user);
    
        return true;
    }
    
  5. ToDoActivity.java 파일에서 authenticateonActivityResult 메서드를 토큰 캐시를 사용하는 다음 메서드로 바꿉니다. Google이 아닌 다른 계정을 사용하려는 경우 로그인 공급자를 변경합니다.

    private void authenticate() {
        // We first try to load a token cache if one exists.
        if (loadUserTokenCache(mClient))
        {
            createTable();
        }
        // If we failed to load a token cache, sign in and create a token cache
        else
        {
            // Sign in using the Google provider.
            mClient.login(MobileServiceAuthenticationProvider.Google, "{url_scheme_of_your_app}", GOOGLE_LOGIN_REQUEST_CODE);
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // When request completes
        if (resultCode == RESULT_OK) {
            // Check the request code matches the one we send in the sign-in request
            if (requestCode == GOOGLE_LOGIN_REQUEST_CODE) {
                MobileServiceActivityResult result = mClient.onActivityResult(data);
                if (result.isLoggedIn()) {
                    // sign-in succeeded
                    createAndShowDialog(String.format("You are now signed in - %1$2s", mClient.getCurrentUser().getUserId()), "Success");
                    cacheUserToken(mClient.getCurrentUser());
                    createTable();
                } else {
                    // sign-in failed, check the error message
                    String errorMessage = result.getErrorMessage();
                    createAndShowDialog(errorMessage, "Error");
                }
            }
        }
    }
    
  6. 앱을 작성하고 유효한 계정으로 인증을 테스트합니다. 앱을 두 번 이상 실행합니다. 첫 번째 실행 중 로그인하고 토큰 캐시를 만들라는 프롬프트가 표시되어야 합니다. 그런 다음 각 실행은 인증에 대한 토큰 캐시를 로드하려고 시도합니다. 로그인할 필요가 없습니다.

다음 단계

이 기본 인증 자습서를 완료했으므로 다음 자습서 중 하나를 계속하는 것을 고려해보세요.