Usage

Twitch Developer Acccount

To use the TwitchAuthComponent you first need to setup a Twitch Developer Account, so that you can create a Client ID.

Create your Twitch Developer Account here.

Registering a Twitch App

If you got your Twitch Developer Account setup, navigate to your dashboard and from there view your apps:

TwitchDevDashboard

Next register a new application:

TwitchDevRegisterApp

NOTE

It is important to enter the http://localhost address in the OAuth Redirect URI, otherwise it will not work.

After the application is registered you will be taken to the Manage Application page, here we can find the Client ID we need.

TwitchDevManageApp

Before You Dive In

Plugin Content

NOTE

There are two examples included in the content of the plugin. There you can get you hands wet without re-drawing the blueprints below.

To access the content you just have to enable Show Plugin Content in the Content Browser.

PluginContent

Browser Cache

While testing and implementing your Twitch authentication within your game you are likely to test with different Twitch accounts, as the web browser used within Unreal Engine 4 automatically caches the previous authentications (when sucessfull) you need to clear the browser cache before you test with a different account.

You can delete the cache in your projects when you delete this project folder Saved/webache.

WARNING

You have to shut down the editor to this.

Blueprint

In-Game Web Browser Setup

To use the plugin we need a web browser to display the Twitch authentication page. The plugin is designed so that you can place the web browser in a Widget Blueprint any way you want.

Create a Widget Blueprint and add a web browser to the canvas. The web browser can be found under the experimental category.

NOTE

If you can not find the web browser please enable it in the plugin settings of your project. It can be found under Build-In -> Widgets menu.

WebBrowserSetup

Host Actor

Now we need a new Blueprint Actor that will use the TwitchAuthComponent that ships with this plugin.

Let's create the Actor and add the component to it.

AddComponent

Component Properties

There are two properties on the component.

  1. Twitch application Client ID that will be needed to communicate to the Twitch API
  2. Flag, whether the authentication is verified every time the user start the game.

ComponentProperties

NOTE

Please read the section Twitch Developer Account on how to retrieve your Client ID.

Component Events

Before we start implementing the actual blueprint let's create the needed events that the component provides for us. As we are dealing with HTTP requests to the Twitch REST API we need callback events when we trigger an action on the component.

ComponentEvents

On User Authenticated

This is the callback event for when the authentication process has finished.

On User Subcribed To Channel

This is the callback event for when the check for a subscription against the Twitch API finishes.

On Authentication Page Loaded

This event is a little different. It is meant to be used to control the flow of the UI. Common use case for this event is the enabling of the mouse cursor so that the player can interact with the authentication web page.

On Access Token Page Loaded

This event is fired when the access token page is loaded into the web browser. As this page is only used to extract the access token from the processed authentication we can use it to hide the web browser.

Now we can start implementing the authentication logic.

On BeginPlay

On BeginPlay we will create web browser widget and start the authentication process via the previously added component.

OnBeginPlay

On Authentication Page Loaded

On Authentication Page Loaded we will enable the mouse cursor so that the player can interact with the web browsers content.

OnAuthenticationPageLoaded

On Access Token Page Loaded

On Access Token Page Loaded we will again disable the mouse cursor and hide the web browser as the access token page does not contain any content.

OnAccessTokenPageLoaded

On User Authenticated

On User Authenticated we can check if the authentication went through successfully. If it did we can retrieve the authenticated user and check if the user is subscribed to a channel. If the authentication did not finish successfully we can retrieve the last error and print it.

Authentication Successful

OnAuthenticationSuccessful

Authentication Failed

OnAuthenticationFailed

On User Subscribed To Channel

On User Subscribed To Channel we can now process to continue the game, in the given case we just print a message.

OnUserSubscribedToChannel

C++

Modules Setup

As we are trying to use the plugins content through C++ we have to added it as a dependency.

ModulesSetup

NOTE

We also need to add the dependency for the "WebBrowserWidget" as TwitchAuth depends on it.

Host Actor

First we need to create a new C++ Actor that will serve as a host to our component.

Choose Actor as the Parent Class:

ParentClass

And give the child a name:

NameClass

Once the class has been added and the compilation finished successfully Visual Studio will open automatically. Now that we have a new Actor Class we can add the TwitchAuthComponent to it.

Component Events

Before we start implementing the actual code let's go over the events that the component provides for us. As we are dealing with HTTP requests to the Twitch REST API we need callback events when we trigger an action on the component.

On User Authenticated

This is the callback event for when the authentication process has finished.

On User Subcribed To Channel

This is the callback event for when the check for a subscription against the Twitch API finishes.

On Authentication Page Loaded

This event is a little different. It is meant to be used to control the flow of the UI. Common use case for this event is the enabling of the mouse cursor so that the player can interact with the authentication web page.

On Access Token Page Loaded

This event is fired when the access token page is loaded into the web browser. As this page is only used to extract the access token from the processed authentication we can use it to hide the web browser.

Now we can start implementing the authentication logic.

Implementation (Header)

First we need to include the header file of the component:

#include "TwitchAuthComponent.h"

Then let's add the component as a public property and create our constructor:

public:	
    ATwitchAuthExampleActor();

    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Twitch Auth")
    class UTwitchAuthComponent* TwitchAuthComponent;

Finally we need callback methods that will handle our above mentioned events:

protected:    
    UFUNCTION()
    void HandleOnAccessTokenPageLoaded();

    UFUNCTION()
    void HandleOnAuthenticationPageLoaded();

    UFUNCTION()
    void HandleOnUserAuthenticated(bool bAuthenticated);

    UFUNCTION()
    void HandleOnUserSubscribedToChannel(bool bSubscribed, FTwitchSubscription TwitchSubscription);

NOTE

It is important to mark all this methods as UFUNCTIONs as does will be bound to the events provided by the component.

At last we write a little helper function to print a Twitch error if we encounter one:

private:
    void PrintTwitchError(FTwitchError TwitchError);

This is our complete header file:

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TwitchAuthComponent.h"
#include "TwitchAuthExampleActor.generated.h"

UCLASS()
class FFGPLUGINS_API ATwitchAuthExampleActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ATwitchAuthExampleActor();

    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Twitch Auth")
    class UTwitchAuthComponent* TwitchAuthComponent;

protected:
    UFUNCTION()
    void HandleOnAccessTokenPageLoaded();

    UFUNCTION()
    void HandleOnAuthenticationPageLoaded();

    UFUNCTION()
    void HandleOnUserAuthenticated(bool bAuthenticated);

    UFUNCTION()
    void HandleOnUserSubscribedToChannel(bool bSubscribed, FTwitchSubscription TwitchSubscription);

private:
    void PrintTwitchError(FTwitchError TwitchError);

};

Implementation (Source)

As we are dealing with a component we have to create and add it to the actor in the constructor:

ATwitchAuthExampleActor::ATwitchAuthExampleActor()
{
	PrimaryActorTick.bCanEverTick = false;

    // Creating the Twitch Auth component.
    TwitchAuthComponent = CreateDefaultSubobject<UTwitchAuthComponent>(TEXT("Twitch Auth"));
    
    // Set the client ID.
    TwitchAuthComponent->ClientId = "<your_client_id_here>";
    // And the verification.
    TwitchAuthComponent->bForceVerify = true;

    // Finally, we wire up our handler methods.
    TwitchAuthComponent->OnAuthenticationPageLoaded.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnAuthenticationPageLoaded);
    TwitchAuthComponent->OnAccessTokenPageLoaded.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnAccessTokenPageLoaded);
    TwitchAuthComponent->OnUserAuthenticated.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnUserAuthenticated);
    TwitchAuthComponent->OnUserSubscribedToChannel.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnUserSubscribedToChannel);
}

To handle the visibility aspect of the web browser displaying the authentication page and receiving the access token URL page we can use the following callback methods:

void ATwitchAuthExampleActor::HandleOnAccessTokenPageLoaded()
{
    // We hide the web browser when the access token URL comes in.
    UWebBrowser* webBrowser = TwitchAuthComponent->GetWebBrowser();
    webBrowser->SetVisibility(ESlateVisibility::Hidden);
}

void ATwitchAuthExampleActor::HandleOnAuthenticationPageLoaded()
{
    // We show the web browser when the authentication web page loaded in.
    UWebBrowser* webBrowser = TwitchAuthComponent->GetWebBrowser();
    webBrowser->SetVisibility(ESlateVisibility::Visible);
}

When the authentication process finishes we have access to the authenticated user and can start to check for subscriptions:

void ATwitchAuthExampleActor::HandleOnUserAuthenticated(bool bAuthenticated)
{
    // First we check if the authentication went through successfully.
    if(bAuthenticated == true)
    {
        // Now we can retrieve the authenticated Twitch user.
        FTwitchUser user = TwitchAuthComponent->GetUser();

        // Writing out a little debug message.
        const FString message = user.display_name + " just signed in!";
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, message);

        // And now we can check if the authenticated Twitch user is subscribed to a Twitch channel.
        TwitchAuthComponent->IsUserSubscribedToChannel("hardlydifficult");
    }
    else
    {
        // If authentication was not successful we get the last error and print it.
        FTwitchError error = TwitchAuthComponent->GetLastError();
        PrintTwitchError(error);
    }
}

After the subscription check process finishes we have access to the subscription data and know what to do with the player:

void ATwitchAuthExampleActor::HandleOnUserSubscribedToChannel(bool bSubscribed, FTwitchSubscription TwitchSubscription)
{
    // First we check if a subscription is present.
    if(bSubscribed == true)
    {
        // We again here get the Twitch user, but only to print a debug message.
        FTwitchUser user = TwitchAuthComponent->GetUser();

        // Creating and printing the debug message.
        const FString message = user.display_name + " is subscribed to the channel " + TwitchSubscription.channel.name;
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, message);
        
        // Load up the game...
    }
    else
    {
        // If the request was not successful we get the last error and print it.
        FTwitchError error = TwitchAuthComponent->GetLastError();
        PrintTwitchError(error);
        
        // Show message that to the player "Nope, you're not a subscriber..."
    }
}

Finally the source code for our little helper method we used throughout the implementation:

void ATwitchAuthExampleActor::PrintTwitchError(FTwitchError TwitchError)
{
    // Creating the print message out of the given Twitch error.
    const FString message = TwitchError.error + "(" + FString::FromInt(TwitchError.status) + "): " + TwitchError.message;
    
    // And print it.
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, message);
}

This is our complete source file:

#include "TwitchAuthExampleActor.h"

ATwitchAuthExampleActor::ATwitchAuthExampleActor()
{
	PrimaryActorTick.bCanEverTick = false;

    // Creating the Twitch Auth component.
    TwitchAuthComponent = CreateDefaultSubobject<UTwitchAuthComponent>(TEXT("Twitch Auth"));
    
    // Set the client ID.
    TwitchAuthComponent->ClientId = "<your_client_id_here>";
    // And the verification.
    TwitchAuthComponent->bForceVerify = true;

    // Finally, we wire up our handler methods.
    TwitchAuthComponent->OnAuthenticationPageLoaded.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnAuthenticationPageLoaded);
    TwitchAuthComponent->OnAccessTokenPageLoaded.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnAccessTokenPageLoaded);
    TwitchAuthComponent->OnUserAuthenticated.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnUserAuthenticated);
    TwitchAuthComponent->OnUserSubscribedToChannel.AddDynamic(this, &ATwitchAuthExampleActor::HandleOnUserSubscribedToChannel);
}

void ATwitchAuthExampleActor::HandleOnAccessTokenPageLoaded()
{
    // We hide the web browser when the access token URL comes in.
    UWebBrowser* webBrowser = TwitchAuthComponent->GetWebBrowser();
    webBrowser->SetVisibility(ESlateVisibility::Hidden);
}

void ATwitchAuthExampleActor::HandleOnAuthenticationPageLoaded()
{
    // We show the web browser when the authentication web page loaded in.
    UWebBrowser* webBrowser = TwitchAuthComponent->GetWebBrowser();
    webBrowser->SetVisibility(ESlateVisibility::Visible);
}

void ATwitchAuthExampleActor::HandleOnUserAuthenticated(bool bAuthenticated)
{
    // First we check if the authentication went through successfully.
    if(bAuthenticated == true)
    {
        // Now we can retrieve the authenticated Twitch user.
        FTwitchUser user = TwitchAuthComponent->GetUser();

        // Writing out a little debug message.
        const FString message = user.display_name + " just signed in!";
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, message);

        // And now we can check if the authenticated Twitch user is subscribed to a Twitch channel.
        TwitchAuthComponent->IsUserSubscribedToChannel("hardlydifficult");
    }
    else
    {
        // If authentication was not successful we get the last error and print it.
        FTwitchError error = TwitchAuthComponent->GetLastError();
        PrintTwitchError(error);
    }
}

void ATwitchAuthExampleActor::HandleOnUserSubscribedToChannel(bool bSubscribed, FTwitchSubscription TwitchSubscription)
{
    // First we check if a subscription is present.
    if(bSubscribed == true)
    {
        // We again here get the Twitch user, but only to print a debug message.
        FTwitchUser user = TwitchAuthComponent->GetUser();

        // Creating and printing the debug message.
        const FString message = user.display_name + " is subscribed to the channel " + TwitchSubscription.channel.name;
        GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, message);
        
        // Load up the game...
    }
    else
    {
        // If the request was not successful we get the last error and print it.
        FTwitchError error = TwitchAuthComponent->GetLastError();
        PrintTwitchError(error);
        
        // Show message that to the player "Nope, you're not a subscriber..."
    }
}

void ATwitchAuthExampleActor::PrintTwitchError(FTwitchError TwitchError)
{
    // Creating the print message out of the given Twitch error.
    const FString message = TwitchError.error + "(" + FString::FromInt(TwitchError.status) + "): " + TwitchError.message;
    
    // And print it.
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, message);
}

That's it, now you just have to call the Authenticate method within a child blueprint:

OnBeginPlay