> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-Auth SDK API 레퍼런스

각종 프로그래밍 언어용 GS2-Auth SDK의 모델 사양과 API 레퍼런스



## 모델

### AccessToken

액세스 토큰<br>

사용자 인증 후 발급되는 액세스 토큰을 관리하는 모델입니다.<br>
액세스 토큰은 사용자가 서비스에 로그인되어 있는 동안 해당 세션의 신원을 증명하는 데 사용됩니다.<br>
토큰에는 유효기간이 설정되어 있으며, 만료되면 재인증이 필요합니다.


|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| token | string |  | ✓ |  |  ~ 1024자 | 액세스 토큰<br>액세스를 인증하기 위한 토큰입니다.<br>이 토큰은 시스템에 의해 자동으로 생성되며, 사용자의 세션을 식별합니다. |
| userId | string |  | ✓ |  |  ~ 128자 | 사용자ID |
| federationFromUserId | string |  |  |  |  ~ 128자 | 페더레이션 원본 사용자 ID<br>ID 페더레이션을 시작한 원본 사용자의 ID입니다. ID 페더레이션을 통해 다른 사용자로서 작업을 수행하는 경우, 이 필드에 조작을 시작한 원본 사용자의 ID가 저장됩니다. |
| expire | long |  |  | 현재 시각으로부터 1시간 후의 절대 시각 |  | 유효기간<br>토큰의 유효기간을 나타내는 타임스탬프입니다. 이 시각에 도달하면 토큰은 무효화됩니다.<br>UNIX 시간·밀리초 |
| timeOffset | int |  |  | 0 | 0 ~ 315360000 | 현재 시각에 대한 보정값(현재 시각을 기준으로 한 초 수)<br>시각 보정값은 서버의 현재 시각과의 차이를 초 단위로 나타냅니다.<br>이 값은 게임 내 이벤트나 기능이 특정 시각에 맞춰 동작해야 할 때 사용됩니다. |


---
## 메서드

### login

사용자 ID를 지정하여 GS2에 로그인<br>

지정한 사용자 ID로 GS2에 로그인하고 액세스 토큰을 취득합니다.<br>
본 API는 신뢰할 수 있는 게임 서버에서 호출되는 것을 상정하고 있습니다.<br>
사용자 ID 값에 대한 검증 처리가 존재하지 않으므로, 클라이언트에서 호출하는 것은 적절하지 않습니다.<br>
옵션으로 타임 오프셋(초 단위)을 지정하면 로그인한 사용자의 현재 시각을 의사적으로 앞당길 수 있어 미래의 이벤트 일정 테스트에 활용할 수 있습니다.<br>
반환되는 액세스 토큰에는 유효기간이 있으며, 기간이 지나면 무효가 됩니다.


#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID |
| timeOffset | int |  | | 0 | 0 ~ 315360000 | 현재 시각에 대한 보정값(현재 시각을 기준으로 한 초 수)<br>시각 보정값은 서버의 현재 시각과의 차이를 초 단위로 나타냅니다.<br>이 값은 게임 내 이벤트나 기능이 특정 시각에 맞춰 동작해야 할 때 사용됩니다. |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| token | string | 액세스 토큰<br>액세스를 인증하기 위한 토큰입니다.<br>이 토큰은 시스템에 의해 자동으로 생성되며, 사용자의 세션을 식별합니다. |
| userId | string | 사용자ID |
| expire | long | 유효기간<br>토큰의 유효기간을 나타내는 타임스탬프입니다. 이 시각에 도달하면 토큰이 무효가 됩니다.<br>UNIX 시간(밀리초) |

#### 구현 예제




**Go**
```go

import "github.com/gs2io/gs2-golang-sdk/core"
import "github.com/gs2io/gs2-golang-sdk/auth"
import "github.com/openlyinc/pointy"

session := core.Gs2RestSession{
    Credential: &core.BasicGs2Credential{
        ClientId: "your client id",
        ClientSecret: "your client secret",
    },
    Region: core.ApNortheast1,
}

if err := session.Connect(); err != nil {
    panic("error occurred")
}

client := auth.Gs2AuthRestClient{
    Session: &session,
}
result, err := client.Login(
    &auth.LoginRequest {
        UserId: pointy.String("user-0001"),
        TimeOffset: nil,
        TimeOffsetToken: nil,
    }
)
if err != nil {
    panic("error occurred")
}
token := result.Token
userId := result.UserId
expire := result.Expire

```

**PHP**
```php

use Gs2\Core\Model\BasicGs2Credential;
use Gs2\Core\Model\Region;
use Gs2\Core\Net\Gs2RestSession;
use Gs2\Core\Exception\Gs2Exception;
use Gs2\Auth\Gs2AuthRestClient;
use Gs2\Auth\Request\LoginRequest;

$session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region::AP_NORTHEAST_1
);

$session->open();

$client = new Gs2AuthRestClient(
    $session
);

try {
    $result = $client->login(
        (new LoginRequest())
            ->withUserId("user-0001")
            ->withTimeOffset(null)
            ->withTimeOffsetToken(null)
    );
    $token = $result->getToken();
    $userId = $result->getUserId();
    $expire = $result->getExpire();
} catch (Gs2Exception $e) {
    exit("error occurred")
}

```

**Java**
```java

import io.gs2.core.model.Region;
import io.gs2.core.model.BasicGs2Credential;
import io.gs2.core.rest.Gs2RestSession;
import io.gs2.core.exception.Gs2Exception;
import io.gs2.auth.rest.Gs2AuthRestClient;
import io.gs2.auth.request.LoginRequest;
import io.gs2.auth.result.LoginResult;

Gs2RestSession session = new Gs2RestSession(
    Region.AP_NORTHEAST_1,
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    )
);
session.connect();
Gs2AuthRestClient client = new Gs2AuthRestClient(session);

try {
    LoginResult result = client.login(
        new LoginRequest()
            .withUserId("user-0001")
            .withTimeOffset(null)
            .withTimeOffsetToken(null)
    );
    String token = result.getToken();
    String userId = result.getUserId();
    long expire = result.getExpire();
} catch (Gs2Exception e) {
    System.exit(1);
}

```

**C#**
```csharp

using Gs2.Core;
using Gs2.Core.Model;
using Gs2.Core.Net;
using Gs2.Core.Exception;

var session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region.ApNortheast1
);
yield return session.OpenAsync(r => { });
var client = new Gs2AuthRestClient(session);

AsyncResult<Gs2.Gs2Auth.Result.LoginResult> asyncResult = null;
yield return client.Login(
    new Gs2.Gs2Auth.Request.LoginRequest()
        .WithUserId("user-0001")
        .WithTimeOffset(null)
        .WithTimeOffsetToken(null),
    r => asyncResult = r
);
if (asyncResult.Error != null) {
    throw asyncResult.Error;
}
var result = asyncResult.Result;
var token = result.Token;
var userId = result.UserId;
var expire = result.Expire;

```

**TypeScript**
```typescript

import Gs2Core from '@/gs2/core';
import * as Gs2Auth from '@/gs2/auth';

const session = new Gs2Core.Gs2RestSession(
    "ap-northeast-1",
    new Gs2Core.BasicGs2Credential(
        'your client id',
        'your client secret'
    )
);
await session.connect();
const client = new Gs2Auth.Gs2AuthRestClient(session);

try {
    const result = await client.login(
        new Gs2Auth.LoginRequest()
            .withUserId("user-0001")
            .withTimeOffset(null)
            .withTimeOffsetToken(null)
    );
    const token = result.getToken();
    const userId = result.getUserId();
    const expire = result.getExpire();
} catch (e) {
    process.exit(1);
}

```

**Python**
```python

from gs2 import core
from gs2 import auth

session = core.Gs2RestSession(
    core.BasicGs2Credential(
        'your client id',
        'your client secret'
    ),
    "ap-northeast-1",
)
session.connect()
client = auth.Gs2AuthRestClient(session)

try:
    result = client.login(
        auth.LoginRequest()
            .with_user_id('user-0001')
            .with_time_offset(None)
            .with_time_offset_token(None)
    )
    token = result.token
    user_id = result.user_id
    expire = result.expire
except core.Gs2Exception as e:
    exit(1)


```

**GS2-Script**
```lua

client = gs2('auth')

api_result = client.login({
    userId="user-0001",
    timeOffset=nil,
    timeOffsetToken=nil,
})

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```

**GS2-Script(Async)**
```lua

client = gs2('auth')

api_result_handler = client.login_async({
    userId="user-0001",
    timeOffset=nil,
    timeOffsetToken=nil,
})

api_result = api_result_handler()  -- Call the handler to get the result

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```



---

### loginBySignature

계정 인증 정보로 GS2에 로그인<br>

계정 인증 정보의 서명을 검증하여 GS2에 로그인하고 액세스 토큰을 취득합니다.<br>
계정 인증 정보의 서명 검증을 수행하므로, 본 API는 클라이언트에서 호출해도 안전합니다.<br>
body와 signature는 일반적으로 GS2-Account의 인증 API에서 취득한 값을 사용하며, keyId는 서명 검증에 사용할 GS2-Key의 암호 키를 지정합니다.<br>
반환되는 액세스 토큰에는 유효기간이 있으며, 기간이 지나면 무효가 됩니다.


#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| keyId | string |  | | "grn:gs2:{region}:{ownerId}:key:default:key:default" |  ~ 1024자 | 암호화 키 GRN |
| body | string |  | ✓|  |  ~ 524288자 | 서명 대상 계정 인증 정보 |
| signature | string |  | ✓|  |  ~ 1024자 | 서명 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| token | string | 액세스 토큰<br>액세스를 인증하기 위한 토큰입니다.<br>이 토큰은 시스템에 의해 자동으로 생성되며, 사용자의 세션을 식별합니다. |
| userId | string | 사용자ID |
| expire | long | 유효기간<br>토큰의 유효기간을 나타내는 타임스탬프입니다. 이 시각에 도달하면 토큰이 무효가 됩니다.<br>UNIX 시간(밀리초) |

#### 구현 예제




**Go**
```go

import "github.com/gs2io/gs2-golang-sdk/core"
import "github.com/gs2io/gs2-golang-sdk/auth"
import "github.com/openlyinc/pointy"

session := core.Gs2RestSession{
    Credential: &core.BasicGs2Credential{
        ClientId: "your client id",
        ClientSecret: "your client secret",
    },
    Region: core.ApNortheast1,
}

if err := session.Connect(); err != nil {
    panic("error occurred")
}

client := auth.Gs2AuthRestClient{
    Session: &session,
}
result, err := client.LoginBySignature(
    &auth.LoginBySignatureRequest {
        KeyId: pointy.String("key-0001"),
        Body: pointy.String("body"),
        Signature: pointy.String("signature"),
    }
)
if err != nil {
    panic("error occurred")
}
token := result.Token
userId := result.UserId
expire := result.Expire

```

**PHP**
```php

use Gs2\Core\Model\BasicGs2Credential;
use Gs2\Core\Model\Region;
use Gs2\Core\Net\Gs2RestSession;
use Gs2\Core\Exception\Gs2Exception;
use Gs2\Auth\Gs2AuthRestClient;
use Gs2\Auth\Request\LoginBySignatureRequest;

$session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region::AP_NORTHEAST_1
);

$session->open();

$client = new Gs2AuthRestClient(
    $session
);

try {
    $result = $client->loginBySignature(
        (new LoginBySignatureRequest())
            ->withKeyId("key-0001")
            ->withBody("body")
            ->withSignature("signature")
    );
    $token = $result->getToken();
    $userId = $result->getUserId();
    $expire = $result->getExpire();
} catch (Gs2Exception $e) {
    exit("error occurred")
}

```

**Java**
```java

import io.gs2.core.model.Region;
import io.gs2.core.model.BasicGs2Credential;
import io.gs2.core.rest.Gs2RestSession;
import io.gs2.core.exception.Gs2Exception;
import io.gs2.auth.rest.Gs2AuthRestClient;
import io.gs2.auth.request.LoginBySignatureRequest;
import io.gs2.auth.result.LoginBySignatureResult;

Gs2RestSession session = new Gs2RestSession(
    Region.AP_NORTHEAST_1,
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    )
);
session.connect();
Gs2AuthRestClient client = new Gs2AuthRestClient(session);

try {
    LoginBySignatureResult result = client.loginBySignature(
        new LoginBySignatureRequest()
            .withKeyId("key-0001")
            .withBody("body")
            .withSignature("signature")
    );
    String token = result.getToken();
    String userId = result.getUserId();
    long expire = result.getExpire();
} catch (Gs2Exception e) {
    System.exit(1);
}

```

**C#**
```csharp

using Gs2.Core;
using Gs2.Core.Model;
using Gs2.Core.Net;
using Gs2.Core.Exception;

var session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region.ApNortheast1
);
yield return session.OpenAsync(r => { });
var client = new Gs2AuthRestClient(session);

AsyncResult<Gs2.Gs2Auth.Result.LoginBySignatureResult> asyncResult = null;
yield return client.LoginBySignature(
    new Gs2.Gs2Auth.Request.LoginBySignatureRequest()
        .WithKeyId("key-0001")
        .WithBody("body")
        .WithSignature("signature"),
    r => asyncResult = r
);
if (asyncResult.Error != null) {
    throw asyncResult.Error;
}
var result = asyncResult.Result;
var token = result.Token;
var userId = result.UserId;
var expire = result.Expire;

```

**TypeScript**
```typescript

import Gs2Core from '@/gs2/core';
import * as Gs2Auth from '@/gs2/auth';

const session = new Gs2Core.Gs2RestSession(
    "ap-northeast-1",
    new Gs2Core.BasicGs2Credential(
        'your client id',
        'your client secret'
    )
);
await session.connect();
const client = new Gs2Auth.Gs2AuthRestClient(session);

try {
    const result = await client.loginBySignature(
        new Gs2Auth.LoginBySignatureRequest()
            .withKeyId("key-0001")
            .withBody("body")
            .withSignature("signature")
    );
    const token = result.getToken();
    const userId = result.getUserId();
    const expire = result.getExpire();
} catch (e) {
    process.exit(1);
}

```

**Python**
```python

from gs2 import core
from gs2 import auth

session = core.Gs2RestSession(
    core.BasicGs2Credential(
        'your client id',
        'your client secret'
    ),
    "ap-northeast-1",
)
session.connect()
client = auth.Gs2AuthRestClient(session)

try:
    result = client.login_by_signature(
        auth.LoginBySignatureRequest()
            .with_key_id('key-0001')
            .with_body('body')
            .with_signature('signature')
    )
    token = result.token
    user_id = result.user_id
    expire = result.expire
except core.Gs2Exception as e:
    exit(1)


```

**GS2-Script**
```lua

client = gs2('auth')

api_result = client.login_by_signature({
    keyId="key-0001",
    body="body",
    signature="signature",
})

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```

**GS2-Script(Async)**
```lua

client = gs2('auth')

api_result_handler = client.login_by_signature_async({
    keyId="key-0001",
    body="body",
    signature="signature",
})

api_result = api_result_handler()  -- Call the handler to get the result

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```



---

### federation

사용자 ID 연계<br>

지정한 사용자 ID를 기점으로 다른 사용자 ID로 동작하기 위한 액세스 토큰을 취득합니다.<br>
길드 마스터가 다른 멤버를 대신하여 조작을 수행하는 등, 다른 사용자로서 액션을 실행해야 하는 시나리오에서 활용할 수 있습니다.<br>
이 액세스 토큰을 사용하여 트랜잭션을 발행하는 경우, 트랜잭션 액션 내의 #{userId}는 페더레이션 대상 사용자 ID로 치환되고<br>
#{originalUserId}는 페더레이션 원본 사용자 ID로 치환됩니다.<br>

정책 문서를 지정하면 페더레이션된 사용자로서 API를 호출할 때 크리덴셜이 가진 권한보다 더 엄격한 제약을 설정할 수 있습니다.<br>
반환되는 액세스 토큰에는 유효기간이 있으며, 기간이 지나면 무효가 됩니다.


#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| originalUserId | string |  | ✓|  |  ~ 128자 | 페더레이션 원본 사용자 ID |
| userId | string |  | ✓|  |  ~ 128자 | 페더레이션 대상 사용자 ID |
| policyDocument | string |  | |  |  ~ 524288자 | 정책 문서 |
| timeOffset | int |  | | 0 | 0 ~ 315360000 | 현재 시각에 대한 보정값(현재 시각을 기준으로 한 초 수)<br>시각 보정값은 서버의 현재 시각과의 차이를 초 단위로 나타냅니다.<br>이 값은 게임 내 이벤트나 기능이 특정 시각에 맞춰 동작해야 할 때 사용됩니다. |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| token | string | 액세스 토큰<br>액세스를 인증하기 위한 토큰입니다.<br>이 토큰은 시스템에 의해 자동으로 생성되며, 사용자의 세션을 식별합니다. |
| userId | string | 사용자ID |
| expire | long | 유효기간<br>토큰의 유효기간을 나타내는 타임스탬프입니다. 이 시각에 도달하면 토큰이 무효가 됩니다.<br>UNIX 시간(밀리초) |

#### 구현 예제




**Go**
```go

import "github.com/gs2io/gs2-golang-sdk/core"
import "github.com/gs2io/gs2-golang-sdk/auth"
import "github.com/openlyinc/pointy"

session := core.Gs2RestSession{
    Credential: &core.BasicGs2Credential{
        ClientId: "your client id",
        ClientSecret: "your client secret",
    },
    Region: core.ApNortheast1,
}

if err := session.Connect(); err != nil {
    panic("error occurred")
}

client := auth.Gs2AuthRestClient{
    Session: &session,
}
result, err := client.Federation(
    &auth.FederationRequest {
        OriginalUserId: pointy.String("user-0001"),
        UserId: pointy.String("user-0002"),
        PolicyDocument: pointy.String("{\n  \"Version\": \"2016-04-01\",\n  \"Statements\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Actions\": [\n        \"Gs2Inbox:SendMessage\"\n      ],\n      \"Resources\": [\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001\",\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*\"\n      ]\n    }\n  ]\n}"),
        TimeOffset: nil,
        TimeOffsetToken: nil,
    }
)
if err != nil {
    panic("error occurred")
}
token := result.Token
userId := result.UserId
expire := result.Expire

```

**PHP**
```php

use Gs2\Core\Model\BasicGs2Credential;
use Gs2\Core\Model\Region;
use Gs2\Core\Net\Gs2RestSession;
use Gs2\Core\Exception\Gs2Exception;
use Gs2\Auth\Gs2AuthRestClient;
use Gs2\Auth\Request\FederationRequest;

$session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region::AP_NORTHEAST_1
);

$session->open();

$client = new Gs2AuthRestClient(
    $session
);

try {
    $result = $client->federation(
        (new FederationRequest())
            ->withOriginalUserId("user-0001")
            ->withUserId("user-0002")
            ->withPolicyDocument("{\n  \"Version\": \"2016-04-01\",\n  \"Statements\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Actions\": [\n        \"Gs2Inbox:SendMessage\"\n      ],\n      \"Resources\": [\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001\",\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*\"\n      ]\n    }\n  ]\n}")
            ->withTimeOffset(null)
            ->withTimeOffsetToken(null)
    );
    $token = $result->getToken();
    $userId = $result->getUserId();
    $expire = $result->getExpire();
} catch (Gs2Exception $e) {
    exit("error occurred")
}

```

**Java**
```java

import io.gs2.core.model.Region;
import io.gs2.core.model.BasicGs2Credential;
import io.gs2.core.rest.Gs2RestSession;
import io.gs2.core.exception.Gs2Exception;
import io.gs2.auth.rest.Gs2AuthRestClient;
import io.gs2.auth.request.FederationRequest;
import io.gs2.auth.result.FederationResult;

Gs2RestSession session = new Gs2RestSession(
    Region.AP_NORTHEAST_1,
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    )
);
session.connect();
Gs2AuthRestClient client = new Gs2AuthRestClient(session);

try {
    FederationResult result = client.federation(
        new FederationRequest()
            .withOriginalUserId("user-0001")
            .withUserId("user-0002")
            .withPolicyDocument("{\n  \"Version\": \"2016-04-01\",\n  \"Statements\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Actions\": [\n        \"Gs2Inbox:SendMessage\"\n      ],\n      \"Resources\": [\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001\",\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*\"\n      ]\n    }\n  ]\n}")
            .withTimeOffset(null)
            .withTimeOffsetToken(null)
    );
    String token = result.getToken();
    String userId = result.getUserId();
    long expire = result.getExpire();
} catch (Gs2Exception e) {
    System.exit(1);
}

```

**C#**
```csharp

using Gs2.Core;
using Gs2.Core.Model;
using Gs2.Core.Net;
using Gs2.Core.Exception;

var session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region.ApNortheast1
);
yield return session.OpenAsync(r => { });
var client = new Gs2AuthRestClient(session);

AsyncResult<Gs2.Gs2Auth.Result.FederationResult> asyncResult = null;
yield return client.Federation(
    new Gs2.Gs2Auth.Request.FederationRequest()
        .WithOriginalUserId("user-0001")
        .WithUserId("user-0002")
        .WithPolicyDocument("{\n  \"Version\": \"2016-04-01\",\n  \"Statements\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Actions\": [\n        \"Gs2Inbox:SendMessage\"\n      ],\n      \"Resources\": [\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001\",\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*\"\n      ]\n    }\n  ]\n}")
        .WithTimeOffset(null)
        .WithTimeOffsetToken(null),
    r => asyncResult = r
);
if (asyncResult.Error != null) {
    throw asyncResult.Error;
}
var result = asyncResult.Result;
var token = result.Token;
var userId = result.UserId;
var expire = result.Expire;

```

**TypeScript**
```typescript

import Gs2Core from '@/gs2/core';
import * as Gs2Auth from '@/gs2/auth';

const session = new Gs2Core.Gs2RestSession(
    "ap-northeast-1",
    new Gs2Core.BasicGs2Credential(
        'your client id',
        'your client secret'
    )
);
await session.connect();
const client = new Gs2Auth.Gs2AuthRestClient(session);

try {
    const result = await client.federation(
        new Gs2Auth.FederationRequest()
            .withOriginalUserId("user-0001")
            .withUserId("user-0002")
            .withPolicyDocument("{\n  \"Version\": \"2016-04-01\",\n  \"Statements\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Actions\": [\n        \"Gs2Inbox:SendMessage\"\n      ],\n      \"Resources\": [\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001\",\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*\"\n      ]\n    }\n  ]\n}")
            .withTimeOffset(null)
            .withTimeOffsetToken(null)
    );
    const token = result.getToken();
    const userId = result.getUserId();
    const expire = result.getExpire();
} catch (e) {
    process.exit(1);
}

```

**Python**
```python

from gs2 import core
from gs2 import auth

session = core.Gs2RestSession(
    core.BasicGs2Credential(
        'your client id',
        'your client secret'
    ),
    "ap-northeast-1",
)
session.connect()
client = auth.Gs2AuthRestClient(session)

try:
    result = client.federation(
        auth.FederationRequest()
            .with_original_user_id('user-0001')
            .with_user_id('user-0002')
            .with_policy_document('{\n  "Version": "2016-04-01",\n  "Statements": [\n    {\n      "Effect": "Allow",\n      "Actions": [\n        "Gs2Inbox:SendMessage"\n      ],\n      "Resources": [\n        "grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001",\n        "grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*"\n      ]\n    }\n  ]\n}')
            .with_time_offset(None)
            .with_time_offset_token(None)
    )
    token = result.token
    user_id = result.user_id
    expire = result.expire
except core.Gs2Exception as e:
    exit(1)


```

**GS2-Script**
```lua

client = gs2('auth')

api_result = client.federation({
    originalUserId="user-0001",
    userId="user-0002",
    policyDocument="{\n  \"Version\": \"2016-04-01\",\n  \"Statements\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Actions\": [\n        \"Gs2Inbox:SendMessage\"\n      ],\n      \"Resources\": [\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001\",\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*\"\n      ]\n    }\n  ]\n}",
    timeOffset=nil,
    timeOffsetToken=nil,
})

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```

**GS2-Script(Async)**
```lua

client = gs2('auth')

api_result_handler = client.federation_async({
    originalUserId="user-0001",
    userId="user-0002",
    policyDocument="{\n  \"Version\": \"2016-04-01\",\n  \"Statements\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Actions\": [\n        \"Gs2Inbox:SendMessage\"\n      ],\n      \"Resources\": [\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001\",\n        \"grn:gs2:ap-northeast-1:YourOwnerId:inbox:namespace-0001:*\"\n      ]\n    }\n  ]\n}",
    timeOffset=nil,
    timeOffsetToken=nil,
})

api_result = api_result_handler()  -- Call the handler to get the result

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```



---

### issueTimeOffsetTokenByUserId

지정한 사용자 ID로 사용 가능한 타임 오프셋 토큰 발행<br>

`타임 오프셋 토큰`을 사용자 ID를 지정하여 실행하는 API에 전달하면, 지정한 사용자의 현재 시각을 가상으로 앞당긴 상태로 API 처리를 실행할 수 있습니다.<br>
예를 들어 timeOffset에 86400(24시간)을 지정하여 발행한 토큰을 이용하면, 서버는 "현재 시각 + 24시간"의 상태로 요청을 처리합니다.<br>
이 구조를 통해 기간 한정 이벤트, 데일리 퀘스트, 스태미나 회복 등 시각에 의존하는 게임 기능을 실제 시간 경과를 기다리지 않고 검증할 수 있습니다.<br>

액세스 토큰을 사용하는 API에서 타임 오프셋을 사용하고 싶은 경우, 액세스 토큰 발행 시 timeOffsetToken을 지정하면 이후 요청에서도 동일한 시각 보정이 적용된 상태로 처리를 실행할 수 있습니다.<br>

타임 오프셋 토큰에는 유효기간이 있으며, 발행 후 1시간이 지나면 무효가 됩니다.<br>
또한 토큰은 발행 대상 사용자 ID에 연결되어 있으며, 다른 사용자 ID의 요청에는 사용할 수 없습니다.<br>

주로 테스트·디버그 용도를 상정하고 있으며, 예정된 이벤트나 기간 한정 콘텐츠의 사전 검증에 사용됩니다.


#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID |
| timeOffset | int |  | | 0 | 0 ~ 315360000 | 현재 시각에 대한 보정값(현재 시각을 기준으로 한 초 수)<br>시각 보정값은 서버의 현재 시각과의 차이를 초 단위로 나타냅니다.<br>이 값은 게임 내 이벤트나 기능이 특정 시각에 맞춰 동작해야 할 때 사용됩니다. |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| token | string | 타임 오프셋 토큰<br>발행된 타임 오프셋 토큰입니다. 이후 요청의 timeOffsetToken에 전달하면 지정한 오프셋만큼 시각을 조정한 상태로 조작을 실행할 수 있습니다. |
| userId | string | 사용자ID |
| expire | long | 유효기간<br>토큰의 유효기간을 나타내는 타임스탬프입니다. 이 시각에 도달하면 토큰이 무효가 됩니다.<br>UNIX 시간(밀리초) |

#### 구현 예제




**Go**
```go

import "github.com/gs2io/gs2-golang-sdk/core"
import "github.com/gs2io/gs2-golang-sdk/auth"
import "github.com/openlyinc/pointy"

session := core.Gs2RestSession{
    Credential: &core.BasicGs2Credential{
        ClientId: "your client id",
        ClientSecret: "your client secret",
    },
    Region: core.ApNortheast1,
}

if err := session.Connect(); err != nil {
    panic("error occurred")
}

client := auth.Gs2AuthRestClient{
    Session: &session,
}
result, err := client.IssueTimeOffsetTokenByUserId(
    &auth.IssueTimeOffsetTokenByUserIdRequest {
        UserId: pointy.String("user-0001"),
        TimeOffset: pointy.Int32(1000),
        TimeOffsetToken: nil,
    }
)
if err != nil {
    panic("error occurred")
}
token := result.Token
userId := result.UserId
expire := result.Expire

```

**PHP**
```php

use Gs2\Core\Model\BasicGs2Credential;
use Gs2\Core\Model\Region;
use Gs2\Core\Net\Gs2RestSession;
use Gs2\Core\Exception\Gs2Exception;
use Gs2\Auth\Gs2AuthRestClient;
use Gs2\Auth\Request\IssueTimeOffsetTokenByUserIdRequest;

$session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region::AP_NORTHEAST_1
);

$session->open();

$client = new Gs2AuthRestClient(
    $session
);

try {
    $result = $client->issueTimeOffsetTokenByUserId(
        (new IssueTimeOffsetTokenByUserIdRequest())
            ->withUserId("user-0001")
            ->withTimeOffset(1000)
            ->withTimeOffsetToken(null)
    );
    $token = $result->getToken();
    $userId = $result->getUserId();
    $expire = $result->getExpire();
} catch (Gs2Exception $e) {
    exit("error occurred")
}

```

**Java**
```java

import io.gs2.core.model.Region;
import io.gs2.core.model.BasicGs2Credential;
import io.gs2.core.rest.Gs2RestSession;
import io.gs2.core.exception.Gs2Exception;
import io.gs2.auth.rest.Gs2AuthRestClient;
import io.gs2.auth.request.IssueTimeOffsetTokenByUserIdRequest;
import io.gs2.auth.result.IssueTimeOffsetTokenByUserIdResult;

Gs2RestSession session = new Gs2RestSession(
    Region.AP_NORTHEAST_1,
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    )
);
session.connect();
Gs2AuthRestClient client = new Gs2AuthRestClient(session);

try {
    IssueTimeOffsetTokenByUserIdResult result = client.issueTimeOffsetTokenByUserId(
        new IssueTimeOffsetTokenByUserIdRequest()
            .withUserId("user-0001")
            .withTimeOffset(1000)
            .withTimeOffsetToken(null)
    );
    String token = result.getToken();
    String userId = result.getUserId();
    long expire = result.getExpire();
} catch (Gs2Exception e) {
    System.exit(1);
}

```

**C#**
```csharp

using Gs2.Core;
using Gs2.Core.Model;
using Gs2.Core.Net;
using Gs2.Core.Exception;

var session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region.ApNortheast1
);
yield return session.OpenAsync(r => { });
var client = new Gs2AuthRestClient(session);

AsyncResult<Gs2.Gs2Auth.Result.IssueTimeOffsetTokenByUserIdResult> asyncResult = null;
yield return client.IssueTimeOffsetTokenByUserId(
    new Gs2.Gs2Auth.Request.IssueTimeOffsetTokenByUserIdRequest()
        .WithUserId("user-0001")
        .WithTimeOffset(1000)
        .WithTimeOffsetToken(null),
    r => asyncResult = r
);
if (asyncResult.Error != null) {
    throw asyncResult.Error;
}
var result = asyncResult.Result;
var token = result.Token;
var userId = result.UserId;
var expire = result.Expire;

```

**TypeScript**
```typescript

import Gs2Core from '@/gs2/core';
import * as Gs2Auth from '@/gs2/auth';

const session = new Gs2Core.Gs2RestSession(
    "ap-northeast-1",
    new Gs2Core.BasicGs2Credential(
        'your client id',
        'your client secret'
    )
);
await session.connect();
const client = new Gs2Auth.Gs2AuthRestClient(session);

try {
    const result = await client.issueTimeOffsetTokenByUserId(
        new Gs2Auth.IssueTimeOffsetTokenByUserIdRequest()
            .withUserId("user-0001")
            .withTimeOffset(1000)
            .withTimeOffsetToken(null)
    );
    const token = result.getToken();
    const userId = result.getUserId();
    const expire = result.getExpire();
} catch (e) {
    process.exit(1);
}

```

**Python**
```python

from gs2 import core
from gs2 import auth

session = core.Gs2RestSession(
    core.BasicGs2Credential(
        'your client id',
        'your client secret'
    ),
    "ap-northeast-1",
)
session.connect()
client = auth.Gs2AuthRestClient(session)

try:
    result = client.issue_time_offset_token_by_user_id(
        auth.IssueTimeOffsetTokenByUserIdRequest()
            .with_user_id('user-0001')
            .with_time_offset(1000)
            .with_time_offset_token(None)
    )
    token = result.token
    user_id = result.user_id
    expire = result.expire
except core.Gs2Exception as e:
    exit(1)


```

**GS2-Script**
```lua

client = gs2('auth')

api_result = client.issue_time_offset_token_by_user_id({
    userId="user-0001",
    timeOffset=1000,
    timeOffsetToken=nil,
})

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```

**GS2-Script(Async)**
```lua

client = gs2('auth')

api_result_handler = client.issue_time_offset_token_by_user_id_async({
    userId="user-0001",
    timeOffset=1000,
    timeOffsetToken=nil,
})

api_result = api_result_handler()  -- Call the handler to get the result

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
token = result.token;
userId = result.userId;
expire = result.expire;

```



---

### getServiceVersion

마이크로서비스 버전 조회


#### Request

요청 파라미터: 없음

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | string | 버전 |

#### 구현 예제




**Go**
```go

import "github.com/gs2io/gs2-golang-sdk/core"
import "github.com/gs2io/gs2-golang-sdk/auth"
import "github.com/openlyinc/pointy"

session := core.Gs2RestSession{
    Credential: &core.BasicGs2Credential{
        ClientId: "your client id",
        ClientSecret: "your client secret",
    },
    Region: core.ApNortheast1,
}

if err := session.Connect(); err != nil {
    panic("error occurred")
}

client := auth.Gs2AuthRestClient{
    Session: &session,
}
result, err := client.GetServiceVersion(
    &auth.GetServiceVersionRequest {
    }
)
if err != nil {
    panic("error occurred")
}
item := result.Item

```

**PHP**
```php

use Gs2\Core\Model\BasicGs2Credential;
use Gs2\Core\Model\Region;
use Gs2\Core\Net\Gs2RestSession;
use Gs2\Core\Exception\Gs2Exception;
use Gs2\Auth\Gs2AuthRestClient;
use Gs2\Auth\Request\GetServiceVersionRequest;

$session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region::AP_NORTHEAST_1
);

$session->open();

$client = new Gs2AuthRestClient(
    $session
);

try {
    $result = $client->getServiceVersion(
        (new GetServiceVersionRequest())
    );
    $item = $result->getItem();
} catch (Gs2Exception $e) {
    exit("error occurred")
}

```

**Java**
```java

import io.gs2.core.model.Region;
import io.gs2.core.model.BasicGs2Credential;
import io.gs2.core.rest.Gs2RestSession;
import io.gs2.core.exception.Gs2Exception;
import io.gs2.auth.rest.Gs2AuthRestClient;
import io.gs2.auth.request.GetServiceVersionRequest;
import io.gs2.auth.result.GetServiceVersionResult;

Gs2RestSession session = new Gs2RestSession(
    Region.AP_NORTHEAST_1,
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    )
);
session.connect();
Gs2AuthRestClient client = new Gs2AuthRestClient(session);

try {
    GetServiceVersionResult result = client.getServiceVersion(
        new GetServiceVersionRequest()
    );
    String item = result.getItem();
} catch (Gs2Exception e) {
    System.exit(1);
}

```

**C#**
```csharp

using Gs2.Core;
using Gs2.Core.Model;
using Gs2.Core.Net;
using Gs2.Core.Exception;

var session = new Gs2RestSession(
    new BasicGs2Credential(
        "your client id",
        "your client secret"
    ),
    Region.ApNortheast1
);
yield return session.OpenAsync(r => { });
var client = new Gs2AuthRestClient(session);

AsyncResult<Gs2.Gs2Auth.Result.GetServiceVersionResult> asyncResult = null;
yield return client.GetServiceVersion(
    new Gs2.Gs2Auth.Request.GetServiceVersionRequest(),
    r => asyncResult = r
);
if (asyncResult.Error != null) {
    throw asyncResult.Error;
}
var result = asyncResult.Result;
var item = result.Item;

```

**TypeScript**
```typescript

import Gs2Core from '@/gs2/core';
import * as Gs2Auth from '@/gs2/auth';

const session = new Gs2Core.Gs2RestSession(
    "ap-northeast-1",
    new Gs2Core.BasicGs2Credential(
        'your client id',
        'your client secret'
    )
);
await session.connect();
const client = new Gs2Auth.Gs2AuthRestClient(session);

try {
    const result = await client.getServiceVersion(
        new Gs2Auth.GetServiceVersionRequest()
    );
    const item = result.getItem();
} catch (e) {
    process.exit(1);
}

```

**Python**
```python

from gs2 import core
from gs2 import auth

session = core.Gs2RestSession(
    core.BasicGs2Credential(
        'your client id',
        'your client secret'
    ),
    "ap-northeast-1",
)
session.connect()
client = auth.Gs2AuthRestClient(session)

try:
    result = client.get_service_version(
        auth.GetServiceVersionRequest()
    )
    item = result.item
except core.Gs2Exception as e:
    exit(1)


```

**GS2-Script**
```lua

client = gs2('auth')

api_result = client.get_service_version({
})

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
item = result.item;

```

**GS2-Script(Async)**
```lua

client = gs2('auth')

api_result_handler = client.get_service_version_async({
})

api_result = api_result_handler()  -- Call the handler to get the result

if(api_result.isError) then
    -- When error occurs
    fail(api_result['statusCode'], api_result['errorMessage'])
end

result = api_result.result
item = result.item;

```



---



