Chat bot integration patterns

Integrate 3rd party AI Chat Bots with IBM Security Verify

Introduction

Chat bots extend the medium of interaction with consumers. In the context of consumer identity and access management (CIAM), brands can interact with consumers in a logical and automated way while also ensuring trust and providing a seamless experience. Chat bot integration with IAM is an area where newer interaction models can be enabled.

IBM Security Verify can be enabled to use chat bots for infusing security challenges to establish and sustain trust through chat bot interactions.

The following document describes the steps for configuring an AI Chat Bot for IBM Security Verify. This document specifies how to use Watson Assistant with IBM Security Verify. IBM Security Verify can extend and integrate to other chat bots as required.

Pre-requisites

To get started with IBM Security Verify integrations with Watson Assistant, the following pre-requisites are needed for this chat bot integration. Other chat bot integrations are possible with IBM Security Verify.

Developers should have familiarity with chat bots, IBM Security Verify, and REST API calls.

Create an IBM Cloud Function

1768

Steps to create an IBM Cloud Function

  1. Click Start Creating
  2. ChooseAction” from the Single entitles category
  3. Give your action a name
  4. This will be used for reference later.
  5. Choose your runtime language
936
  1. In the code page, copy this code. Ensure you change the tenantid, clientid, and clientsecret. Add additional methods and rest calls as needed.
#
#
# main() will be run when you invoke this action
#
# @param Cloud Functions actions accept a single parameter, which must be a JSON object.
#
# @return The output of this action, which must be a JSON object.
#
#
import sys
import os
import requests
import json
import base64
import random
from flask import Flask, request, jsonify

tentantid="https://mytenatn.ice.ibmcloud.com"
clientid="46e458c7-33f4-XXXXXX"
clientsecret="abcdef"

def main(dict):
    action = dict.get("action")
    if action == "lookup":
        username = dict.get("userName")
        response=accountlookup(username)
        return response
    if action == "email":
        otpmethod = dict.get("method")
        target = dict.get('target')
        response=initiate_email(method=otpmethod, target=target)
        return response
    if action == "sms":
        otpmethod = dict.get("method")
        target = dict.get('target')
        response=initiate_sms(method=otpmethod, target=target)
        return response
    if action == "verify":
        txnid = dict.get('txnid')
        method = dict.get('method')
        otp = dict.get('otp')
        response=verify(txnid=txnid, method=method, otp=otp)
        return response
    if action == "reset":
        userid = dict.get('userid')
        response = pwreset(userid)
        return response
    if action == "showotp":
        userid = dict.get('userid')
        response = showotp(userid)
    response = {'message': "Sorry, I didn't understand"}
    return response
def auth():
    url = tentantid + ":443/v1.0/endpoint/default/token"
    payload = "grant_type=client_credentials&client_id=" + clientid + "&client_secret=" + clientsecret + "&scope=openid"
    headers = {
        'Content-Type': "application/x-www-form-urlencoded"
        }
    response = requests.request("POST", url, data=payload, headers=headers)
    return response.json()["access_token"]
def showotp():
    access_token = auth()
    url = tentantid + "/v2.0/factors/otp"
    payload = "{\r\n  \"correlation\": \"1234\"}"
    headers = {
        'Authorization': "Bearer "+access_token,
        'Content-Type': "application/json"
        }
    response = requests.request("POST", url, data=payload, headers=headers)
    if response.status_code == 202:
        resp = {
                    "txnid": response.json()["id"], 
                    "correlation": response.json()["correlation"],
                    "otp": response.json()["otp"],
                    'status_code': 200
                }
    else:
        resp = {
                'messages': "Nope.. that didnt work.",
                'status_code': 400        
        }
    return resp
def initiate_email(method, target):
    access_token = auth()
    url = tentantid + "/v1.0/authnmethods/" + method + "/transient/verification"
    payload = "{\r\n  \"correlation\": \"1234\",\r\n  \"otpDeliveryEmailAddress\": \""+target+"\"\r\n}"
    headers = {
        'Authorization': "Bearer "+access_token,
        'Content-Type': "application/json"
        }
    response = requests.request("POST", url, data=payload, headers=headers)
    if response.status_code == 202:
        resp = {
                    "txnid": response.json()["id"], 
                    "correlation": response.json()["correlation"],
                    'status_code': 200
                }
    else:
        resp = {
                'messages': "Nope.. that didnt work.",
                'status_code': 400        
        }
    return resp
def initiate_sms(method, target):
    access_token = auth()
    url = tentantid + "/v1.0/authnmethods/" + method + "/transient/verification"
    payload = "{\r\n  \"correlation\": \"1234\",\r\n  \"otpDeliveryMobileNumber\": \""+target+"\"\r\n}"
    headers = {
        'Authorization': "Bearer "+access_token,
        'Content-Type': "application/json"
        }
    response = requests.request("POST", url, data=payload, headers=headers)
    if response.status_code == 202:
        resp = {
                "txnid": response.json()["id"], 
                "correlation": response.json()["correlation"],
                'status_code': 200
        }
    else:
        resp = {
                'messages': "Nope.. that didnt work.",
                'status_code': 400
        }
    return resp
def accountlookup(userName):
    access_token = auth()
    url = tentantid + "/v2.0/Users?filter=userName eq \"" + userName + "\""
    payload = ""
    headers = {
        'Authorization': "Bearer "+access_token,
        }
    response = requests.request("GET", url, data=payload, headers=headers)
    print(response.text)
    if response.status_code == 200:
        if response.json()["totalResults"] != 0:
            resp={
                    'message': "I found your account.",
                    'user_email': response.json()["Resources"][0]["emails"][0]["value"],
                    'user_id': response.json()["Resources"][0]["id"], 
                    'cell_phone': response.json()["Resources"][0]["phoneNumbers"][0]["value"],
                    'status_code': 200
            }
        else:
            resp = {'messages': "I'm sorry, I can't find that account. Can you try again?",
                    'status_code': 400                    
            }
    else:
        resp = {'messages': "Oops... that didnt work.",
                'status_code': 400
        }
    return resp
def verify(txnid, method, otp):
    access_token = auth()
    url = tentantid + "/v1.0/authnmethods/" + method + "/transient/verification/" + txnid
    print("URL "+url)
    payload = "{\r\n  \"otp\": \"" + otp + "\"\r\n}"
    print(payload)
    headers = {
        'Authorization': "Bearer "+access_token,
        'Content-Type': "application/json"
        }
    response = requests.request("POST", url, data=payload, headers=headers)
    print(response.text)
    if response.status_code == 200:
        resp = {
                    "bbb_verified": "true",
                    'messages':"Perfect, the code was successful. We're good to go!",
                    'status_code': 200
                }
    else:
        resp = {'messages': "Nope.. that didnt work.",
                'status_code': 400}
    return resp
def pwreset(userid):
    access_token = auth()
    url = tentantid + "/v2.0/Users/" + userid + "/passwordResetter"
    print("URL "+url)
    payload = """{
        "schemas": [
            "urn:ietf:params:scim:api:messages:2.0:PatchOp"
        ],
        "operations": [
            {
                "op": "replace",
                "value": {
                    "password": "auto-generate",
                    "urn:ietf:params:scim:schemas:extension:ibm:2.0:Notification": {
                        "notifyType": "EMAIL",
                        "notifyPassword": true,
                        "notifyManager": false
                    }
                }
            }
        ]
    }"""
    headers = {
        'Authorization': "Bearer "+access_token,
        'Content-Type': "application/scim+json"
        }
    response = requests.request("PATCH", url, data=payload, headers=headers)
    print(response.text)
    if response.status_code == 204:
        resp = {
                    'messages': "Your password has been reset successfully. Please check your email for the new password.",
                    'status_code': 200    
                }
    else:
        resp = {
                    'messages': "The password reset operation failed. Please try again.",
                    'status_code': 400
                }
    return resp
  1. Go to Endpoint and get the URL. This url is needed in the next step.

Create Watson Assistant Configuration

  1. Start by Launching the Watson Assistant
  2. Navigate to the Watson Assistant Tool Page (specific to your account)
  3. Create a new assistant (or use “My first assistant”)
  4. Select “Add dialog skill”

  1. “Create skill”

  1. Select Options and enter the webhooks. This is where you need to past the url from the previous step, make sure to add .json at the end

  1. Within the dialog section, create the nodes and flows as needed.

  1. A node (Lookup Account) makes use of the Web Hook by passing an action and any required data:

  1. Once you have defined the flow, use preview to test:
361 366
  1. Return to your assistant main tab, and select “Add integrations”
452
  1. Select the embedded tab, and copy the html code for the next step.
967

IBM Security Verify Configuration

Embed the html code from previous step into any IBM Security Verify customized pages as needed. This can be done on the login page, error pages, forgot password, and more. For more guidance on branding, see the document on Branding and customization.

💎

Diana Jorgenson, IBM Security

Martin Schmidt, IBM Security