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

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

Last updated on February 4, 2026

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

概要

本ガイドでは、OpenID Connect (OIDC) をAccelByte Gaming Services (AGS) と統合する方法について説明します。AGSでは、Authorization CodeID TokenAccess Tokenの3つのOIDC認証タイプをサポートしています。

ゲームによっては、本ガイドに記載されていない追加のアイデンティティプロバイダー機能を設定する必要がある場合があります。OIDCサービスの設定に関する詳細については、ご利用のアイデンティティプロバイダーのドキュメントをご参照ください。

important

本ガイドは一般公開用であり、機密保持の観点から一部の情報が省略されています。完全な機密ガイドを先にご確認されることをお勧めします。機密ガイドのコピーをご希望の場合は、AccelByteテクニカルプロデューサーまでお問い合わせください。

目標

  • AccelByteのGame SDKを使用して、ゲームでOIDC認証を有効にする
  • AGSのPlayer Portalを使用して、パブリッシャーウェブサイトでOIDC認証を有効にする

前提条件

ウェブログイン統合

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

ウェブログイン統合は現在AGS Shared 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) Clientsの基礎知識

Authorization Codeタイプ

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

IdPの設定

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

ここでは、Okta OIDCを例としてOIDC Player PortalおよびAdmin Portalのログイン設定を説明します。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. サイドバーメニューで、Game Setup > 3rd Party Configuration > Auth & Account Linkingに移動します。

  3. Login Methodsページで、+ Add Newボタンをクリックします。

    Image shows the Login Methods 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: 用途に応じて、Player Portal、Launcher、Admin Portal、ゲーム内ログインで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トークン内のユーザーIDをマッピングし、システムがAccelByteアカウントに解析できるようにします。

    Image hows the Token Claims Mapping form

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

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

    注記

    Register Domainは、特定のドメインのユーザーにロールを自動的に割り当てたい場合に便利です。例えば、Admin PortalへのログインにOIDCを使用し、<your-domain>ドメインのユーザーがOIDCでログインした際に管理者ロールを自動的に付与したい場合に使用します。

    • この手順をスキップするには、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アカウントにリンクするか、新しいAccelByteアカウントを作成するよう求めます。さらに、プレイヤーがヘッドレスアカウントを使用してPlayer Portalに直接ログインできるようにプラットフォームを設定できます(つまり、登録フォームは不要です)。

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

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

注記

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

  1. Admin Portalに移動します。システムはログインページにリダイレクトします。OIDCロゴをクリックします。複数ある場合は、ボタンにカーソルを合わせて正しいOIDCログインを使用していることを確認します。

    Image shows the Admin Portal page

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

    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トークンタイプ

IDトークンタイプは、JWKSを介したIDトークンの検証による認証をサポートします。IDトークンはゲーム内フローベースの認証用です。アイデンティティプロバイダーから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 AccountでFacebookアプリケーションを作成します。

アプリにFacebookログイン製品を追加する

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

ゲーム内ログインの設定

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

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

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

  3. Login Methodsページで、+ Add Newボタンをクリックします。

    Image shows the Login Methods 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 (/images/moved-ags-en/services/01_access/03_auth/oidc/18_createconfigidtoken1.png)

  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

アクセストークンタイプ

アクセストークンタイプは、UserInfo APIエンドポイントを介してアクセストークンを検証することで認証をサポートします。アクセストークンタイプは、IdPがIDトークンを提供できないが、アクセストークンで使用できるUser Infoエンドポイントがある場合のカスタムニーズ用です。

IdPの設定

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

アクセストークンタイプを使用するには、IdP OIDCをAGSと統合するために次の項目が必要です:

  • User Info Endpoint URL
  • User Info Endpoint 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. サイドバーメニューで、Game Setup > 3rd Party Configuration > Auth & Account Linkingに移動します。

  3. Login Methodsページで、+ Add Newボタンをクリックします。

    Image shows the Login Methods 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アプリケーションのuser infoエンドポイントを使用します。例: 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

OIDC用のIAMクライアントの作成

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

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

ゲーム内ログイン

各ゲームエンジンの設定は異なります。ゲームエンジンに適用される手順に従ってください。

Unreal Engineゲーム内ログイン統合

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

Unreal Engineの準備と設定

依存関係の追加

まず、build.csファイルにAccelbyteUe4Sdkパブリック依存関係モジュールを組み込みます。このリンクにより、AccelByte SDK Pluginを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" } );
}

OIDCログイン用のUEプロジェクト設定

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"

サンプルコード実装

次のステップは、提供されているサンプルコードを使用してゲームの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;
};

IDトークンまたはアクセストークンの取得

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

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トークンまたはアクセストークンを効率的に取得できます。

コード例

注記

スニペットで使用される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

提供されているコードは、例示とガイドとしてのみ機能します。トークンを取得するプロセスに関する洞察を提供しますが、実際の実装には追加の考慮事項と制限が含まれる可能性があることを認識することが不可欠です。厳密なエラー処理を確保し、ベストセキュリティプラクティスに従い、アプリケーションの特定の要件に合わせた堅牢な認証およびトークン取得システムを確立するために包括的なテストを実施してください。

サンプルコードログインログ

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": ""
}

サンプルコードテスト

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

Image shows sample code for Unreal code testing

Extend SDKログイン

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
}