콘텐츠로 이동

WebAuth 로그인 Add-on

앱이 만든 OAuth 2.0 인가 URL을 플랫폼이 제공하는 인증 전용 브라우저 세션에서 열고, 인증을 마친 뒤 돌아오는 리다이렉트 콜백 URL과 쿼리 파라미터를 반환하는 Add-on입니다. OAuth 2.0 네이티브 앱 규격인 RFC 8252의 외부 사용자 에이전트 방식을 따르며, 전용 로그인 Add-on이 없는 외부 인증 제공자와 OS 조합에서 자격 증명을 받아 올 때 사용합니다.

Add-on은 OAuth 파라미터를 해석하거나 검증하지 않습니다. PKCE, state, nonce 같은 OAuth 값의 해석과 리다이렉트 URI 일치 확인은 앱이 담당합니다.

플랫폼마다 사용하는 인증 세션 기능은 아래와 같습니다.

  • iOS, macOS: ASWebAuthenticationSession
  • Android: Chrome Custom Tabs
  • Windows: 기본 브라우저와 루프백 HTTP 리스너

모듈 정보

  • 패키지: com.com2usplatform.hiveaxyl.auth.addon.webauth
  • 인터페이스: IExternalUserAgent, IWindowsLoopbackAgent
  • 진입 클래스: WebAuthSessionPlugin
  • 네임스페이스: Hive.Axyl.Auth.Addon.WebAuth
  • 등록 메서드: AddWebAuth()
  • 지원 플랫폼: Android, Windows, iOS, macOS
  • 최소 사양: Android API 29+, iOS 17+, macOS 15+, Unity 6000.0+
사전 준비

외부 인증 제공자가 인증을 마친 뒤 앱이 리다이렉트 콜백을 받을 수 있도록 플랫폼별로 리다이렉트 URI를 준비해야 합니다. 준비 방법은 리다이렉트 URI 준비를 참조하세요.

등록과 획득

HiveBootstrap.Initialize의 등록 단계에서 등록한 뒤 HiveCore.TryResolve<T>()로 IExternalUserAgent를 가져옵니다. 등록되는 객체는 WebAuthSessionPlugin입니다.

using Hive.Axyl.Auth;
using Hive.Axyl.Auth.Addon.WebAuth;
using Hive.Axyl.Core;
using Hive.Axyl.Core.Unity;   // HiveBootstrap

HiveBootstrap.Initialize(config, builder =>
{
    builder.AddAuth()
           .AddToken()
           .AddWebAuth();
});

if (HiveCore.TryResolve<IExternalUserAgent>(out var webAuth))
{
    // 지원 플랫폼 빌드에서만 실행되는 코드
}
Unity 에디터에서는 등록되지 않습니다

이 Add-on은 Android, Windows, iOS, macOS로 빌드한 플레이어에서만 등록됩니다. Unity 에디터에서는 플랫폼이 맞아도 등록되지 않으므로, HiveCore.Resolve<T>()를 쓰면 RegistrationNotFoundException이 발생합니다. 반드시 TryResolve<T>()로 확인한 뒤 사용하세요.

패키지 설치와 등록 절차는 모듈 설치 및 초기화를 참조하세요.

메서드 요약

비동기 메서드는 마지막 파라미터로 CancellationToken ct = default를 받습니다. 호출 규약은 호출 컨텍스트를 참조하세요.

인터페이스·클래스 멤버 설명
IExternalUserAgent OpenAsync() 인증 전용 브라우저 세션에서 인가 URL을 열고 리다이렉트 콜백을 받습니다.
IExternalUserAgent CancelCurrentSession() 진행 중인 세션을 코드에서 취소합니다.
WebAuthSessionPlugin WindowsLoopback Windows 전용 루프백 에이전트를 가져옵니다.
IWindowsLoopbackAgent AllocateLoopbackRedirectUriAsync() Windows에서 루프백 리다이렉트 URI와 HTTP 리스너를 예약합니다.

IExternalUserAgent

인증 전용 브라우저 세션을 열고 플랫폼이 전달한 리다이렉트 콜백을 반환하는 인터페이스입니다.

OpenAsync

앱이 만든 인가 URL을 인증 전용 브라우저 세션에서 열고, 플랫폼이 리다이렉트 콜백을 전달할 때까지 기다립니다. 콜백을 받으면 콜백 URL 원문과 쿼리 파라미터를 반환합니다.

한 번에 하나의 세션만 진행합니다. 세션이 진행 중일 때 다시 호출하면 진행 중인 세션은 그대로 두고 Code가 FailedPrecondition인 Failure를 바로 반환합니다.

Task<ExternalUserAgentServiceOpenResult> OpenAsync(OpenRequest request, CancellationToken ct = default)

결과 케이스 — ExternalUserAgentServiceOpenResult

결과 케이스 와이어 코드 설명
Success — 리다이렉트 콜백을 받았습니다. Data에 콜백 URL과 쿼리 파라미터가 담깁니다.
UserCanceled user_canceled 앱 사용자가 창을 닫거나 뒤로 가기 또는 취소를 선택해 인증 화면을 닫았습니다. 앱 사용자에게 재시도를 안내할 수 있습니다. Windows에서는 앱 사용자가 브라우저를 닫아도 감지하지 못하므로 이 결과가 반환되지 않습니다.
UnknownOutcome UNKNOWN 이 SDK 버전이 알지 못하는 새 결과입니다.
Failure FAILURE 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. 지원하지 않는 플랫폼이거나 네이티브 콜백을 처리하지 못한 경우도 여기에 해당합니다.

UserCanceled는 IUserCanceledOutcome을 구현합니다.

사용자 취소와 코드 취소는 다릅니다

앱 사용자가 인증 화면을 닫으면 UserCanceled입니다. 반면 CancellationToken이나 CancelCurrentSession()으로 코드에서 취소하면 Code가 Cancelled인 Failure가 됩니다.

Windows 주의 사항

Windows에서는 AllocateLoopbackRedirectUriAsync()로 예약한 리다이렉트 URI를 OpenRequest.RedirectUri에 넣어야 합니다. 예약하지 않고 호출했거나 마지막으로 예약한 URI와 다른 값을 넣으면 Code가 FailedPrecondition인 Failure를 반환합니다.

Windows에서는 앱 사용자가 브라우저를 닫아도 이를 감지하지 못하고 제한 시간도 없어서, OpenAsync()가 끝나지 않고 계속 기다립니다. 로그인 화면의 취소 버튼에서 CancelCurrentSession()을 호출하거나, 제한 시간을 둔 CancellationToken을 전달하세요.

발생 예외

  • ArgumentNullException: request가 null인 경우
  • ArgumentException: request.Url 또는 request.RedirectUri가 null이거나 비어 있는 경우

호출 예시

using Hive.Axyl.Auth.Addon.WebAuth;
using Hive.Axyl.Core;

var result = await webAuth.OpenAsync(new OpenRequest
{
    Url = authorizationUrl,      // 앱이 만든 인가 URL
    RedirectUri = redirectUri,   // 앱이 리다이렉트 콜백을 받을 URI
});

switch (result)
{
    case ExternalUserAgentServiceOpenResult.Success success:
        if (success.Data.Parameters.TryGetValue("error", out var providerError))
        {
            // 외부 인증 제공자가 콜백으로 보낸 오류입니다.
        }
        else if (success.Data.Parameters.TryGetValue("code", out var code))
        {
            // state를 검증한 뒤 code를 로그인 흐름에 사용합니다.
        }
        break;

    case ExternalUserAgentServiceOpenResult.UserCanceled:
        // 앱 사용자가 인증 화면을 닫았습니다.
        break;

    case ExternalUserAgentServiceOpenResult.Failure failure:
        HiveError error = failure.Problem;
        break;

    default:
        // 처리하지 않은 결과와 UnknownOutcome
        break;
}

Success가 반환되어도 외부 인증 제공자가 error=access_denied 같은 오류를 콜백으로 보낼 수 있습니다. 인가 코드가 있다고 가정하지 말고 Parameters의 값을 확인하세요.

콜백 데이터를 로그에 남기지 마세요

Data.CallbackUrl과 Data.Parameters에는 인가 코드, state, 외부 인증 제공자의 토큰이 담길 수 있습니다. 로그, 크래시 리포트, 분석 이벤트에 기록하지 마세요.

구현 절차는 웹 로그인 세션 열기를 참조하세요.

CancelCurrentSession

진행 중인 세션을 코드에서 취소합니다. 대기 중이던 OpenAsync()는 Code가 Cancelled인 Failure로 끝납니다. 진행 중인 세션이 없으면 아무 동작도 하지 않습니다.

void CancelCurrentSession()

구현 절차는 진행 중인 세션 취소를 참조하세요.

WebAuthSessionPlugin

AddWebAuth()가 IExternalUserAgent로 등록하는 클래스입니다. 플랫폼별 인증 전용 브라우저 세션을 IExternalUserAgent로 감싸고, 한 번에 하나의 세션만 진행하도록 제한합니다. Windows 루프백 에이전트가 필요할 때만 HiveCore.TryResolve<T>()로 가져온 IExternalUserAgent를 이 클래스로 확인해 사용하세요.

WindowsLoopback

Windows 전용 루프백 에이전트입니다. OpenAsync()를 호출하기 전에 AllocateLoopbackRedirectUriAsync()로 리다이렉트 URI를 예약할 때 사용합니다. Windows가 아닌 플랫폼에서는 null입니다.

IWindowsLoopbackAgent? WindowsLoopback { get; }

IWindowsLoopbackAgent

Windows에서 임시 루프백 포트와 HTTP 리스너를 예약하는 인터페이스입니다. 루프백 주소는 127.0.0.1처럼 같은 기기 안에서만 접속되는 주소입니다. Windows에는 OS가 제공하는 인증 전용 브라우저 세션이 없으므로, 기본 브라우저로 인가 URL을 열고 RFC 8252 7.3절의 루프백 인터페이스 리다이렉션 방식으로 예약한 루프백 주소에서 리다이렉트 콜백을 받습니다. 이 인터페이스는 WebAuthSessionPlugin.WindowsLoopback으로 가져옵니다.

AllocateLoopbackRedirectUriAsync

임시 루프백 포트를 예약하고 HTTP 리스너를 미리 바인딩한 뒤, http://127.0.0.1:<포트><경로> 형식의 리다이렉트 URI를 반환합니다. 반환된 URI를 OpenRequest.RedirectUri에 그대로 넣으세요. 루프백 주소를 리다이렉트 URI로 허용하는 외부 인증 제공자라면 인가 URL의 리다이렉트 URI에도 같은 값을 넣으세요. Apple처럼 루프백 주소를 허용하지 않는 외부 인증 제공자로 로그인할 때는 Hive Axyl 중계 주소를 거쳐 예약한 주소로 콜백을 받습니다.

OpenAsync()를 호출하기 전에 다시 호출하면 이전 리스너를 해제하고 새 포트를 예약하므로, 이전에 받은 URI는 더 이상 사용할 수 없습니다. 리스너는 리다이렉트 콜백을 한 번 받으면 해제되므로, 예약한 URI는 OpenAsync() 한 번에만 사용할 수 있습니다. 다시 로그인할 때는 이 메서드로 새 URI를 예약하세요.

Task<WindowsLoopbackServiceAllocateLoopbackRedirectUriResult> AllocateLoopbackRedirectUriAsync(AllocateLoopbackRedirectUriRequest request, CancellationToken ct = default)

결과 케이스 — WindowsLoopbackServiceAllocateLoopbackRedirectUriResult

결과 케이스 와이어 코드 설명
Success — 리다이렉트 URI를 예약했습니다. Data.RedirectUri에 예약한 URI가 담깁니다.
UnknownOutcome UNKNOWN 이 SDK 버전이 알지 못하는 새 결과입니다.
Failure FAILURE 호출을 마치지 못했습니다. Problem의 HiveError로 원인을 확인합니다. 바인딩할 수 있는 포트가 없으면 Code는 ResourceExhausted, 로컬 포트 바인딩이 차단됐으면 Unavailable, PathPrefix 형식이 잘못됐으면 InvalidArgument입니다.

발생 예외

  • ArgumentNullException: request가 null인 경우
  • ArgumentException: request.PathPrefix가 null인 경우

호출 예시

using Hive.Axyl.Auth.Addon.WebAuth;

if (webAuth is not WebAuthSessionPlugin { WindowsLoopback: { } loopback })
{
    // Windows가 아니므로 루프백 에이전트가 없습니다.
    return;
}

var allocated = await loopback.AllocateLoopbackRedirectUriAsync(new AllocateLoopbackRedirectUriRequest
{
    PathPrefix = "/hive-auth/callback",
});

if (allocated is not WindowsLoopbackServiceAllocateLoopbackRedirectUriResult.Success success)
{
    return;
}

string redirectUri = success.Data.RedirectUri;                // 예: http://127.0.0.1:54321/hive-auth/callback
string authorizationUrl = BuildAuthorizationUrl(redirectUri);  // 앱이 인가 URL을 만드는 코드

var result = await webAuth.OpenAsync(new OpenRequest
{
    Url = authorizationUrl,
    RedirectUri = redirectUri,   // 예약한 URI를 그대로 넣습니다.
});

구현 절차는 리다이렉트 URI 준비를 참조하세요.

데이터 타입

AllocateLoopbackRedirectUriRequest

필드 타입 필수 여부 설명
PathPrefix string Required 리다이렉트 URI의 경로입니다. 예: /hive-auth/callback. 값을 넣을 때는 /로 시작해야 하며, 빈 문자열이면 기본 경로인 /hive-auth/callback을 사용합니다. null이면 ArgumentException이 발생합니다.

AllocateLoopbackRedirectUriResponse

필드 타입 필수 여부 설명
RedirectUri string Required 예약한 루프백 리다이렉트 URI입니다. 예: http://127.0.0.1:54321/hive-auth/callback. OpenRequest.RedirectUri에 그대로 넣어 예약한 리스너로 콜백을 받습니다.

OpenRequest

필드 타입 필수 여부 설명
Url string Required 인증 전용 브라우저 세션에서 열 OAuth 인가 URL입니다. 앱이 만든 값을 넣습니다. 비어 있으면 ArgumentException이 발생합니다.
RedirectUri string Required 앱이 리다이렉트 콜백으로 받을 URI입니다. iOS와 macOS에서는 이 값의 스킴으로 돌아오는 콜백을 받습니다. Windows에서는 AllocateLoopbackRedirectUriAsync()로 예약한 URI와 같아야 합니다. Android에서는 이 값으로 스킴을 바꿀 수 없고, 빌드할 때 매니페스트에 등록한 스킴으로 콜백을 받습니다. Hive Axyl 중계 주소를 거치는 로그인에서는 인가 URL에 넣은 중계 주소가 아니라 앱 콜백 주소를 넣습니다. 비어 있으면 ArgumentException이 발생합니다.

OpenResponse

리다이렉트 콜백을 받은 결과입니다. Add-on은 OAuth 값을 검증하지 않고 그대로 전달합니다.

필드 타입 필수 여부 설명
CallbackUrl string Required 플랫폼이 전달한 리다이렉트 콜백 URL 원문입니다. 예: com.myapp://cb?code=abc&state=xyz. 인가 코드, state, 외부 인증 제공자의 토큰이 담길 수 있습니다.
Parameters IReadOnlyDictionary<string, string> Required CallbackUrl의 쿼리 파라미터를 파싱한 값입니다. code, state는 물론 error=access_denied 같은 외부 인증 제공자의 오류까지 모든 값의 해석은 앱이 담당합니다.