콘텐츠로 이동

Steam 로그인 구현하기

레시피 코드로 Steam 로그인을 구현하려면 아래 절차를 순서대로 완료하세요.

시작하기 전에 공통 사전 준비를 마치세요.

전체 흐름

각 단계에서 무엇을 설정하고 무엇을 호출하는지는 아래와 같습니다. 대상 방식이 적힌 단계는 그 방식을 지원할 때만 수행하세요.

순서 구분 하는 일 대상 방식
1 외부 콘솔 Steamworks에서 인증 정보 준비 전체
2 Hive 콘솔 인증 정보 등록과 Steam 로그인 활성화 전체
3 Hive Axyl SDK 인증 모듈과 Add-on 설치 전체
4 Hive Axyl SDK SDK 초기화와 모듈 등록 전체
5 앱 코드 Steamworks 초기화 Steam 클라이언트 방식
6 레시피 코드 레시피 폴더 복사 전체
7 앱 코드 ClientId와 DeviceKey 준비 전체
8 레시피 코드 Steam 자격 증명 소스 준비 전체
9 레시피 코드 Steam 로그인 호출 전체
10 Add-on 인증 티켓 반납 Steam 클라이언트 방식
11 앱 코드 로그인 결과 처리 전체
12 앱 코드 동작 확인 전체
인증 티켓을 반납하지 않으면 로그인이 막힙니다

Steam 클라이언트 방식에서 레시피가 받아 오는 인증 티켓은 앱이 동시에 보유할 수 있는 개수가 정해져 있습니다. 레시피는 티켓을 반납하지 않으므로 10단계를 앱이 직접 구현해야 합니다.

1. Steamworks 설정

Steamworks에서 Hive Axyl 인증 서버가 사용할 인증 정보를 먼저 준비하세요. Hive Axyl 인증 서버는 이 값으로 앱이 보낸 Steam 인증 결과가 진짜인지 Steam에 확인합니다.

Publisher Web API Key를 확인해 복사해 두세요. 이 값은 2단계의 Hive 콘솔에 입력합니다.

브라우저 방식은 Steamworks에 리다이렉트 주소를 등록하지 않습니다. Steam은 사용자를 돌려보낼 주소의 도메인을 로그인 화면에 로그인을 요청한 사이트로 표시하기만 합니다. Android와 iOS에서는 8.2의 Hive Axyl 중계 주소 도메인이 표시됩니다.

2. Hive 콘솔 설정

준비한 인증 정보를 Hive 콘솔에 등록하고 Steam 로그인을 활성화하세요. 로그인 수단이 비활성 상태이면 레시피 호출이 거절됩니다.

설정 항목 필수 여부 확인할 곳
Steam App ID와 Web API Key 등록 필수 Steam 로그인 인증 정보
Steam 로그인 활성화 필수 로그인 수단 종류
App ID별 로그인 설정 선택 App ID별 로그인 설정

여기서 등록한 설정은 프로젝트에 속한 모든 App ID에 함께 적용됩니다. 특정 App ID에서만 다른 로그인 수단을 노출하려면 App ID별 로그인 설정을 사용하세요.

여기에 입력하는 Steam App ID는 사전 준비에서 Store App ID로 등록한 값과 같습니다. 두 화면은 쓰임새가 다르므로 같은 값을 양쪽에 모두 입력하세요. 입력란은 프로젝트에 Windows 또는 macOS App ID가 있을 때 나타납니다.

3. SDK 모듈과 Add-on 설치

인증 모듈과 앱이 지원할 OS에 맞는 Add-on을 Unity 프로젝트에 설치하세요. Add-on은 Steam 인증을 대신 수행하는 Hive Axyl SDK 확장 패키지이며, 8단계에서 준비하는 자격 증명 소스가 이 Add-on을 호출합니다.

패키지 필요 여부 역할
com.com2usplatform.hiveaxyl.core 필수 SDK 초기화와 로그인 세션 관리
com.com2usplatform.hiveaxyl.auth 필수 Steam 자격 증명으로 로그인, 토큰 발급
com.com2usplatform.hiveaxyl.auth.addon.steam Steam 클라이언트 방식에 필수 Steam 클라이언트에서 인증 티켓 발급
com.com2usplatform.hiveaxyl.auth.addon.webauth 브라우저 방식에 필수 브라우저로 Steam 로그인 페이지 표시
com.unity.nuget.newtonsoft-json 브라우저 방식에 필수 ProviderLogin.WebAuth/ 어셈블리가 참조하므로 없으면 컴파일되지 않음
com.com2usplatform.hiveaxyl.storage 권장 DeviceKey와 세션 토큰의 암호화 저장

설치할 때 아래 내용도 확인하세요.

  • 설치하지 않은 Add-on: 그 방식의 자격 증명 소스가 컴파일 대상에서 빠지므로, Windows와 macOS 빌드에서도 Steam Add-on을 설치하지 않으면 SteamCredentialSource를 사용하지 못합니다.
  • Android의 브라우저 방식: 로그인 결과를 받을 앱 콜백 스킴을 앱에 등록해야 하며, 등록할 스킴과 방법은 8.2.2. Android 앱 콜백 스킴 등록을 참조하세요.
  • Steamworks.NET 바인딩: Steam 로그인 Add-on이 com.com2usplatform.hiveaxyl.steamworks 패키지를 함께 가져오므로 따로 설치하지 않아도 됩니다.

4. SDK 초기화

  • Hive Axyl SDK  Hive Axyl SDK를 앱에서 호출합니다.


    상세 절차: 모듈 초기화

앱 시작 지점에서 SDK를 한 번 초기화하고 인증, 토큰, 그리고 지원할 OS의 Add-on 모듈을 등록하세요. 레시피는 SDK를 초기화하지 않으므로, 초기화하지 않은 상태에서 호출하면 FailedPrecondition 오류로 실패합니다.

아래는 두 방식을 모두 지원하도록 모듈을 등록해 초기화하는 예제 코드입니다.

using Hive.Axyl.Auth;
using Hive.Axyl.Auth.Addon.WebAuth;
using Hive.Axyl.Core;
using Hive.Axyl.Core.Unity;
using Hive.Axyl.Storage;
#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
using Hive.Axyl.Auth.Addon.Steam;
#endif

var config = CoreConfig.CreateBuilder("{appId}").Build();

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

#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
    builder.AddSteamAuth();
#endif
});

{appId}에는 빌드할 실행 환경에 맞는 App ID를 입력하세요.

AddSteamAuth()를 조건부 컴파일로 감싼 이유는 Steam Add-on 어셈블리가 Windows, macOS, Linux 빌드와 Unity 에디터에만 포함되기 때문입니다. Android와 iOS 빌드에서는 이 메서드 자체가 없으므로 감싸지 않으면 컴파일 오류가 납니다.

AddWebAuth()는 모든 빌드에 어셈블리가 포함되므로 분기 없이 호출해도 됩니다. 실제 등록은 Android, iOS, macOS, Windows 빌드에서만 일어나고, AddSteamAuth()는 Windows와 macOS 빌드에서만 일어납니다. Unity 에디터에서는 둘 다 등록을 건너뜁니다.

앱에서 이미 안전한 저장소를 사용한다면 AddSecureStorage()는 등록하지 않아도 됩니다. 이 경우에도 DeviceKey와 세션 토큰을 앱 재시작 뒤에 다시 읽을 수 있어야 합니다.

5. Steamworks 초기화

Windows와 macOS에서는 Add-on이 Steamworks를 통해 인증 티켓을 받습니다. Hive Axyl SDK는 Steamworks를 초기화하지 않으므로 앱이 직접 초기화하고 유지해야 합니다.

앱 시작 시점에 SteamAPI.Init()을 한 번 호출하고, 매 프레임 SteamAPI.RunCallbacks()를 호출하세요. Steam 클라이언트 밖에서 개발용으로 실행한다면 실행 파일과 같은 위치에 steam_appid.txt 파일을 두고 Steam App ID를 적어 두세요.

SteamAPI는 Steam 로그인 Add-on이 함께 가져오는 Steamworks.NET 바인딩이 제공합니다. using Steamworks;를 추가하고, 6단계에서 앱 어셈블리에 com.rlabrecque.steamworks.net을 참조로 추가하세요. 이 코드도 Windows와 macOS 빌드에서만 컴파일되도록 조건부 컴파일로 감싸세요.

초기화하기 전에 레시피를 호출하면 FailedPrecondition 오류로 실패합니다.

브라우저 방식만 지원한다면 이 단계는 건너뛰세요.

6. 레시피 코드 설치

  • 레시피 코드  레시피 코드를 프로젝트에 복사합니다.

레시피는 패키지가 아니라 프로젝트에 복사해서 사용하는 소스 코드입니다. axyl-samples-unity 저장소에서 아래 항목을 Unity 프로젝트의 Assets/Recipes/ 아래로 복사하세요.

복사할 항목과 역할은 아래와 같습니다.

  • Recipes.asmdef: 레시피 공통 어셈블리 정의
  • AssemblyInfo.cs: 내부 헬퍼를 다른 레시피 어셈블리에 공개하는 설정
  • Helper/: 여러 레시피가 함께 사용하는 공통 코드
  • ProviderLogin/: ProviderLoginRecipe, 결과 유형, 자격 증명 소스 계약
  • ProviderLogin.Steam/: SteamCredentialSource
  • ProviderLogin.WebAuth/: SteamOpenIdCredentialSource, Steam이 돌려보낼 주소를 만드는 SteamRelayReturnTo, 브라우저 로그인 공통 코드

지원하지 않는 방식의 자격 증명 소스는 복사하지 않아도 됩니다. Steam 클라이언트 방식만 지원한다면 ProviderLogin.WebAuth/를, 브라우저 방식만 지원한다면 ProviderLogin.Steam/을 빼세요.

앱 코드에서 레시피를 호출하려면 앱 쪽 어셈블리 정의의 references에 아래 어셈블리를 추가하세요. 원본 Recipes.asmdef의 autoReferenced 값이 false이므로 앱 어셈블리가 자동으로 참조하지 않습니다.

{
  "name": "MyApp",
  "references": [
    "Hive.Axyl.Core",
    "Hive.Axyl.Auth",
    "Hive.Axyl.Auth.Addon.Steam",
    "Hive.Axyl.Auth.Addon.WebAuth",
    "Hive.Axyl.Storage",
    "com.rlabrecque.steamworks.net",
    "Hive.Axyl.Samples.Recipes",
    "Hive.Axyl.Samples.Recipes.ProviderLogin",
    "Hive.Axyl.Samples.Recipes.ProviderLogin.Steam",
    "Hive.Axyl.Samples.Recipes.ProviderLogin.WebAuth"
  ]
}

MyApp은 앱에서 사용하는 어셈블리 이름으로 바꾸고, 기존 설정과 참조는 유지하세요. Unity 어셈블리는 참조를 전이하지 않으므로 앱 코드가 직접 사용하는 어셈블리를 모두 여기에 적어야 합니다. Hive.Axyl.Core에는 CoreConfig와 HiveError가, Hive.Axyl.Auth에는 AddAuth()와 AddToken()이, Hive.Axyl.Auth.Addon.Steam에는 AddSteamAuth()와 티켓 반납 메서드가, Hive.Axyl.Auth.Addon.WebAuth에는 AddWebAuth()가, Hive.Axyl.Storage에는 AddSecureStorage()가, com.rlabrecque.steamworks.net에는 5단계에서 사용하는 SteamAPI와 SteamUser가 들어 있습니다.

AddSecureStorage()를 등록하지 않는다면 Hive.Axyl.Storage는 적지 않아도 됩니다. 한 방식만 지원한다면 다른 방식의 Add-on과 레시피 어셈블리도 빼세요.

자격 증명 소스 폴더만 복사하면 컴파일되지 않습니다

SteamCredentialSource와 SteamOpenIdCredentialSource는 ProviderLogin/의 자격 증명 소스 계약을 구현하고, ProviderLoginRecipe는 Helper/의 PKCE 생성 코드와 세션 준비 코드를 사용합니다. Helper/, Recipes.asmdef, AssemblyInfo.cs, ProviderLogin/을 함께 복사하세요.

7. ClientId와 DeviceKey 준비

ProviderLoginRecipe의 생성자는 ClientId와 DeviceKey를 받습니다. ClientId는 공통 사전 준비에서 확인한 값으로, Hive 콘솔이 프로젝트마다 발급합니다. DeviceKey는 Hive Axyl 인증 서버가 로그인 세션을 기기 단위로 구분하는 값이며, 앱이 직접 만들어 보관합니다.

레시피는 DeviceKey를 만들거나 저장하지 않으므로, 아래 조건에 맞게 만들고 관리하세요.

  • 기기마다 다른 값. UUID 같은 난수 권장
  • 최초 실행 때 한 번 만들어 저장하고, 이후 모든 로그인에서 재사용하는 값
  • 22자 이상 64자 이하의 길이
  • 공백과 제어 문자를 제외한 ASCII 문자로만 이루어진 값
저장소를 읽지 못했다고 새 DeviceKey로 덮어쓰지 마세요

값이 사라진 것이 아니라 읽기에만 실패했을 수 있습니다. 먼저 저장소 접근 문제를 해결하거나 다시 읽기를 시도하세요.

PKCE 값은 준비하지 않아도 됩니다. 레시피가 호출할 때마다 한 쌍을 직접 만들어 로그인 호출과 토큰 발급 호출에 나누어 전달합니다.

빈 값을 전달하면 예외가 발생합니다

ClientId나 DeviceKey가 비어 있으면 레시피는 결과를 반환하지 않고 ArgumentException을 던집니다. 자격 증명 소스를 null로 전달할 때도 ArgumentNullException을 던집니다. 저장소에서 읽은 값을 그대로 넘기기 전에 비어 있는지 먼저 확인하세요.

8. Steam 자격 증명 소스 준비

레시피에 로그인할 외부 인증 제공자를 알려 주려면 자격 증명 소스를 만들어 전달해야 합니다. Steam은 OS마다 인증 방법이 다르므로 실행 중인 OS에 맞는 소스를 고르세요.

8.1. Steam 클라이언트 방식

SteamCredentialSource는 Steam 클라이언트에서 인증 티켓을 받아 옵니다. 생성자 인자는 아래와 같습니다.

인자 필수 여부 준비 방법
identity 필수 Steamworks가 티켓을 만들 때 사용하는 식별 문자열입니다. Hive Axyl 인증 서버가 검증할 때 쓰는 값과 같아야 하며, 서버는 Steam ID64를 SHA-256으로 해시해 16진 소문자로 바꿔 앞 30자를 사용합니다.
steamId 필수 Steamworks에서 읽은 Steam ID64입니다. identity를 만들 때도 필요하므로 먼저 읽으세요.

두 값은 Steam 로그인 Add-on이 제공하지 않으므로 앱이 Steamworks에서 직접 읽고 만듭니다. 아래는 두 값을 준비하는 예제 코드입니다.

using System;
using System.Security.Cryptography;
using System.Text;
using Steamworks;

string steamId = SteamUser.GetSteamID().m_SteamID.ToString();

string identity;
using (var sha = SHA256.Create())
{
    byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(steamId));
    identity = BitConverter.ToString(hash)
        .Replace("-", string.Empty)
        .ToLowerInvariant()
        .Substring(0, 30);
}

앞 30자만 쓰는 이유는 Steam이 식별 문자열의 길이를 제한하기 때문입니다. 앱 서버가 다른 식별 문자열로 검증하도록 정해 두었다면 그 값을 그대로 넣으세요.

identity가 비어 있거나 공백만 있으면 생성자에서 ArgumentException이 발생합니다. Hive Axyl SDK 메서드를 직접 호출할 때와 달리 레시피는 빈 문자열을 허용하지 않습니다.

10단계에서 반납할 티켓 값은 로그인 결과에 담기지 않습니다. 자격 증명 소스를 감싸는 클래스를 앱에 만들어 티켓을 따로 보관하세요. IProviderCredentialSource는 공개된 계약이므로 레시피를 고치지 않고 감쌀 수 있습니다.

using System.Threading;
using System.Threading.Tasks;
using Hive.Axyl.Samples.Recipes;

public sealed class SteamTicketKeepingSource : IProviderCredentialSource
{
    private readonly SteamCredentialSource m_inner;

    public SteamTicketKeepingSource(string identity, string steamId = null)
    {
        m_inner = new SteamCredentialSource(identity, steamId);
    }

    public string TicketHex { get; private set; }

    public LoginProvider Provider => m_inner.Provider;

    public async Task<ProviderCredentialOutcome> AcquireAsync(
        CancellationToken cancellationToken = default)
    {
        ProviderCredentialOutcome outcome = await m_inner.AcquireAsync(cancellationToken);
        TicketHex = outcome.Credential?.ProviderToken;
        return outcome;
    }
}

이 클래스와 위의 identity 준비 코드는 Windows와 macOS 빌드에서만 컴파일되어야 합니다. 8.3단계처럼 조건부 컴파일로 감싸거나, includePlatforms를 Windows와 macOS로 제한한 별도 어셈블리 정의를 만들어 그 안에 두세요.

8.2. 브라우저 방식

SteamOpenIdCredentialSource는 브라우저에서 Steam 로그인 페이지를 열고, 돌아온 콜백에서 Steam 식별자와 인증 응답을 꺼냅니다. Steam은 앱 고유 스킴 주소로 사용자를 돌려보내지 못하므로, Android와 iOS에서는 로그인 결과가 Hive Axyl이 운영하는 중계 주소를 거쳐 앱 콜백 주소로 돌아옵니다.

생성자 인자는 아래와 같습니다.

인자 필수 여부 준비 방법
returnTo 필수 Steam이 사용자를 돌려보낼 절대 http 또는 https 주소입니다. Android와 iOS에서는 SteamRelayReturnTo.Build()로 만든 Hive Axyl 중계 주소를 넣습니다. 형식이 맞지 않으면 생성자에서 ArgumentException이 발생합니다.
redirectUri 선택 앱이 콜백을 기다리는 주소가 returnTo와 다를 때 넣습니다. Android와 iOS에서는 앱 콜백 주소 {appId}://oauth-callback을 넣습니다. 생략하면 returnTo를 그대로 사용합니다.

8.2.1. Steam이 돌려보낼 주소 구성

SteamRelayReturnTo.Build()는 Hive Axyl 중계 주소 뒤에 앱 콜백 주소와 로그인 시도별 난수를 쿼리 파라미터로 붙여 returnTo를 만듭니다. Hive Axyl 중계 주소는 Steam이 보낸 콜백 파라미터를 바꾸지 않고 이 앱 콜백 주소로 전달합니다. 아래 값을 인자로 넣으세요.

  • relayBase: Hive Axyl 중계 주소 https://core-api.hiveaxyl.com/auth/v1/provider/callback
  • appCallback: 앱 콜백 주소 {appId}://oauth-callback. {appId}는 Android 패키지 이름이 아니라 Hive 콘솔에서 만든 App ID
  • nonce: 로그인 시도마다 새로 만든 난수
using System;
using Hive.Axyl.Samples.Recipes;

string appCallback = "{appId}://oauth-callback";
string returnTo = SteamRelayReturnTo.Build(
    "https://core-api.hiveaxyl.com/auth/v1/provider/callback",
    appCallback,
    Guid.NewGuid().ToString("N"));

IProviderCredentialSource source = new SteamOpenIdCredentialSource(returnTo, appCallback);

returnTo에는 로그인 시도별 난수가 들어가므로 로그인할 때마다 returnTo와 소스를 새로 만드세요. 인가 URL과 state 값은 준비하지 않아도 됩니다. 자격 증명 소스가 Steam OpenID 규격에 맞는 주소를 직접 만들고, 돌아온 콜백의 openid.return_to가 이번 로그인에서 만든 returnTo와 같은지도 직접 확인합니다.

8.2.2. Android 앱 콜백 스킴 등록

Android에서는 앱 콜백 주소의 스킴인 App ID를 WebAuth Add-on의 콜백 화면이 받도록 앱에 등록하세요. 등록하지 않으면 Hive Axyl 중계 주소가 보낸 결과가 앱에 도착하지 않아 로그인이 끝나지 않습니다. 등록 방법은 Android 리다이렉트 URI 준비를 참조하고, 다른 로그인 수단이 이미 다른 스킴을 사용한다면 여러 스킴 등록에 따라 두 스킴을 모두 등록하세요. iOS는 OS 인증 세션이 스킴을 직접 확인하므로 등록하지 않아도 됩니다.

8.3. 방식에 따라 소스 고르기

두 방식을 모두 지원한다면 조건부 컴파일로 나누세요. SteamCredentialSource가 들어 있는 레시피 어셈블리는 Windows, macOS, Linux 빌드와 Unity 에디터에만 포함되므로, Android와 iOS 빌드에서 감싸지 않으면 컴파일 오류가 납니다. identity와 steamId는 8.1에서, returnTo와 appCallback은 8.2에서 만든 값입니다.

using Hive.Axyl.Samples.Recipes;

IProviderCredentialSource source;

#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
var steamSource = new SteamTicketKeepingSource(identity, steamId);
source = steamSource;
#else
source = new SteamOpenIdCredentialSource(returnTo, appCallback);
#endif

한 방식만 지원한다면 그쪽 소스만 만들면 됩니다.

9. Steam 로그인 호출

  • 레시피 코드  레시피 코드를 앱에서 호출합니다.

준비한 자격 증명 소스를 LoginWithProviderAsync()에 전달하세요. 레시피가 Steam에서 자격 증명을 받아 로그인하고 세션까지 활성화합니다.

앱이 로그인 대기를 직접 중단해야 할 때를 대비해 CancellationTokenSource를 함께 준비하세요.

using System.Threading;
using Hive.Axyl.Samples.Recipes;

var recipe = new ProviderLoginRecipe(clientId, deviceKey);

var cancellation = new CancellationTokenSource();
CancellationToken token = cancellation.Token;

LoginWithProviderOutcome outcome = await recipe.LoginWithProviderAsync(source, token);

로그인을 시작한 장면을 벗어나는 것처럼 앱이 먼저 대기를 끝내야 할 때 cancellation.Cancel()을 호출하고, 호출이 끝나면 cancellation.Dispose()로 정리하세요. 사용자가 Steam 로그인 페이지를 닫은 경우에는 호출하지 마세요. 레시피가 UserCanceled로 알려 줍니다.

레시피가 내부에서 수행하는 작업은 아래와 같습니다.

구분 호출 확인할 곳
레시피 코드 인증, 토큰, 세션 모듈이 등록되었는지 확인 없음
Add-on Steam 클라이언트 방식에서 GetAuthTicketForWebApiAsync()로 인증 티켓 확보 Windows와 macOS
Add-on 브라우저 방식에서 OpenAsync()로 Steam 로그인 페이지를 열고 Hive Axyl 중계 주소가 앱 콜백 주소로 전달한 콜백 수신 웹 로그인 세션 열기
레시피 코드 브라우저 방식에서 콜백의 openid.mode와 openid.return_to를 확인하고, openid.claimed_id의 Steam ID64와 콜백 쿼리 문자열을 자격 증명으로 확보 Windows와 macOS 외 OS
레시피 코드 PKCE 값 한 쌍을 만들어 로그인 호출과 토큰 발급 호출에 나눠 전달 호출 파라미터값 준비
Hive Axyl SDK LoginProviderAsync()로 Steam 자격 증명을 전달하고 인가 코드 수신 외부 인증 제공자 로그인
Hive Axyl SDK IssueTokenAsync()로 인가 코드를 액세스 토큰과 리프레시 토큰으로 교환 토큰 발급과 세션 활성화
Hive Axyl SDK SetSession()으로 로그인 세션 활성화 토큰 발급과 세션 활성화

위 표의 상세 절차는 Hive Axyl SDK 메서드를 직접 호출할 때를 기준으로 쓰여 있습니다. PKCE 값이나 인가 URL을 만드는 작업처럼 레시피가 대신하는 단계는 앱에서 다시 구현하지 마세요. 각 호출이 무엇을 주고받는지 확인할 때만 참조하세요.

모듈이 등록되어 있지 않으면 모듈 확인 단계에서 FailedPrecondition 오류로 멈춥니다. Success가 반환되면 세션까지 준비된 상태이므로 토큰 발급이나 세션 활성화 코드를 따로 호출하지 마세요. 세션은 사용할 수 있는 토큰을 받은 뒤에만 활성화되므로, 실패한 시도는 이미 열려 있던 세션을 건드리지 않습니다.

10. 인증 티켓 반납

  • Add-on  Add-on 메서드를 앱에서 직접 호출합니다.


    상세 절차: 인증 티켓 반납

Steam 클라이언트 방식에서는 로그인 결과를 받은 뒤 인증 티켓을 반납하세요. Steam은 앱이 동시에 보유할 수 있는 티켓 개수를 제한하므로, 반납하지 않고 계속 발급하면 이후 로그인이 실패합니다. 레시피는 티켓을 반납하지 않습니다.

반납할 티켓 값은 8.1단계에서 만든 자격 증명 소스가 보관하고 있습니다. 로그인 결과에는 티켓이 담기지 않으므로 그 값을 사용하세요. 이 코드는 8.3단계에서 자격 증명 소스를 만들었던 곳과 같은 범위에 두어야 steamSource를 읽을 수 있습니다.

반납 시점은 로그인이 성공했든 실패했든 결과를 받은 다음입니다. 검증이 끝나기 전에 반납하면 Steam이 티켓을 무효로 판단해 로그인이 실패합니다.

#if UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
using Hive.Axyl.Auth.Addon.Steam;
using Hive.Axyl.Core;

// LoginWithProviderAsync의 결과를 받은 뒤 호출합니다.
if (steamSource.TicketHex != null
    && HiveCore.TryResolve<ISteamPlugin>(out var steam))
{
    steam.ReleaseTicket(steamSource.TicketHex);
}
#endif

ReleaseTicket()은 Unity 메인 스레드에서 호출하세요. 이미 반납했거나 알 수 없는 티켓을 넘겨도 아무 동작도 하지 않습니다.

이 코드를 조건부 컴파일로 감싼 이유는 ISteamPlugin이 들어 있는 어셈블리가 Android와 iOS 빌드에 포함되지 않기 때문입니다. 브라우저 방식에는 반납할 티켓이 없으므로 이 코드가 실행되지 않아도 됩니다.

11. 로그인 결과 처리

  • 앱 코드  앱에서 직접 구현합니다.


    상세 절차: HiveError 정보

LoginWithProviderOutcome은 Status로 로그인 결과를 알려 줍니다. FailedStep은 진단용 값이므로 앱의 정상 흐름을 분기하는 기준으로 사용하지 마세요.

Status 확인할 값 앱 처리
Success PlayerId, IsBlocked 이용 제한 상태가 아니면 로그인 후 화면으로 이동합니다.
BusinessOutcome BusinessOutcome, UnknownOutcomeCode 거절 사유에 맞게 분기하고, 모르는 값은 실패로 처리해 기록합니다.
UserCanceled 없음 사용자가 Steam 로그인 페이지를 닫았거나 로그인을 거부한 상태이므로 이전 화면으로 돌아갑니다.
Failure Error.Code, Error.TraceId 기술 문제를 기록하고 재시도 흐름을 제공합니다.

UserCanceled는 브라우저 방식에서만 나옵니다. Steam 클라이언트 방식에는 사용자가 닫을 로그인 화면이 없기 때문입니다.

IsBlocked가 true이면 로그인은 성공했지만 이용이 제한된 계정입니다. 제한 종류와 안내 방법은 이용 제한을 참조하세요.

PlayerId는 Hive Axyl이 사용자 한 명에게 부여하는 고유 식별자입니다. 같은 Steam 계정으로 다시 로그인하면 같은 값이 돌아오므로, 앱은 이 값으로 사용자의 플레이 데이터를 구분합니다.

오류를 기록할 때는 FailedStep을 함께 남기세요. 값은 None, Resolve, AcquireCredential, LoginProvider, SessionSetup 다섯 가지이며, 어느 단계에서 멈췄는지 알려 줍니다.

11.1. 거절 사유 처리

BusinessOutcome 값은 로그인이 성사되지 않은 사유이므로, 값마다 사용자에게 보여 줄 안내가 다릅니다. 레시피는 두 번의 서버 호출에서 나온 거절 사유를 하나의 값으로 묶어 돌려주므로 두 곳을 모두 확인하세요.

위 두 곳에 없는 거절 사유도 있습니다. TemporarilyUnavailable은 Hive Axyl 인증 서버가 판정을 내리지 못하고 요청을 되돌린 상태이므로 같은 요청을 다시 보내세요. 곧바로 반복하지 말고 1초, 3초, 6초처럼 간격을 늘려 가며 재시도하세요.

레시피가 이 SDK 버전이 알지 못하는 결과를 받으면 BusinessOutcome이 Unrecognized가 됩니다. 이때는 UnknownOutcomeCode로 두 경우를 구분하세요. 값이 있으면 서버가 보낸 결과 코드를 이 SDK 버전이 모른다는 뜻이고, 비어 있으면 SDK는 아는 결과지만 레시피가 이름을 붙이지 않았다는 뜻입니다. 어느 쪽이든 위 두 곳에서 찾지 말고 UnknownOutcomeCode와 RawJson을 기록한 뒤 실패로 처리하세요. 두 값은 사용자에게 표시하지 말고 앱 오류 기록에만 사용하세요.

레시피는 상세 절차에 적힌 이름을 아래와 같이 바꿔 돌려줍니다.

  • TerminateService: ServiceTerminated
  • InvalidClientId: InvalidClient
  • InvalidGrant: InvalidAuthorizationCode
  • InvalidGrantExpired: ExpiredAuthorizationCode
  • InvalidGrantCodeChallenge: CodeChallengeMismatch
  • InvalidGrantRefreshToken: InvalidRefreshToken

InvalidRefreshToken은 리프레시 토큰으로 토큰을 다시 발급받을 때만 나오므로 이 레시피에서는 발생하지 않습니다. 나머지 다섯 개는 이 레시피에서도 그대로 나타납니다.

ProviderTokenError는 Hive Axyl 인증 서버가 Steam에 확인했을 때 인증 결과가 유효하지 않았다는 뜻입니다. 사용자를 다시 인증시키세요.

11.2. 취소와 미지원 환경 처리

Status가 Failure라고 해서 모두 사용자에게 실패로 안내할 것은 아닙니다. 앱이 대기를 중단한 경우와 Steam 로그인을 실행할 수 없는 환경도 여기로 들어오므로 Error.Code로 구분하세요.

Error.Code 의미 앱 처리
Cancelled 앱이 CancellationToken으로 로그인을 취소한 상태. 사용자가 Steam 로그인 페이지를 닫은 UserCanceled와 다른 결과 UserCanceled와 안내 메시지를 구분합니다.
Unavailable 호출을 끝까지 실행하지 못한 상태 아래 원인별 처리를 따릅니다.
FailedPrecondition 호출에 필요한 준비가 끝나지 않은 상태. FailedStep이 Resolve이면 4단계에서 인증과 토큰 모듈을 등록하지 않았거나 SDK를 초기화하지 않은 경우이고, AcquireCredential이면 Steam 클라이언트가 실행 중이 아니거나, 5단계의 Steamworks 초기화를 하지 않았거나, 앞서 시작한 티켓 요청이 아직 끝나지 않은 경우 FailedStep에 해당하는 준비 상태를 확인합니다. 티켓 요청이 겹치지 않도록 응답이 돌아올 때까지 로그인 버튼을 잠금 상태로 두세요.
Internal 호출 과정에서 다음 단계에 필요한 값을 얻지 못한 상태. Steam 클라이언트 방식에서는 Steamworks 호출 자체가 실패했거나 유효하지 않은 티켓을 돌려준 경우이고, 브라우저 방식에서는 콜백이 Steam의 승인 응답이 아니거나 Steam 식별자를 담고 있지 않은 경우 재시도로 해결되지 않으므로 Error.TraceId와 FailedStep을 기록합니다.
PermissionDenied 브라우저에서 돌아온 콜백의 openid.return_to가 이번 로그인에서 만든 returnTo와 다른 상태. 이번 로그인에서 시작하지 않은 콜백이므로 레시피는 로그인을 요청하지 않음 로그인 화면을 유지하고, 8.2단계처럼 returnTo와 소스를 새로 만들어 다시 시도하게 합니다.
Unknown Steamworks가 예상하지 못한 결과를 돌려준 상태 Steamworks가 반환한 원래 값이 Error.ExternalCode에 담기므로 함께 기록합니다.

Error.Code가 HiveErrorCode.Unavailable인 원인은 네 가지이며, 원인별 처리는 아래와 같습니다.

  • Steam Add-on 미등록: Unity 에디터에서 실행했거나 4단계의 AddSteamAuth() 등록을 빼놓은 경우이므로, 등록 여부를 점검한 뒤 실제 빌드에서 다시 시도하세요.
  • Steam 클라이언트에 로그인한 사용자 없음: Steam 클라이언트에 로그인하도록 안내하세요.
  • 웹 로그인 세션 Add-on 미등록: 3단계의 Add-on 설치와 4단계의 AddWebAuth() 등록을 확인하세요.
  • 네트워크 단절이나 서비스 일시 중단: 잠시 뒤에 다시 시도하도록 안내하세요.

12. 동작 확인

  • 앱 코드  앱에서 동작을 확인합니다.

지원하는 방식마다 실제 기기에서 확인하세요. Unity 에디터에서는 두 Add-on 모두 등록되지 않아 Unavailable 오류가 반환되므로 자격 증명 획득부터 검증할 수 없습니다.

Steam 클라이언트 방식은 아래 순서로 확인하세요.

  1. Steam 클라이언트를 실행하고 로그인한 상태에서 앱을 실행하세요.
  2. Steam 로그인을 실행하고 Success와 PlayerId를 확인하세요.
  3. 10단계의 티켓 반납이 호출되는지 확인하세요.
  4. 로그인을 연속해서 여러 번 실행해 티켓 발급이 계속 성공하는지 확인하세요. 반납을 빼놓으면 이 단계에서 실패합니다.
  5. 앱을 완전히 종료한 뒤 다시 실행해 같은 Steam 계정으로 로그인하고, PlayerId가 같은지 확인하세요.
  6. Steam 클라이언트에서 로그아웃한 뒤 로그인을 실행해 Unavailable이 반환되는지 확인하세요. Steam 클라이언트를 종료한 경우에는 FailedPrecondition이 반환됩니다.

브라우저 방식은 아래 순서로 확인하세요.

  1. 앱을 실행하고 Steam 로그인을 실행하세요.
  2. 브라우저에 Steam 로그인 페이지가 뜨는지 확인하고 로그인을 완료하세요.
  3. 앱으로 돌아와 Success와 PlayerId를 확인하세요. Android에서 앱으로 돌아오지 않으면 8.2.2. Android 앱 콜백 스킴 등록을 확인하세요.
  4. 앱을 완전히 종료한 뒤 다시 실행해 같은 Steam 계정으로 로그인하고, PlayerId가 같은지 확인하세요.
  5. Steam 로그인 페이지에서 취소해 UserCanceled가 반환되는지 확인하세요.

다음 단계

로그인한 사용자가 앱을 다시 실행할 때 로그인 화면을 건너뛰도록 하려면 자동 로그인을 참조하세요.

이미 로그인한 계정에 다른 로그인 수단을 추가로 연결하려면 외부 인증 제공자 연동 활용 가이드를 참조하세요.

로그인한 계정에서 빠져나와 다른 계정으로 로그인하도록 하려면 로그아웃 활용 가이드를 참조하세요.