メインコンテンツまでスキップ

OIDC をアイデンティティプロバイダーとして設定する

Last updated on July 15, 2026

注釈:本資料はAI技術を用いて翻訳されています。

Overview

このガイドの目的は、OpenID Connect (OIDC) を AccelByte Gaming Services (AGS) と統合できるようにすることです。3 つの OIDC 認証タイプ(Authorization CodeID TokenAccess Token)をサポートしています。

ゲームによっては、ここに記載されていない追加のアイデンティティプロバイダー機能を設定する必要がある場合があります。OIDC サービスの設定に関する詳細は、お使いのアイデンティティプロバイダーのドキュメントを確認することをお勧めします。

important

このガイドは一般公開用であり、機密保持の観点から掲載できる情報が限られています。まずは機密版の完全なガイドを参照することをお勧めします。機密版ガイドのコピーが必要な場合は、担当の AccelByte テクニカルプロデューサーにお問い合わせください。

Goals

  • AccelByte の Game SDK を使用して、ゲームに OIDC 認証方式を有効にします。
  • AGS の Player Portal を使用して、パブリッシャーの Web サイトに OIDC 認証方式を有効にします。

Prerequisites

Web ログイン統合

  • OIDC をサポートするアイデンティティプロバイダー。
  • 認証を設定し権限を管理するための AccelByte Admin Portal アカウント。
  • Player Portal と Launcher 用のパブリッシャー Namespace
  • Player Portal。
AGS Public Cloud

Web ログイン統合は現在 AGS Public Cloud では利用できず、AGS Private Cloud のみでサポートされています。

インゲームログイン統合

  • OIDC をサポートするアイデンティティプロバイダー。
  • 認証を設定し権限を管理するための AGS Admin Portal アカウント。
  • ゲーム Namespace。
  • AccelByte の Game SDK をインポートした Unity または Unreal のゲームプロジェクト。
  • 最新バージョンの AccelByte Unity SDK または Unreal SDK。
  • AGS Identity and Access Management (IAM) クライアントに関する知識。

Authorization Code type

Authorization Code タイプは、標準の Authorization Code フローを使用した認証と、JSON Web Key Set (JWKS) による ID トークンの検証の両方をサポートします。Authorization Code は Web フローベースの認証 です。システムはアイデンティティプロバイダーのログインページにリダイレクトし、認証後にアクセス権を付与した状態で AccelByte のポータルに戻します。

IdP を設定する

以下の手順に従って、ゲームにアイデンティティプロバイダー (IdP) の OIDC ログインを設定します。これにより、プレイヤーは自分のアカウントを使用して Admin PortalPlayer PortalLauncher にサインインできるようになります。

ここでは、OIDC の Player Portal と Admin Portal のログインを設定する例として Okta OIDC を使用します。Authorization Code の場合、アイデンティティプロバイダーの OIDC を AGS と統合するために以下の項目が必要です。

  • JWKS URL
  • Issuer
  • Client ID
  • Client Secret
  • Authorization Request URL
  • Token Endpoint URL

例として、アイデンティティプロバイダーに Okta を使用します。OIDC をサポートする他の IdP を使用することもできます。

Okta アプリケーションを作成する

Okta の Create OIDC app integrations ガイドに従って、Okta アカウント内に Okta アプリケーションを作成します。

注記

この手順で生成したクライアント ID とクライアントシークレットのコピーを保管しておいてください。Web ログインを設定する際に必要になります。

Okta OIDC 設定を取得する

次の URL を使用して、アプリの openid-configuration を開きます: https://<YOUR_OKTA_URL>.okta.com/oauth2/default/.well-known/openid-configuration

OIDC Authorization Code タイプのログインを設定するために、以下の項目をコピーする必要があります。

  • JWKS URL
  • Issuer
  • Authorization Request URL
  • Token Endpoint URL

Web ログインを設定する

Player Portal と Admin Portal で OIDC ログインを設定し、プレイヤーが自分の IdP アカウントを使用して Player Portal にサインインできるようにするには、以下の手順に従います。

  1. AGS Admin Portal で、パブリッシャー namespace に移動します。

  2. サイドバーメニューで、Foundations > 3rd Party Integrations > Auth & Account Linking に移動します。

  3. Auth & Account Linking ページで、+ Add New ボタンをクリックします。

    Image shows the Auth &amp; Account Linking page

  4. ログイン方式オプションの一番下にある + Create OIDC をクリックします。

    Image shows the Create OIDC button

  5. Create OpenID Connect (OIDC) フォームが表示されます。必要な情報を入力します。この例では Authorization Code タイプを使用します。

    • Platform Name: わかりやすい名前を入力します。例: oidcokta
    • Platform ID: Okta アプリの Valid RedirectURI として使用するプラットフォーム ID を入力します。例: oidcokta
    • Authentication type: Authorization Code を選択します。
    • JWKS URL: Okta の openid 設定 URL にある jwks_url を使用します。
    • Issuer: Okta の openid 設定 URL にある issuer を使用します。
    • Client ID: Okta アプリケーションを作成する手順で取得した Okta Client ID を使用します。
    • Client Secret: Okta アプリケーションを作成する手順で取得した Okta Client Secret を使用します。
    • Authorization Request URL: Okta の openid 設定 URL にある authorization_endpoint を使用します。
    • Token Endpoint URL: Okta の openid 設定 URL にある token_endpoint を使用します。
    • Clients: 使用状況に応じて、この OIDC にクライアントを設定することで、Player Portal、Launcher、Admin Portal、In-Game ログインで OIDC ログインを使用できます。例えば、OIDC ログインを Player Portal と Admin Portal に統合したい場合は、ここに Player Portal Website IAM ClientAdmin Portal Website IAM Client を追加する必要があります。
    • Scopes (Optional): デフォルトでは openid email profile に設定されています。

    Image shows the upper part of the Create OIDC page

    Image shows the power part of the Create OIDC page

  6. Next をクリックします。

  7. Token Claims Mapping フォームで、システムが ID トークン内のユーザーアイデンティティを解析して AccelByte アカウントに変換できるようにマッピングします。

    Image hows the Token Claims Mapping form

  8. Next をクリックします。

  9. (オプション) Domains セクションでは、ドメインを登録し、ユーザーにロールを割り当てることができます。

    注記

    Register Domain は、指定したドメイン配下のユーザーに自動的にロールを割り当てたい場合に便利です。例えば、OIDC ログインが Admin Portal ログインに使用されている場合、<your-domain> 配下のユーザーが OIDC ログインを使用してログインした後に、そのユーザーに自動的に Admin ロールを付与したい場合に使用します。

    • この手順をスキップするには、Create をクリックします。

      Image shows the Domains page

    • ドメインを登録するには、+ Register Domain をクリックします。次に、Register Domain フォームの以下のフィールドに入力します。フィールドの入力後、Save をクリックし、続けて Create をクリックします。

      Image shows the Register Domain form

      • Domain Name: ドメイン名を入力します。この例では accelbyte.net を使用します。
      • Clients: ユーザーがクライアントに初めてログインしたとき、システムはデフォルトのロールをそのユーザーに付与します。この例では、ユーザーが Admin Portal で OIDC を使用してログインした際に Admin ロールを付与したいので、Admin Portal Website IAM Client に設定します。
      • Default Role: ユーザーに付与したいロールです。
      • Default Namespace: デフォルトロールがグローバルロールでない場合、対象の Namespace を指定します。
  10. システムは作成した OIDC の詳細ページにリダイレクトします。Activate をクリックして OIDC を有効化します。

    Image shows the OIDC Details page

OIDC を使用した Player Portal からのユーザーログイン

Publisher Namespace で OIDC ログイン方式を設定し、Player Portal Website Client を OIDC クライアントとして設定していることを確認してください。

  1. Player Portal に移動し、Login をクリックします。

    Image shows the Player Portal

  2. More Login Options をクリックします。

    Image shows the More Login Options button

  3. 設定した OIDC のログインオプションをクリックします。この例では Okta を使用します。

  4. システムは Okta のログインページにリダイレクトします。認証情報を入力してログインします。

    Image shows the Okta Login page

    注記

    ログインに成功すると、システムはプレイヤーに OIDC アカウントを既存の AccelByte アカウントとリンクするか、新しいアカウントを作成するように要求します。さらに、ヘッドレスアカウントを使用してプレイヤーが直接 Player Portal にログインできるように(つまり登録フォームを必要とせずに)プラットフォームを設定することもできます。

OIDC を使用した Admin Portal からのユーザーログイン

Publisher Namespace で OIDC ログイン方式を設定し、Admin Portal Website Client を OIDC クライアントとして設定していることを確認してください。

注記

Admin Portal にアクセスするには、ユーザーに Admin Role を付与する必要があります。ただし、既にドメインを OIDC ログイン方式として登録し、Admin ロールを付与している場合、システムはそのドメインに関連付けられた認証済み OIDC ユーザーに自動的にその Admin ロールを付与します。

  1. Admin Portal に移動します。システムがログインページにリダイレクトします。OIDC のロゴをクリックします。ロゴが複数ある場合は、ボタンにマウスを合わせて、正しい OIDC ログインを選択していることを確認してください。

    Image shows the Admin Portal page

  2. システムは Okta Login ページにリダイレクトします。認証情報を使用してログインします。

    Image shows the Okta Login page

  3. システムは Admin Portal にリダイレクトします。

    Image shows the Admin Portal

    ポータルへのアクセスは、割り当てられているロールに基づきます。例えば、割り当てられたロールが AccelByte namespace に対する Admin Portal Read Only の場合、そのロールで許可された機能のみにアクセスできます。

    Image shows sample domain settings

ID token type

ID Token タイプは、JWKS を介して ID トークンを検証することで認証をサポートします。ID Token はインゲームフローベースの認証向けです。アイデンティティプロバイダーから ID トークンを生成する必要があります。これを AccelByte のアクセストークンと交換できます。

IdP を設定する

以下の手順に従って、ゲームにアイデンティティプロバイダー (IdP) の OIDC ログインを設定します。これにより、プレイヤーは自分のアカウントを使用してゲームにサインインできるようになります。

ID トークンを取得するために、IdP からの認可を処理する必要があります。IdP の OIDC を AGS と統合するには、以下の項目が必要です。

  • JWKS URL
  • Issuer
  • Client ID

例として、Facebook を IdP として使用します。OIDC をサポートする他の IdP を使用することもできます。

Facebook アプリケーションを作成する

Facebook の Create an App ガイドに従って、Facebook Developer アカウント内に Facebook アプリケーションを作成します。

アプリに Facebook Login プロダクトを追加する

Facebook Login for the Web with the JavaScript SDK ガイドに従って、アプリに Facebook Login プロダクトを追加します。

インゲームログインを設定する

以下の手順に従って、ゲーム内で OIDC ログインを設定します。例として Facebook OIDC を使用します。これにより、プレイヤーはアイデンティティプロバイダーのアカウントを使用してゲームにサインインできるようになります。

  1. AGS Admin Portal で、ゲーム namespace に移動します。

  2. サイドバーメニューで、Foundations > 3rd Party Integrations > Auth & Account Linking に移動します。

  3. Auth & Account Linking ページで、+ Add New ボタンをクリックします。

    Image shows the Auth &amp; Account Linking page

  4. ログイン方式オプションの一番下にある + Create OIDC をクリックします。

    Image shows the Create OIDC button

  5. Create OpenID Connect (OIDC) フォームで、必要なフィールドに入力します。この例では認証タイプとして ID Token を使用します。

    • Platform Name: ログイン方式の名前を入力します。例: oidcfacebook
    • Platform ID: ログイン方式の ID を入力します。例: oidcfacebook
    • Authentication type: ID Token を選択します。
    • JWKS URL: この例では Facebook OIDC を使用しているため、https://www.facebook.com/.well-known/oauth/openid/jwks/ を使用します。
    • Issuer: この例では Facebook OIDC を使用しているため、[https://www.facebook.com](https://www.facebook.com) を使用します。

    Image shows the Create Open ID (OIDC) form

  6. Next をクリックします。

  7. システムが ID トークン内のユーザーアイデンティティを解析して AccelByte アカウントに変換できるようにマッピングします。トークンクレームの詳細については、Claims を参照してください。

    Image shows the Claims Mapping page

  8. システムは作成した OIDC の詳細ページにリダイレクトします。Activate をクリックして OIDC を有効化します。

    Image shows the Detail page of the new login method

Access Token type

Access Token タイプは、UserInfo API エンドポイントを介してアクセストークンを検証することで認証をサポートします。Access Token タイプは、IdP が ID トークンを提供できないものの、アクセストークンとともに使用できる User Info エンドポイントを持っている場合のカスタム要件向けです。

IdP を設定する

以下の手順に従って、ゲームに IdP の OIDC ログインを設定します。これにより、プレイヤーは自分のアカウントを使用してゲームにサインインできるようになります。

Access Token タイプを使用するには、IdP の OIDC を AGS と統合するために以下の項目が必要です。

  • User Info エンドポイント URL
  • User Info エンドポイントの HTTP メソッド

例として、Okta を IdP として使用します。OIDC をサポートする他の IdP を使用することもできます。

Okta アプリケーションを作成する

Okta の Create OIDC app integrations ガイドに従って、Okta アプリケーションを作成します。

以下の URL を使用して、Okta アプリケーションのサインインリダイレクト URI を設定します。

  • <BaseURL>/iam/v3/platforms/<PlatformId>/authenticate
  • <BaseURL>/iam/v3/public/namespaces/<namespace>/users/me/platforms/<platformId>/web/link/establish
注記
  • BaseURL はドメインアドレスです。例: https://development.accelbyte.io
  • Namespace はパブリッシャーまたはスタジオの namespace です。例: accelbyte
  • PlatformId は、AGS Admin Portal で設定する OIDC の PlatformId です。

インゲームログインを設定する

インゲームの OIDC ログインを設定し、プレイヤーが自分の IdP アカウントを使用してサインインできるようにするには、以下の手順に従います。

  1. AGS Admin Portal で、ゲーム namespace に移動します。

  2. サイドバーメニューで、Foundations > 3rd Party Integrations > Auth & Account Linking に移動します。

  3. Auth & Account Linking ページで、+ Add New ボタンをクリックします。

    Image shows the Auth &amp; Account Linking page

  4. ログイン方式オプションの一番下にある + Create OIDC をクリックします。

    Image shows the Create OIDC button

  5. Create OpenID Connect (OIDC) フォームで、必要な情報を入力します。この例 (Okta) では、認証タイプとして Access Token を使用します。

    • Platform Name: OIDC の名前を入力します。例: oidc okta access token
    • Platform ID: OIDC の ID を入力します。oktaaccesstoken
    • Authentication type: Access Token を選択します。
    • UserInfo Endpoint: Okta アプリケーションのユーザー情報エンドポイントを使用します。例: https://YOUR_OKTA_URL.okta.com/oauth2/v1/userinfo
    • HTTP Method: IdP が使用する対応する HTTP メソッドを入力します。例: GET

    Image shows the Create OIDC page

  6. Next をクリックします。

  7. システムが User Info エンドポイントのレスポンスを解析して AccelByte アカウントに変換できるように、ユーザーアイデンティティをマッピングします。

    Image shows the Token Claims Mapping form

  8. システムは作成した OIDC の詳細ページにリダイレクトします。Activate をクリックして OIDC を有効化します。

    Image shows the OIDC details page

Create an IAM client for OIDC

IAM クライアントは、対象プラットフォームでリリースしたいゲームクライアントを表すものです。

特定の SDK プラットフォーム(例: Xbox、Steam、または PlayStation)向けにゲームの IAM クライアントを既に持っている場合、新しい IAM クライアントを作成する必要はありません。IdP はゲームを構築するためのプラットフォームではないため、既存の IAM クライアントを使用できます。IAM クライアントの詳細については、Manage Access control for applications の記事を参照してください。

In-game login

各ゲームエンジンごとに設定方法が異なります。お使いのゲームエンジンに適用される手順に従ってください。

Unreal Engine in-game login integration

インゲームサインインのために AccelByte SDK とゲームをシームレスに統合し、プレイヤーが OIDC 認証情報を使用してゲームにアクセスできるようにします。Unreal Engine 4 の IdP サポートの制約上、ここでは特定のアプローチを採用しており、この実装には Web ログインが必要です。

Unreal Engine preparation and configuration

依存関係の追加

まず、AccelbyteUe4Sdk パブリック依存モジュールを build.cs ファイルに組み込みます。このリンクにより、AccelByte SDK プラグインを Unreal Engine プロジェクトに統合できます。

public ABThirdPartyLogin(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "AccelByteUe4Sdk", "HTTP"});
}

Unreal Engine は外部ブラウザからの URI リダイレクトをサポートしていないため、Unreal 自体の中でインゲームブラウザを利用する必要があります。これには、以下のように build.cs ファイルにプライベート依存モジュールを追加する必要があります。

PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore", "UMG", "WebBrowser", "WebBrowserWidget" });

<YourProject>.Target.csAccelbyteUe4Sdk を追加します。

public ABThirdPartyLoginTarget( TargetInfo Target) : base(Target)
{
Type = TargetType.Game;
DefaultBuildSettings = BuildSettingsVersion.V2;
ExtraModuleNames.AddRange( new string[] { "ABThirdPartyLogin", "AccelByteUe4Sdk" } );
}

そして <YourProjectEditor>.Target.cs

public ABThirdPartyLoginEditorTarget( TargetInfo Target) : base(Target)
{
Type = TargetType.Editor;
DefaultBuildSettings = BuildSettingsVersion.V2;
ExtraModuleNames.AddRange( new string[] { "ABThirdPartyLogin", "AccelByteUe4Sdk" } );
}

UE project settings for OIDC login

DefaultEngine.ini ファイルに AccelByte の認証情報を追加します。

[/Script/AccelByteUe4Sdk.AccelByteSettings]
ClientId=<Your Client_Id>
ClientSecret=<Your Client_Secret>
Namespace=<Your Namespace>
PublisherNamespace=<Your Publisher Namespace>
RedirectURI="http://127.0.0.1"
BaseUrl="https://prod.gamingservices.accelbyte.io"
IamServerUrl="https://prod.gamingservices.accelbyte.io/iam"
PlatformServerUrl="https://prod.gamingservices.accelbyte.io/platform"

Sample code implementation

次のステップは、提供されているサンプルコードを使用してゲームに OIDC 認証方式を実装することです。まず C++ クラスを作成します。例えば、以下のコードはアクター class.LoginActor.h を利用します。

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SWebBrowser.h"
#include "HttpModule.h"
#include "Core/AccelByteRegistry.h"
#include "Api/AccelByteUserApi.h"
#include "Core/AccelByteApiClient.h"
#include "Core/AccelByteMultiRegistry.h"
#include "Core/AccelByteMultiRegistry.h"
#include "Core/AccelByteError.h"

#include "LoginActor.generated.h"

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FActionInfo, FString, Message);

UCLASS()
class ABTHIRDPARTYTEST_API ALoginActor : public AActor
{
GENERATED_BODY()

public:
// Sets default values for this actor's properties
ALoginActor();
UPROPERTY(BlueprintAssignable)
FActionInfo OnActionInfoUpdated;

private:
TSharedPtr<SWebBrowser> SlateBrowserWidget;
FHttpModule* HttpModule;

protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString ClientID;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString ClientSecret;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString RedirectURI;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString AuthorizationUrl;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString TokenUrl;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString ServerURL;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString ResponseType;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "OIDC Settings")
FString OIDCScope;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Status")
FString LoginStatus;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Status")
bool bIsLoggedIn;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Status")
FString AccessToken;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OIDC Status")
FString IdToken;

public:
UFUNCTION(BlueprintCallable, Category = "OIDC")
void ExecBroadcast();

void HandleUrlChanged(const FText& Text);

void OnAccessTokenReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
void ParseAndHandleTokens(const FString& ResponseBody);
void LoginWithOtherPlatformId(const FString& PlatformId, const FString& Token, const FVoidHandler& OnSuccessDelegate);

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};

Obtain an ID Token or Access Token

アプリケーションで ID トークンまたはアクセストークンを取得する方法は、Authorization Code を使用してトークンを取得する方法と、ID トークンを直接処理する方法の 2 つのシナリオに分かれます。

Authorization Code を使用してトークンを取得する

アプリケーションが ID トークンまたはアクセストークンを取得する最初のステップとして Authorization Code を必要とし、Implicit (Hybrid) Grant Type をサポートしていない場合は、以下の手順に従います。

  1. 初期化と設定: アプリケーションが必要な認証情報、URL、スコープで適切に設定されていることを確認します。
  2. Web ベースの認可: response_typeclient_idredirect_uriscope などの必要なパラメーターを使用して Authorization URL を構築し、認可プロセスを開始します。Web ブラウザウィジェットを起動して、ユーザーに認可ページを表示します。
  3. URL 変更の処理: Web ブラウザウィジェット内での URL の変化を捕捉する URL 変更ハンドラーを実装します。URL に Authorization Code パラメーターが含まれているかを検出します。
  4. トークン交換: Authorization Code が検出された場合、そのコードをアクセストークンおよび(該当する場合)ID トークンと交換するリクエストを構築します。必要なフォームデータ(例: codeclient_idclient_secretredirect_urigrant_type)を含む POST リクエストを Token URL に送信します。
  5. トークンの解析と処理: トークンリクエストからの JSON レスポンスを解析します。レスポンスに access_token フィールドが含まれている場合、アクセストークンと(該当する場合)ID トークンを抽出します。これらのトークンを後続の操作に必要に応じて使用します。
  6. AGS へのログイン: トークンが取得された場合、LoginWithOtherPlatformId メソッドを使用して AGS にログインを試みます。成功およびエラーのシナリオをそれぞれ適切に処理します。
  7. クリーンアップ: 必要に応じて Web ブラウザウィジェットを隠すか閉じます。

ID トークンを直接処理する

レスポンス URL に Platform ID Token フラグメントが直接含まれている場合は、以下の手順に従います。

  1. 初期化と設定: アプリケーションが必要な認証情報、URL、スコープで適切に設定されていることを確認します。
  2. Web ベースの認可: パラメーターを含む Authorization URL を構築して認可プロセスを開始します。Web ブラウザウィジェットを起動します。
  3. URL 変更の処理: URL に ID Token フラグメントが含まれているかを検出します。
  4. トークンの処理: ID Token フラグメントが検出された場合、トークンを文字列として直接処理します。トークンから必要な情報を解析します。
  5. AGS へのログイン: LoginWithOtherPlatformId メソッドを使用して AGS にログインを試みます。成功およびエラーのシナリオを処理します。
  6. クリーンアップ: Web ブラウザウィジェットを隠すか閉じます。

これらの手順に従い、提供されたコードスニペットを利用することで、特定の要件に基づいてアプリケーション内で ID トークンやアクセストークンを効率的に取得できます。

Code example

注記

スニペット内で使用される AccelByteOnlineSubsystemPtr を取得するには、こちらのガイド に従ってください。

LoginActor.cpp

ALoginActor::ALoginActor()
{
// Set this actor to call Tick() every frame.
PrimaryActorTick.bCanEverTick = false;
HttpModule = &FHttpModule::Get();

// Initialize variables with your desired values.
ClientID = TEXT("Your_IdentityProvider_ClientId");
ClientSecret = TEXT("Your_IdentityProvider_ClientSecret");// Used to exchange the authorization_code into idtoken or access token using /oauth2/default/v1/token endpoint.
RedirectURI = TEXT("http://localhost:8080/login/callback");
AuthorizationUrl = TEXT("https://{Your_Identity Provider_BaseUrl}/oauth2/default/v1/authorize");
TokenUrl = TEXT("https://{Your_Identity Provider_BaseUrl}/oauth2/default/v1/token");
OIDCScope = TEXT("openid profile email phone address");
}

// Called when the game starts or when spawned.
void ALoginActor::BeginPlay()
{
Super::BeginPlay();
}

void ALoginActor::ExecBroadcast()
{
// Please be advised that this can be different. Sync it with your own requested form data.
FString AuthorizationURL = AuthorizationUrl + "?response_type=" + ResponseType + "&client_id=" + ClientID +
"&redirect_uri=" + RedirectURI + "&scope=" + OIDCScope + "&state=foo" + "&nonce=nonce";
OnActionInfoUpdated.Broadcast(FString::Printf(TEXT("Trying To Login First")));
TSharedRef<SVerticalBox> MainContent = SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
// WebBrowserWidget will launch in-game browser.
SAssignNew(SlateBrowserWidget, SWebBrowser)
.InitialURL(AuthorizationURL)
.ShowControls(false)
.ShowAddressBar(false)
.ShowErrorMessage(true)
.SupportsTransparency(false)
.SupportsThumbMouseButtonNavigation(false)
.ShowInitialThrobber(true)
.PopupMenuMethod(TOptional<EPopupMethod>())
.ViewportSize(FVector2D::ZeroVector)
.OnUrlChanged_Lambda([this](const FText& Text)
{
FString UrlString = Text.ToString();
UE_LOG(LogTemp, Warning, TEXT("WebBrowser URL changed: %s"), *UrlString);
FText FullUrlText = FText::FromString(UrlString); // Assuming UrlString is the full URL
HandleUrlChanged(FullUrlText);
})];

if (GEngine && GEngine->GameViewport)
{
GEngine->GameViewport->AddViewportWidgetContent(SlateBrowserWidget.ToSharedRef());
}
}

void ALoginActor::HandleUrlChanged(const FText& Text)
{
UE_LOG(LogTemp, Warning, TEXT("The link has changed: %s"), *Text.ToString());
FString UrlString = Text.ToString();

// Check if the URL contains a query parameter or a fragment.
FString AuthorizationCode;
FString PlatformIdToken;

if (UrlString.Contains(TEXT("?code=")))
{
AuthorizationCode = FPlatformHttp::UrlDecode(UrlString.RightChop(UrlString.Find(TEXT("?code=")) + 6));
}
else if (UrlString.Contains(TEXT("#id_token=")))
{
PlatformIdToken = FPlatformHttp::UrlDecode(UrlString.RightChop(UrlString.Find(TEXT("#id_token=")) + 10));
}

// Process the authorization code or ID token.
if (!AuthorizationCode.IsEmpty())
{
// Build the request form data.
FString FormData = TEXT("code=") + AuthorizationCode
+ TEXT("&client_id=") + ClientID
+ TEXT("&client_secret=") + ClientSecret
+ TEXT("&redirect_uri=") + RedirectURI
+ TEXT("&grant_type=authorization_code");

// Make a POST request to exchange the authorization code for an access token or ID Token.
TSharedRef<IHttpRequest> HttpRequest = HttpModule->CreateRequest();
HttpRequest->SetURL(TokenUrl);
HttpRequest->SetVerb(TEXT("POST"));
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded"));
HttpRequest->SetContentAsString(FormData);
HttpRequest->OnProcessRequestComplete().BindUObject(this, &ALoginActor::OnAccessTokenReceived);
HttpRequest->ProcessRequest();

// Hide or close the SWebBrowser widget.
if (SlateBrowserWidget.IsValid())
{
SlateBrowserWidget->SetVisibility(EVisibility::Collapsed);
}
}
else if (!PlatformIdToken.IsEmpty())
{
OnActionInfoUpdated.Broadcast(FString::Printf(TEXT("Platform ID Token : %s"), *PlatformIdToken));

// Call the common handling function for tokens.
ParseAndHandleTokens(PlatformIdToken);

// Hide or close the SWebBrowser widget.
if (SlateBrowserWidget.IsValid())
{
SlateBrowserWidget->SetVisibility(EVisibility::Collapsed);
}
}
}

void ALoginActor::OnAccessTokenReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
if (bWasSuccessful && Response.IsValid())
{
FString ResponseBody = Response->GetContentAsString();
// Parse the JSON response and handle tokens.
ParseAndHandleTokens(ResponseBody);
}
}

//Manage these field as member of the class to make this accessible by each function in ALoginActor class
auto ApiClient = AccelByteOnlineSubsystemPtr->GetApiClient(TEXT("YOUR_KEY"));

void ALoginActor::ParseAndHandleTokens(const FString& ResponseBody)
{
// Remove any line breaks and extra spaces from the response body.
FString CleanedResponseBody = ResponseBody.Replace(TEXT("\n"), TEXT("")).Replace(TEXT(" "), TEXT(""));
UE_LOG(LogTemp, Warning, TEXT("Response Body: %s"), *ResponseBody);
const FVoidHandler OnLoginSuccessDelegate = FVoidHandler::CreateLambda([=]()
{
FAccountUserData AccountUserData = ApiClient->CredentialsRef->GetAccountUserData();
FString AccountUserDataString;
FJsonObjectConverter::UStructToJsonObjectString(AccountUserData, AccountUserDataString);
FString Message = FString::Printf(TEXT("Login to AB Service Success : %s"), *AccountUserDataString);
OnActionInfoUpdated.Broadcast(Message);
UE_LOG(LogTemp, Warning, TEXT("Login to AB Service Success: %s"), *AccountUserDataString);
});
if (CleanedResponseBody.Contains(TEXT("access_token")))
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(CleanedResponseBody);
if (FJsonSerializer::Deserialize(Reader, JsonObject))
{
AccessToken = JsonObject->GetStringField(TEXT("access_token"));
IdToken = JsonObject->GetStringField(TEXT("id_token"));

// Use the access token and ID token as needed.
UE_LOG(LogTemp, Warning, TEXT("Access Token: %s"), *AccessToken);
UE_LOG(LogTemp, Warning, TEXT("ID Token: %s"), *IdToken);
OnActionInfoUpdated.Broadcast(FString::Printf(TEXT("Platform Access Token : %s"), *AccessToken));
OnActionInfoUpdated.Broadcast(FString::Printf(TEXT("Platform ID Token : %s"), *IdToken));
// Try to login into AGS Endpoint
if (!AccessToken.IsEmpty() || !IdToken.IsEmpty())
{
LoginWithOtherPlatformId("oidctest", IdToken, OnLoginSuccessDelegate);
}
}
else
{
FString ErrorMsg = Reader->GetErrorMessage();
UE_LOG(LogTemp, Error, TEXT("Failed to parse JSON response. Error: %s"), *ErrorMsg);
}
}
else if (!CleanedResponseBody.IsEmpty()) // Check if the response body is not empty.
{
// Handle ID token directly as a string.
IdToken = CleanedResponseBody;

// Use the ID token as needed.
UE_LOG(LogTemp, Warning, TEXT("ID Token: %s"), *IdToken);
OnActionInfoUpdated.Broadcast(FString::Printf(TEXT("Platform ID Token : %s"), *IdToken));

// Try to log in to AGS Endpoint.
LoginWithOtherPlatformId("oidctest", IdToken, OnLoginSuccessDelegate);
}
}

void ALoginActor::LoginWithOtherPlatformId(const FString& PlatformId, const FString& Token, const FVoidHandler& OnSuccessDelegate)
{
OnActionInfoUpdated.Broadcast(FString::Printf(TEXT("Login to AGS")));

FAccountUserData AccountUserData = ApiClient->CredentialsRef->GetAccountUserData();

auto UserApi = ApiClient->GetUserApi().Pin();
UserApi->LoginWithOtherPlatformId(PlatformId, Token, OnSuccessDelegate, LoginTestFErrorOAuthHandler);

UE_LOG(LogTemp, Warning, TEXT("Request LoginWithOtherPlatform"));
OnActionInfoUpdated.Broadcast(TEXT("Request LoginWithOtherPlatform"));
}

// Called every frame
void ALoginActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
important

提供されているコードは、あくまで説明とガイドのための一例です。トークンを取得するプロセスについての知見を提供するものですが、実際の実装ではさらに多くの検討事項や制約が発生する可能性があることを認識しておく必要があります。厳格なエラーハンドリングを行い、セキュリティのベストプラクティスに従い、アプリケーション固有の要件に合わせた堅牢な認証およびトークン取得システムを構築するために、包括的なテストを実施してください。

Sample code login log

PIE: Server logged in
PIE: Play in editor total start time 0.317 seconds.
LogViewport: Scene viewport resized to 1282x730, mode Windowed.
LogAccelByte: Warning: [Compatibility] Version mismatch: Expected "group" version "2.11.0"-"2.11.0", found "2.18.1"
LogTemp: Warning: The link has changed: https://dev-23268164.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=0oaaomiaanDOioaIe5d7&redirect_uri=http://localhost:8080/login/callback&scope=openid%20profile%20email%20phone%20address&state=foo
LogTemp: Warning: The link has changed: https://dev-23268164.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=0oaaomiaanDOioaIe5d7&redirect_uri=http://localhost:8080/login/callback&scope=openid%20profile%20email%20phone%20address&state=foo
LogTemp: Warning: The link has changed: https://dev-23268164.okta.com/signin/refresh-auth-state/00JnYaV0WU7hlAu9AXJSC-GtLmPAUwtfEpBP_SHCxO
LogTemp: Warning: The link has changed: https://dev-23268164.okta.com/
LogTemp: Warning: The link has changed: http://localhost:8080/login/callback?code=cnV2E9gIfouXrtaQ9rG347W2o9q7yZ3COO5H3-EfTYI&state=foo
LogTemp: Warning: Access token response: {"token_type":"Bearer","expires_in":3600,"access_token":"xxxxxx","scope":"openid profile address phone email","id_token":"xxxxxx"}
LogTemp: Warning: Access Token: xxxxxx
LogTemp: Warning: ID Token: xxxxxx
LogTemp: Warning: Request LoginWithOtherPlatform
LogTemp: Warning: Login to AB Service Success: {
"authType": "EMAILPASSWD",
"bans": [],
"country": "ID",
"createdAt": "2023-08-30T01:58:08.038119Z",
"dateOfBirth": "",
"displayName": "Ken",
"emailVerified": false,
"enabled": true,
"lastEnabledChangedTime": "0001-01-01T00:00:00Z",
"loginId": "",
"namespace": "sdktest",
"permissions": [],
"phoneVerified": false,
"platformId": "",
"platformUserId": "",
"roles": [
"2251438839e948d783ec0e5281daf05b"
],
"userId": "415271c4ef874a99aa81aa6d0a999e00",
"username": "",
"emailAddress": "",
"avatarUrl": "",
"deletionDate": "",
"deletionStatus": false,
"lastDateOfBirthChangedTime": "0001.01.01-00.00.00",
"namespaceRoles": [
{
"namespace": "*",
"roleId": "2251438839e948d783ec0e5281daf05b"
}
],
"newEmailAddress": "",
"oldEmailAddress": "",
"phoneNumber": "",
"platformAvatarUrl": "",
"platformDisplayName": ""
}

Sample code testing

提供されているコードは、Unreal Engine エディター内で Okta を使用して正常にテストされています。Okta のログインでサインインボタンをクリックすると、自動的にログインします。

Image shows sample code for Unreal code testing

Extend SDK login

Extend SDK を通じて OIDC を統合し、OIDC 認証情報を使用してサインインできます。

// OIDC provider credentials
public class ProviderSpecification
{
[JsonPropertyName("name")]
public string Name { get; set; } = String.Empty;

[JsonPropertyName("key")]
public string Key { get; set; } = String.Empty;

[JsonPropertyName("discovery_url")]
public string DiscoveryUrl { get; set; } = String.Empty;

[JsonPropertyName("client_id")]
public string ClientId { get; set; } = String.Empty;

[JsonPropertyName("client_secret")]
public string ClientSecret { get; set; } = String.Empty;

[JsonPropertyName("scope")]
public string Scope { get; set; } = String.Empty;
}

// Discovery data from provider
public class DiscoveryData
{
[JsonPropertyName("issuer")]
public string Issuer { get; set; } = String.Empty;

[JsonPropertyName("jwks_uri")]
public string JWKSUri { get; set; } = String.Empty;

[JsonPropertyName("authorization_endpoint")]
public string AuthEndpoint { get; set; } = String.Empty;

[JsonPropertyName("token_endpoint")]
public string TokenEndpoint { get; set; } = String.Empty;

[JsonPropertyName("registration_endpoint")]
public string RegistrationEndpoint { get; set; } = String.Empty;

[JsonPropertyName("introspection_endpoint")]
public string IntrospectionEndpoint { get; set; } = String.Empty;

[JsonPropertyName("userinfo_endpoint")]
public string UserInfoEndpoint { get; set; } = String.Empty;

[JsonPropertyName("scopes_supported")]
public List<string> SupportedScopes { get; set; } = new List<string>();

[JsonPropertyName("grant_types_supported")]
public List<string> SupportedGrantTypes { get; set; } = new List<string>();

[JsonPropertyName("claims_supported")]
public List<string> SupportedClaims { get; set; } = new List<string>();

public static DiscoveryData Retrieve(HttpClient httpClient, string discoveryUrl)
{
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, discoveryUrl);

HttpResponseMessage response = httpClient.Send(req);
string jsonString = response.Content.ReadAsStream().ReadToString();
return JsonSerializer.Deserialize<DiscoveryData>(jsonString)!;
}
}

// Method to get authorization token from provider
public OAuthTokens GetAuthorizedToken(ProviderSpecification spec, string authorizationToken)
{
DiscoveryData dData = DiscoveryData.Retrieve(DefaultHttpClient.Http, spec.DiscoveryUrl);

HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, dData.TokenEndpoint);
req.Content = new FormUrlEncodedContent(new Dictionary<string, string>()
{
{"grant_type", "authorization_code" },
{"client_id", spec.ClientId },
{"client_secret", spec.ClientSecret },
{"redirect_uri", "http://localhost:9090/callback" },
{"code", authorizationToken }
});

HttpResponseMessage response = DefaultHttpClient.Http.Send(req);
string jsonString = response.Content.ReadAsStream().ReadToString();

return JsonSerializer.Deserialize<OAuthTokens>(jsonString)!;
}

using IAccelByteSdk sdk = AccelByteSdk.Builder
.UseDefaultHttpClient()
.UseDefaultConfigRepository()
.UseDefaultTokenRepository()
.UseDefaultCredentialRepository()
.Build();

var abPlatformId = "<ab platform id>"
var authCode = "<authorization code from provider>";

var spec = new ProviderSpecification(); //specify or load provider credentials
OAuthTokens tokens = GetAuthorizedToken(spec, authCode);

try
{
string output = String.Empty;
sdk.LoginPlatform(abPlatformId, tokens.ID, (otr) =>
{
output = JsonSerializer.Serialize(otr);
});

// Do something when login succeeds
}
catch (Exception x)
{
// Do something when login fails
}