자동 로그인
이전에 로그인한 사용자가 앱을 다시 실행했을 때 로그인 화면을 거치지 않고 바로 앱에 들어가게 하는 흐름입니다. Hive Axyl SDK는 세션을 메모리에만 유지하고 기기에 저장하지 않습니다. 따라서 앱 클라이언트가 인증 정보를 직접 보관했다가 다음 실행에서 세션을 복원해야 합니다.
자동 로그인은 메서드 하나로 끝나지 않습니다. 앱 클라이언트가 Hive Axyl SDK의 기능을 순서대로 호출해 완성합니다.
flowchart TD
A(["앱 실행"])
B(["저장한 인증 정보 불러오기"])
C(["저장한 토큰으로 세션 복원 요청"])
D(["새 토큰 발급"])
E(["세션 등록 후 앱 진입"])
F(["로그인 화면 노출"])
A --> B --> C --> D --> E
B -- 저장된 값 없음 --> F
C -- 복원 실패 --> F
D -- 발급 실패 --> F 빌딩 블록
자동 로그인에 사용하는 빌딩 블록은 아래와 같습니다.
ISecureStorage: 액세스 토큰과 리프레시 토큰처럼 다음 실행에도 필요한 값을 기기에 암호화해 저장하고 불러오는 보안 저장소IAuthService.LoginWithAccessTokenAsync: 저장해 둔 액세스 토큰이 아직 유효한지 Hive Axyl 인증 서버에서 확인하며 로그인하고, 성공하면 인가 코드를 반환하는 메서드ITokenService.IssueTokenAsync: 인가 코드 또는 리프레시 토큰으로 새 액세스 토큰과 리프레시 토큰을 발급하는 메서드ISessionManager.SetSession: 발급받은 토큰을 세션에 등록해 로그인 상태로 만드는 메서드AuthTokenRefresh.Enable: 세션을 등록한 뒤 만료된 액세스 토큰을 리프레시 토큰으로 자동 갱신하는 기능을 켜는 메서드
Hive Axyl SDK는 위 빌딩 블록만 제공합니다. 어떤 값을 어떤 키로 저장할지, 앱 실행 시 어느 시점에 복원할지는 앱 클라이언트에서 정합니다.
Warning
검증을 마치기 전에 저장된 토큰을 SetSession()으로 세션에 등록하지 마세요. 검증 호출이 실패했을 때 세션 만료로 잘못 처리되어 자동 갱신과 세션 이벤트가 어긋납니다. SetSession()은 복원 흐름 전체가 성공한 뒤 한 번만 호출합니다.
1. 인증 정보 저장
로그인에 성공해 세션을 등록한 직후, 다음 실행에 필요한 값을 보안 저장소에 저장합니다. 저장할 값은 아래와 같습니다.
- 액세스 토큰과 리프레시 토큰
- Player ID
deviceKey
deviceKey는 기기 식별 값이며, 앱을 처음 실행할 때 만들어 계정 유형과 관계없이 계속 재사용합니다. 만들고 보관하는 규칙은 deviceKey를 참조하세요. 게스트 계정이라면 재로그인 자격 증명인 guestToken도 함께 저장하세요. 다만 그 계정에 로그인 수단을 처음 연동하면 게스트 토큰이 무효가 되므로, 연동에 성공한 시점에 저장해 둔 게스트 토큰을 지우세요. 자세한 내용은 계정 연동 처리 및 조회를 참조하세요.
using Hive.Axyl.Core;
using Hive.Axyl.Storage;
// 보안 저장소는 에디터처럼 지원하지 않는 환경에서는 등록되지 않으므로 TryResolve로 확인합니다.
if (!HiveCore.TryResolve<ISecureStorage>(out var storage))
{
return; // 인증 정보를 저장하지 않으므로 다음 실행에서 자동 로그인을 쓰지 않습니다.
}
ISessionManager session = HiveCore.Resolve<ISessionManager>();
SessionSnapshot snapshot = session.GetSnapshot();
// 아래 키는 앱이 정한 값의 예시입니다(SDK가 정하지 않음). 로그아웃과 계정 삭제에서도 같은 키로 지웁니다.
await storage.SaveAsync(new SecureStorageSaveRequest {
Key = "hive.axyl.auth.access_token",
Value = snapshot.AccessToken,
});
await storage.SaveAsync(new SecureStorageSaveRequest {
Key = "hive.axyl.auth.refresh_token",
Value = snapshot.RefreshToken,
});
await storage.SaveAsync(new SecureStorageSaveRequest {
Key = "hive.axyl.auth.player_id",
Value = snapshot.PlayerId.ToString(),
});
SaveAsync()가 AccessDenied나 DataCorrupted를 반환하면 저장에 실패한 상태입니다. 이때는 다음 실행에서 자동 로그인이 동작하지 않으므로 사용자가 다시 로그인해야 합니다.
2. 앱 실행 시 세션 복원
앱을 실행하면 로그인 화면을 그리기 전에 복원을 시도합니다. 저장한 값이 없으면 곧바로 로그인 화면을 노출하세요.
2.1. 저장한 액세스 토큰으로 복원
저장한 액세스 토큰이 아직 유효하면 사용자를 다시 인증시키지 않고 세션을 되살릴 수 있습니다. LoginWithAccessTokenAsync()를 호출할 때 저장한 액세스 토큰을 ApiCallContext.WithAccessToken()으로 실어 보내면, Hive Axyl 인증 서버가 그 토큰을 검증하고 새 인가 코드를 반환합니다.
using Hive.Axyl.Auth;
using Hive.Axyl.Core;
IAuthService auth = HiveCore.Resolve<IAuthService>();
// CreatePkce()는 게스트 계정 생성에서 정의한 보조 코드입니다.
var (codeVerifier, codeChallenge) = CreatePkce();
var result = await auth.LoginWithAccessTokenAsync(
new TokenLoginRequest {
ClientId = "{clientId}",
CodeChallenge = codeChallenge,
CodeChallengeMethod = CodeChallengeMethod.S256,
},
ApiCallContext.WithAccessToken(storedAccessToken));
if (result is AuthLoginWithAccessTokenResult.Success success
&& success.Data.PlayerId == storedPlayerId)
{
// 인가 코드를 토큰으로 교환하고 세션에 등록합니다.
await StartSessionAsync(success.Data.AuthorizationCode, codeVerifier, success.Data.PlayerId);
}
응답의 Data.PlayerId가 저장해 둔 Player ID와 다르면 다른 계정의 세션이 확정될 수 있으므로 즉시 중단하고, 저장한 값을 지우지 말고 사용자가 직접 로그인하도록 안내하세요.
StartSessionAsync()는 인가 코드를 토큰으로 교환하고 세션에 등록하는 보조 코드이며, 구현은 세션 활성화하기를 참조하세요.
2.2. 저장한 리프레시 토큰으로 복원
저장한 액세스 토큰이 만료되어 2.1 단계가 실패하면, 리프레시 토큰으로 새 토큰을 발급받습니다. IssueTokenAsync()에 RefreshTokenTokenRequest를 전달하면 세션이 없는 상태에서도 토큰을 발급합니다.
using System;
using Hive.Axyl.Auth;
using Hive.Axyl.Core;
ITokenService token = HiveCore.Resolve<ITokenService>();
ISessionManager session = HiveCore.Resolve<ISessionManager>();
var issueResult = await token.IssueTokenAsync(new RefreshTokenTokenRequest {
GrantType = "refresh_token",
ClientId = "{clientId}",
RefreshToken = storedRefreshToken,
});
if (issueResult is TokenIssueTokenResult.Success issued)
{
session.SetSession(
issued.Data.AccessToken,
issued.Data.RefreshToken ?? string.Empty,
storedPlayerId,
DateTimeOffset.UtcNow.ToUnixTimeSeconds() + issued.Data.ExpiresIn);
// 새로 발급된 토큰을 보안 저장소에 다시 저장합니다.
}
Hive Axyl 인증 서버는 리프레시 토큰을 쓸 때마다 새 값으로 바꾸고 기존 값을 무효로 만듭니다. 발급 결과에 따라 저장한 값을 아래와 같이 처리하세요. 판단 기준은 공통 오류 처리를 참조하세요.
Success: 저장한 액세스 토큰과 리프레시 토큰을 반드시 새 값으로 갱신하세요.InvalidGrantRefreshToken: 리프레시 토큰이 무효로 확정되었으므로, 게스트 계정의guestToken과deviceKey는 남겨 두고 저장한 액세스 토큰과 리프레시 토큰을 지운 뒤 로그인 화면을 노출하세요.TemporarilyUnavailable: 저장한 값을 지우지 말고, 간격을 두고 같은 요청을 다시 보내세요.- 네트워크 오류처럼 무효 여부를 확정하지 못한 실패: 저장한 값을 지우지 마세요.
2.3. 재로그인으로 되돌아가기
두 경로 모두 실패하면 자동 로그인을 포기하고 로그인 화면을 노출합니다. 게스트 계정은 저장해 둔 guestPlayerId, guestToken, deviceKey로 다시 로그인해 같은 Player ID를 되찾을 수 있습니다. 구현은 게스트 로그인을 참조하세요.
3. 액세스 토큰 자동 갱신
세션을 등록한 뒤에도 액세스 토큰은 일정 시간이 지나면 만료됩니다. AuthTokenRefresh.Enable()을 한 번 호출해 두면, 만료된 토큰으로 메서드를 호출했을 때 Hive Axyl SDK가 세션의 리프레시 토큰으로 새 토큰을 발급받아 세션을 갱신하고 원래 요청을 이어서 처리합니다. 사용자가 따로 조작하지 않아도 앱 이용이 끊기지 않습니다.
3.1. 자동 갱신 켜기
SDK를 초기화한 뒤 AuthTokenRefresh.Enable()을 한 번 호출하세요.
{baseUrl}에는 ITokenService가 연결하는 토큰 서버 주소를 입력하세요. AddToken()을 인자 없이 등록했다면 https://core-api.hiveaxyl.com입니다. Enable()은 한 번만 호출할 수 있습니다. SDK를 초기화하기 전에 호출하거나 두 번 호출하면 InvalidOperationException이 발생합니다.
Warning
세션이 살아 있는 동안에는 Hive Axyl SDK가 자동 갱신을 전담합니다. 세션이 있는 상태에서 앱이 refresh_token 방식의 IssueTokenAsync()를 직접 호출하면 세션에 있던 리프레시 토큰이 무효가 되므로 호출하지 마세요. 앱이 직접 호출하는 경우는 2.2 단계처럼 세션이 아직 없는 복원 시점뿐입니다.
3.2. 갱신된 토큰 저장
자동 갱신으로 발급된 토큰은 세션에만 반영되고 보안 저장소에는 반영되지 않습니다. 리프레시 토큰은 갱신할 때마다 새 값으로 바뀌고 이전 값은 무효가 되므로, 저장한 값을 교체하지 않으면 다음 실행 때 자동 로그인이 실패합니다.
OnSessionRefreshed 이벤트는 세션의 토큰이 새로 등록될 때마다 최신 SessionSnapshot과 함께 발생합니다. 이 이벤트를 구독해 1. 인증 정보 저장과 같은 키로 저장한 값을 교체하세요.
using Hive.Axyl.Core;
using Hive.Axyl.Storage;
// 보안 저장소가 없는 환경(에디터 등)에서는 저장한 토큰도 없으므로 구독하지 않습니다.
if (!HiveCore.TryResolve<ISecureStorage>(out var storage))
{
return;
}
ISessionManager session = HiveCore.Resolve<ISessionManager>();
session.OnSessionRefreshed += async snapshot =>
{
await storage.SaveAsync(new SecureStorageSaveRequest {
Key = "hive.axyl.auth.access_token",
Value = snapshot.AccessToken,
});
await storage.SaveAsync(new SecureStorageSaveRequest {
Key = "hive.axyl.auth.refresh_token",
Value = snapshot.RefreshToken,
});
};
3.3. 갱신 실패 처리
Hive Axyl 인증 서버가 리프레시 토큰을 무효로 판정하면 자동 갱신이 실패하고 세션이 종료되며 OnSessionExpired 이벤트가 발생합니다. 이 이벤트를 구독해 저장한 액세스 토큰과 리프레시 토큰을 지우고 로그인 화면으로 안내하세요. 게스트 계정의 guestToken과 deviceKey는 지우지 말고 그대로 두세요. 이 이벤트는 로그아웃처럼 앱이 ClearSession()으로 세션을 직접 정리할 때도 발생합니다.
네트워크 오류처럼 리프레시 토큰의 유효성을 확정하지 못한 갱신 실패에서는 세션이 유지됩니다. 다만 이런 실패가 세 번 연속으로 발생하면 OnSessionExpired 이벤트 없이 세션이 끝나고 ISessionManager.IsLoggedIn이 false가 됩니다. 이때 저장한 인증 정보는 여전히 유효하므로 지우지 말고, 2. 앱 실행 시 세션 복원과 같은 방법으로 세션을 다시 등록하세요. 호출 결과별 처리 기준은 토큰 자동 갱신 실패를 참조하세요.
연관 문서
- 세션 활성화하기: 토큰을 세션에 등록하는 방법
- 여러 계정 간 전환: 여러 계정의 인증 정보를 보관하고 세션을 바꾸는 방법
- 공통 오류 처리: 저장한 인증 정보를 보존할지 삭제할지 판단하는 기준