Xamarin.Essentials: 웹 인증자

WebAuthenticator 클래스를 사용하면 앱에 등록된 특정 URL에 대한 콜백을 수신 대기하는 브라우저 기반 흐름을 시작할 수 있습니다.

개요

많은 앱에서 사용자 인증 추가가 필요하며, 이는 흔히 사용자가 기존 Microsoft, Facebook, Google 그리고 이제 Apple 로그인 계정에 로그인할 수 있게 된다는 의미입니다.

MSAL(Microsoft 인증 라이브러리)은 앱에 인증을 추가하는 뛰어난 턴 키 솔루션을 제공합니다. 클라이언트 NuGet 패키지에서 Xamarin 앱을 지원하기도 합니다.

자체 웹 서비스를 인증에 사용하는 데 관심이 있는 경우 WebAuthenticator를 사용하여 클라이언트 쪽 기능을 구현할 수 있습니다.

서버 백 엔드를 사용하는 이유

보안을 강화하기 위해 많은 인증 공급자가 명시적 또는 2단계 인증 흐름만 제공하도록 전환했습니다. 이는 인증 흐름을 완료하기 위해 공급자로부터 '클라이언트 암호'가 필요함을 의미합니다. 아쉽게도 모바일 앱은 암호를 저장하기에 적합한 위치가 아니며, 모바일 앱의 코드, 이진 파일 또는 기타 위치에 저장된 모든 것은 일반적으로 안전하지 않은 것으로 간주됩니다.

여기에서 모범 사례는 모바일 앱과 인증 공급자 간의 중간 계층으로 웹 백 엔드를 사용하는 것입니다.

Important

인증 흐름에서 웹 백 엔드를 활용하지 않는 이전의 모바일 전용 인증 라이브러리 및 패턴은 내재적으로 클라이언트 암호 저장을 위한 보안이 불충분하기 때문에 사용하지 않는 것이 좋습니다.

시작하기

이 API를 사용하기 전에 라이브러리가 제대로 설치되고 프로젝트에 설정되어 있는지 확인하기 위해 Xamarin.Essentials에 대한 시작 가이드를 읽어보세요.

WebAuthenticator 기능에 액세스하려면 다음 플랫폼 관련 설정이 필요합니다.

Android에서는 콜백 URI를 처리하기 위한 의도 필터 설정이 필요합니다. 이 작업은 WebAuthenticatorCallbackActivity 클래스를 서브클래싱하여 쉽게 수행할 수 있습니다.

const string CALLBACK_SCHEME = "myapp";

[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionView },
    Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable },
    DataScheme = CALLBACK_SCHEME)]
public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
{
}

프로젝트의 대상 Android 버전이 Android 11(R API 30)로 설정된 경우 새 패키지 가시성 요구 사항에 사용되는 쿼리로 해당 Android 매니페스트를 업데이트해야 합니다.

속성 폴더에서 AndroidManifest.xml 파일을 열고 매니페스트 노드 내부에 다음을 추가합니다.

<queries>
    <intent>
        <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
</queries>

WebAuthenticator 사용

클래스에서 Xamarin.Essentials에 대한 참조를 추가합니다.

using Xamarin.Essentials;

API는 두 개의 매개 변수를 사용하는 단일 메서드 AuthenticateAsync 로 기본 구성됩니다. 즉, 웹 브라우저 흐름을 시작하는 데 사용해야 하는 URL과 흐름이 궁극적으로 다시 호출될 것으로 예상되는 URI 및 앱이 처리할 수 있도록 등록된 URI입니다.

결과는 콜백 URI에서 구문 분석된 모든 쿼리 매개 변수를 포함하는 WebAuthenticatorResult입니다.

var authResult = await WebAuthenticator.AuthenticateAsync(
        new Uri("https://mysite.com/mobileauth/Microsoft"),
        new Uri("myapp://"));

var accessToken = authResult?.AccessToken;

WebAuthenticator API는 브라우저에서 URL을 시작하고 콜백이 수신될 때까지 대기합니다.

Typical Web Authentication Flow

사용자가 어느 지점에서든 흐름을 취소하면 TaskCanceledException이 throw됩니다.

프라이빗 인증 세션

iOS 13에는 개발자가 인증 세션을 프라이빗으로 시작할 수 있는 임시 웹 브라우저 API가 도입되었습니다. 이를 통해 개발자는 인증 세션 간에 쿠키 또는 검색 데이터를 공유할 수 없고 매번 새로운 로그인 세션이 시작되도록 요청할 수 있습니다. 이 기능은 iOS용 Xamarin.Essentials 1.7에 도입된 새 WebAuthenticatorOptions를 통해 사용할 수 있습니다.

var url = new Uri("https://mysite.com/mobileauth/Microsoft");
var callbackUrl = new Uri("myapp://");
var authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
    {
        Url = url,
        CallbackUrl = callbackUrl,
        PrefersEphemeralWebBrowserSession = true
    });

플랫폼 간 차이점

사용자 지정 탭이 사용 가능한 경우 항상 사용되며, 그렇지 않으면 URL에 대한 의도가 시작됩니다.

Apple 로그인

Apple 검토 지침에 따라 앱에서 소셜 로그인 서비스를 사용하여 인증하는 경우에는 Apple 로그인도 옵션으로 제공해야 합니다.

앱에 Apple 로그인을 추가하려면 먼저 Apple 로그인을 사용하도록 앱을 구성해야 합니다.

iOS 13 이상에서는 AppleSignInAuthenticator.AuthenticateAsync() 메서드를 호출하는 것이 좋습니다. 이렇게 하면 내부에서 네이티브 Apple 로그인 API를 사용하여 사용자가 이러한 디바이스에서 최상의 환경을 얻을 수 있습니다. 다음과 같이 런타임에 적절한 API를 사용하는 공유 코드를 작성할 수 있습니다.

var scheme = "..."; // Apple, Microsoft, Google, Facebook, etc.
WebAuthenticatorResult r = null;

if (scheme.Equals("Apple")
    && DeviceInfo.Platform == DevicePlatform.iOS
    && DeviceInfo.Version.Major >= 13)
{
    // Use Native Apple Sign In API's
    r = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
    // Web Authentication flow
    var authUrl = new Uri(authenticationUrl + scheme);
    var callbackUrl = new Uri("xamarinessentials://");

    r = await WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);
}

var authToken = string.Empty;
if (r.Properties.TryGetValue("name", out var name) && !string.IsNullOrEmpty(name))
    authToken += $"Name: {name}{Environment.NewLine}";
if (r.Properties.TryGetValue("email", out var email) && !string.IsNullOrEmpty(email))
    authToken += $"Email: {email}{Environment.NewLine}";

// Note that Apple Sign In has an IdToken and not an AccessToken
authToken += r?.AccessToken ?? r?.IdToken;

iOS 13이 아닌 디바이스에서는 이 코드가 웹 인증 흐름을 시작하며, Android 및 UWP 디바이스에서 Apple 로그인을 사용하도록 설정하는 데에도 사용될 수 있습니다. iOS 시뮬레이터에서 iCloud 계정에 로그인하여 Apple 로그인을 테스트할 수 있습니다.


ASP.NET Core 서버 백 엔드

모든 웹 백 엔드 서비스에서 WebAuthenticator API를 사용할 수 있습니다. ASP.NET Core 앱에서 사용하려면 먼저 다음 단계를 사용하여 웹앱을 구성해야 합니다.

  1. ASP.NET Core 웹앱에 원하는 외부 소셜 인증 공급자를 설치합니다.
  2. .AddAuthentication() 호출에서 기본 인증 체계를 CookieAuthenticationDefaults.AuthenticationScheme으로 설정합니다.
  3. Startup.cs .AddAuthentication() 호출에서 .AddCookie()를 사용합니다.
  4. .SaveTokens = true;를 사용하여 모든 공급자를 구성해야 합니다.
services.AddAuthentication(o =>
    {
        o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddFacebook(fb =>
    {
        fb.AppId = Configuration["FacebookAppId"];
        fb.AppSecret = Configuration["FacebookAppSecret"];
        fb.SaveTokens = true;
    });

Apple 로그인을 포함하려는 경우 AspNet.Security.OAuth.Apple NuGet 패키지를 사용할 수 있습니다. Essentials GitHub 리포지토리에서 전체 Startup.cs 샘플을 볼 수 있습니다.

사용자 지정 모바일 인증 컨트롤러 추가

모바일 인증 흐름에서는 사용자가 선택한 공급자(예: 앱의 로그인 화면에서 "Microsoft" 단추 클릭)로 직접 흐름을 시작하는 것이 좋습니다. 또한 특정 콜백 URI에서 애플리케이션으로 관련 정보를 반환하여 인증 흐름을 종료할 수 있어야 하는 것도 중요합니다.

이를 위해 사용자 지정 API 컨트롤러를 사용합니다.

[Route("mobileauth")]
[ApiController]
public class AuthController : ControllerBase
{
    const string callbackScheme = "myapp";

    [HttpGet("{scheme}")] // eg: Microsoft, Facebook, Apple, etc
    public async Task Get([FromRoute]string scheme)
    {
        // 1. Initiate authentication flow with the scheme (provider)
        // 2. When the provider calls back to this URL
        //    a. Parse out the result
        //    b. Build the app callback URL
        //    c. Redirect back to the app
    }
}

이 컨트롤러의 목적은 앱이 요청하는 체계(공급자)를 유추하고 해당 소셜 공급자를 사용하여 인증 흐름을 시작하는 것입니다. 공급자가 웹 백 엔드로 콜백되면 컨트롤러는 결과를 구문 분석하고 매개 변수를 사용하여 앱의 콜백 URI로 리디렉션합니다.

경우에 따라 공급자의 access_token과 같은 데이터를 앱으로 다시 반환해야 할 수 있는데, 이 작업은 콜백 URI의 쿼리 매개 변수를 통해 수행할 수 있습니다. 또는 서버에서 고유한 ID를 만들고 앱에 자체 토큰을 다시 전달할 수도 있습니다. 어떤 작업을 수행할지, 어떤 방법을 사용할지는 개발자가 결정합니다.

Essentials 리포지토리에서 전체 컨트롤러 샘플을 확인하세요.

참고 항목

위의 샘플에서는 타사 인증(예: OAuth) 공급자에서 액세스 토큰을 반환하는 방법을 보여 줍니다. 웹 백엔드 자체에 대한 웹 요청을 인증하는 데 사용할 수 있는 토큰을 얻으려면 웹앱에서 자체 토큰을 만들어서 이를 대신 반환해야 합니다. ASP.NET Core 인증 개요에는 ASP.NET Core의 고급 인증 시나리오에 대해 자세히 설명되어 있습니다.


API