cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Your Friends List is a way to easily have access to the community members that you interact with the most! X

Create An Authentication Extension Part 2

No ratings

 

Step 4: Install and Configure

 

Before you install the plugin, ensure that software requirements are met for proper installation of the plugin.

 

  1. Open The Eclipse IDE and choose a suitable directory as a workspace.
  2. Go to the menu bar of the Eclipse window and select Help->Install New Software…
  3. After the Install window opens, click Add to add the Eclipse Plugin repository.
  4. Click Archive… and browse to the directory where the Eclipse Plugin zip file is stored and click Open.

    NOTE: Do not extract this zip file.
  5. Enter a name (for example, Eclipse Plugin).

    install-Plugin-1.jpg

     

  6. Click OK.
  7. Ensure that the Group items by category checkbox is not selected.
  8. Select ThingWorx Extension Builder in the items list of the Install window.
  9. Click Next and the items to be installed are listed.

    IoTProductMgmt_1-1664981560844.jpeg

  10. Click Next and review the license agreement.
  11. Accept the license agreement and click Finish to complete the installation process. If a warning for unsigned content is displayed, click OK to complete the installation process.
  12. Restart Eclipse.
  13. When Eclipse starts again, ensure that you are in the ThingWorx Extension perspective. If not, select Window->Perspective->Open Perspective->Other->ThingWorx Extension, then click OK.

    IoTProductMgmt_2-1664981560850.jpeg

     


    IoTProductMgmt_3-1664981560851.jpeg

     

NOTE: Opening any item from File->New->Other…->ThingWorx will also change the perspective to ThingWorx Extension.

 

You are ready to start a ThingWorx Extension Project!

 

Step 5: Create Extension Project

 

In this tutorial, you will create a ThingWorx extension that performs authentication based on your security needs.

 

  1. While in the ThingWorx Extension Perspective, go to File->New->Project.
  2. Click ThingWorx->ThingWorx Extension Project.

    IoTProductMgmt_7-1664982859479.jpeg

     

  3. Click Next.
  4. Enter the Project Name (for example, AuthenticatorExample).
  5. Select Gradle or Ant as your build framework.
  6. Enter the SDK location by browsing to the directory where the Extension SDK is stored.
  7. Enter the Vendor information (for example, ThingWorx Labs).
  8. Select the JRE version to 1.8.
  9. Click Finish. Your newly created project is added to the Package Explorer tab.

The information from ThingWorx Extension Properties is used to populate the metadata.xml file in your project. The metadata.xml file contains information about the extension and details for the various artifacts within the extension. The information in this file is used in the import process in ThingWorx to create and initialize the entities.

 

Create New Authenticator

 

  1. Select your project and click New -> Authenticator to create a new Authenticator.

    eclipse-new-authenticator.png

     

  2. In the new window, enter AwesomeCustomAuthenticator for the Name.

    eclipse-configure-new-authenticator.png

     

  3. If no Server is available, create a Server using any available option. You will not need that for this guide. This Server option might be utilized based on your later needs.
  4. Enter a description to your Authenticator, such as Sample Authenticator that validates against the Thingworx User.
  5. Select Finish.

You will be able to check these settings within the metadata.xml file inside of the configfiles  directory.

 

You will now need to add the stubs for the authenticateissueAuthenticationChallenge, and matchesAuthRequest methods. See below for sample code and descriptions.

 

Method

Description

Constructor

Needed to instantiate new objects of type AwesomeCustomAuthenticator. Instance member data/variable values in your Authenticator will not be available across requests.

initializeEntity

This method is called when the Authenticator Thing is saved in ThingWorx Composer, e.g. saving configuration table updates.

authenticate

The logic/implementation that is used to authenticate a HTTP request.

issueAuthenticationChallenge

Handles logic which follows authentication failure (e.g. logging an error).

matchesAuthRequest

This method determines if this Authenticator is valid for the authentication request type.

 

Below provides more information about each of these methods and some example source code:

 

Constructor:

 

  • A new instance of custom Authenticator class is created to handle each new HTTP request for authentication.
  • Upon importing a custom Authenticator extension, that Authenticator is registered into AuthenticatorManager and can be managed in the ThingWorx Composer with the other system authenticators.
  • When that custom Authenticator is enabled, it will be used in conjunction with the other configured Authenticators to attempt to authenticate HTTP requests.
  • Any static data for each new authentication instance should be thread safe.
  • Best to avoid putting very much logic here, even calls to get configuration or instance data (use authenticate method instead).

 

initializeEntity:

 

  • Read configuration data into properties as needed for Authenticator challenges.
  • Write the LDAP server address to some static property for use across all future instances for use in Authenticator challenges.
  • This would be a way to ensure the LDAP server location is configurable from within ThingWorx Composer.
  • Best to update this only once (e.g. for when the first connection is made).

 

authenticate:

 

  • If the authentication logic/implementation fails to authenticate the HTTP request due to error in the logic or the HTTP request contained invalid data that does not pass authentication, then this implementation should throw an exception.

 

Example code below:

 

@Override
    public void authenticate(HttpServletRequest request, HttpServletResponse response) throws AuthenticatorException {
        String username = request.getHeader("User"), password =  request.getHeader("Password");
        if(username.isEmpty() || password.isEmpty())
            throw new AuthenticatorException("User login info is empty");
        
        try {
            // This section logs the latest login time and login user to a thing called MyThing
            // Subscribing to these properties via DataChange event will allow this information to be stored
            Thing LoginHelper = (Thing) EntityUtilities.findEntity("MyThing", ThingworxRelationshipTypes.Thing);
            LoginHelper.setPropertyValue("LatestLoginUser", new StringPrimitive(username));
            LoginHelper.setPropertyValue("LatestLoginTime", new DatetimePrimitive(DateTime.now()));
            
            _logger.warn(DateTime.now() + " -- " + username + " login attempt");
            
            // Checks that user exists and is enabled; throws exception if can't validate
            // May want to create user in ThingWorx if they don't exist
            AuthenticationUtilities.validateEnabledThingworxUser(username);
            
            // Checks that user exists and validates credentials through all configured DirectoryServices
            // (one is the internal directory of ThingWorx users, one could be LDAP if configured);
            // throws exception if can't validate
            AuthenticationUtilities.validateCredentials(username, password);
            
            // REQUIRED: tells rest of ThingWorx which user is logged in for purposes of permissions, etc.
            this.setCredentials(username);
        }   
    }

 

issueAuthenticationChallenge:

 

  • This may not be used at all, or it may be used for alerting or logging.
  • May be used for constructing and sending a response to the client so the client can ask the user to enter credentials again (i.e. authentication challenge).

matchesAuthRequest:

 

Example code below. This sample code for Authenticator to automatically login the user with default username/password when specific URI used in web browser.

 

@Override
public boolean matchesAuthRequest(HttpServletRequest httpRequest) throws AuthenticatorException {
    String requestURI = httpRequest.getRequestURI();
    // Must access it from this URL and not from /Thingworx/Runtime/index.html#mashup=LogoutButtonMashup as
    // the Request URI in the latter case is always going to show as /Thingworx/Runtime/index.html
    if (requestURI.equals("/Thingworx/Mashups/LogoutButtonMashup"))       
        return true;
    else
        return false;
}

 

Below is another example of how to implement the matchesAuthRequest method. Of course, it’s not a safe method. Nevertheless, it provides input into a different way to handle things.

 

@Override
public boolean matchesAuthRequest(HttpServletRequest request) throws AuthenticatorException {
    try {
        
        // DON'T DO THIS by itself -- getHeader returns null if it can't find the header, 
        // so this is unsafe and may block other authenticators from attempting
        String value1 = request.getHeader("User");
        String value2 = request.getHeader("Password");

        // DO ADD THIS - this is safe
        // Optionally add some logging statement here to inform of missing headers
        if(value1 == null || value2 == null)
            return false;

        return true;
    } catch(Exception e) {
        // This won't normally hit. This is really for other, more complicated validation processes
        throw new AuthenticatorException("Missing headers");
    }
}

 

Step 6: Build Extension

 

You can use either Gradle or Ant to build your ThingWorx Extension Project.

 

Build Extension with Gradle

 

  1. Right click on your project ->Gradle (STS)->Tasks Quick Launcher.

    gradle-build.jpg

     

  2. Set Project from the drop-down menu to your project name and type Tasks as build.
  3. Press Enter. This will build the project and any error will be indicated in the console window.

    gradle-build-2.png

     

  4. Your console window will display BUILD SUCCESSFUL. This means that your extension is created and stored as a zip file in your_project->build->distributions folder.

    gradle-success.jpg

 

Build Extension with Ant

 

  1. Go to the Package explorer -> your_project->.
  2. Right click on build-extension.xml->Run As->Ant Build.

    ant-build-1.png

     

  3. Your console output will indicate BUILD SUCCESSFUL similar to the below text:
build:
     [echo] Building AuthenticatorExample extension package...
BUILD SUCCESSFUL
Total time: 770 milliseconds
 
NOTE: This will build your project and create the extension zip in the AuthenticatorExample->build->distributions folder of your project.
 
 
Click here to view Part 3 of this guide.
 
Version history
Last update:
‎Mar 07, 2023 02:42 PM
Updated by:
Labels (2)
Contributors