Skip to content

Commit

Permalink
Added only email verified
Browse files Browse the repository at this point in the history
  • Loading branch information
verschoren committed Feb 23, 2024
1 parent 6528706 commit 689bd24
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 123 deletions.
23 changes: 5 additions & 18 deletions docs/messaging.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,12 @@ <h2 class="text-xl font-medium text-blue-gray-900">User Info</h2>
</div>
</div>
<div class="flex justify-end gap-3">
<button onclick="Login('email')" id="login" type="button" class="relative inline-flex items-center gap-x-1.5 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10">
<button onclick="Login()" id="login" type="button" class="relative inline-flex items-center gap-x-1.5 rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10">
<svg class="-ml-0.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path d="M3 4a2 2 0 0 0-2 2v1.161l8.441 4.221a1.25 1.25 0 0 0 1.118 0L19 7.162V6a2 2 0 0 0-2-2H3Z" />
<path d="m19 8.839-7.77 3.885a2.75 2.75 0 0 1-2.46 0L1 8.839V14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8.839Z" />
</svg>
Login with verified email
</button>
<button type="button" onclick="Login('external_id')" id="login" class="relative -ml-px gap-x-1.5 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10">
<svg class="-ml-0.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M1 6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V6Zm4 1.5a2 2 0 1 1 4 0 2 2 0 0 1-4 0Zm2 3a4 4 0 0 0-3.665 2.395.75.75 0 0 0 .416 1A8.98 8.98 0 0 0 7 14.5a8.98 8.98 0 0 0 3.249-.604.75.75 0 0 0 .416-1.001A4.001 4.001 0 0 0 7 10.5Zm5-3.75a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Zm0 6.5a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Zm.75-4a.75.75 0 0 0 0 1.5h2.5a.75.75 0 0 0 0-1.5h-2.5Z" clip-rule="evenodd" />
</svg>
Login with external_id
Login
</button>
<button type="button" onclick="Logout()" id="logout" class="bg-red-100 py-2 px-4 border border-red-300 rounded-md shadow-sm text-sm font-medium text-red-900 hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500">Logout</button>
</div>
Expand Down Expand Up @@ -193,30 +187,23 @@ <h1 class="text-sm font-medium pb-2">Subscribe to Internal Note</h1>
$('#login_ok').hide();
}

function Login(type){
$('#external_id').val(btoa($('#email').val()));
function Login(){
var user = {
name: $('#name').val(),
email: $('#email').val(),
external_id: btoa($('#email').val())
}
$('#external_id').val(user.external_id);
console.log("User logged in", user);

//replace with your worker URLs
url = 'https://jwtauth.internalnote.com/messaging';
if (type == 'external_id'){
url = 'https://jwtauth.internalnote.com/messaging';
}
if (type == 'email'){
url = 'https://jwtauth.internalnote.com/messaging_email';
}

//get token for current user
var jwttoken = '';
$.ajax({
type: "POST",
url: url,
data: JSON.stringify({ "external_id": user.external_id, "user_email": user.email, "user_name": user.name }),
data: JSON.stringify({ "external_id": user.external_id, "email": user.email, "name": user.name }),
dataType: 'text',
async: false,
success: function (json) {
Expand Down
39 changes: 12 additions & 27 deletions messaging-worker/src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ export default {
case "/":
return Response.redirect('https://demo.internalnote.com', 302);
case "/messaging":
var response_messaging = await respondMessaging(json,env,"external_id");
response_messaging.headers.set("access-control-allow-origin", "*");
return response_messaging;
case "/messaging_email":
var response_messaging = await respondMessaging(json,env,"email");
var response_messaging = await respondMessaging(json,env);
response_messaging.headers.set("access-control-allow-origin", "*");
return response_messaging;
default :
Expand All @@ -29,10 +25,10 @@ export default {
}
};

async function respondMessaging(json,env,type) {
//{"external_id":"JB007","user_email":"james@universalexports.com","user_name":"James Bond"}
async function respondMessaging(json,env) {
//{"external_id":"JB007","email":"james@universalexports.com","name":"James Bond"}

if (!json.external_id || !json.user_email || !json.user_name) {
if (!json.external_id || !json.email || !json.name) {
return new Response("missing parameters", { status: 401 });
} else {
var app_id = env.MESSAGING_APP_ID;
Expand All @@ -48,25 +44,14 @@ async function respondMessaging(json,env,type) {

const header = JSON.stringify({ alg: "HS256", typ: "JWT", kid: app_id });

var payload;
if (type == "external_id") {
payload = JSON.stringify({
scope: "user",
name: json.user_name,
email: json.user_email,
external_id: json.external_id,
exp: Math.floor(new Date().getTime() / 1000.0) + 86400,
});
} else {
payload = JSON.stringify({
scope: "user",
name: json.user_name,
email: json.user_email,
exp: Math.floor(new Date().getTime() / 1000.0) + 86400,
external_id: "user_" + json.user_email,
email_verified: true
});
}
var payload = JSON.stringify({
scope: "user",
name: json.name,
email: json.email,
exp: Math.floor(new Date().getTime() / 1000.0) + 86400,
external_id: json.external_id,
email_verified: true
});

const partialToken = `${base64URLStringify(
utf8ToUint8Array(header)
Expand Down
79 changes: 1 addition & 78 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,82 +21,15 @@ Deployment can be done via this [GitHub Action](https://github.com/marketplace/a
**We do recommend including a check with your SSO tool of choice to validate the user before returning the token**

The script requires:
- Classic SDK Token
- Shared Secret (Chat and Widget
- Messaging App Secret and Token

We return
- Status 200 for POST to the /sdk endpoint with a valid payload for the Classic SDK
- Status 200 for POST to the /chat endpoint with a valid payload for the Chat SDK
- Status 200 for POST to the /guide endpoint with a valid payload for authenticating Guide in the Classic Widget
- Status 200 for POST to the /messaging endpoint with a valid payload in the Messaging SDK and Widget
- Status 401 for any error we find, which results in an unauthorized user in the SDK or Widget

## References
- [JWT Endpoint for Mobile SDK](https://develop.zendesk.com/hc/en-us/articles/360001075248-Building-a-dedicated-JWT-endpoint-for-the-Support-SDK)
- [Authenticated users in Chat SDK](https://develop.zendesk.com/hc/en-us/articles/360052354433-Enabling-authenticated-users-with-the-Chat-SDK-)
- [Authenticated Visitors in Widget](https://support.zendesk.com/hc/en-us/articles/360022185314-Enabling-authenticated-visitors-in-the-Chat-widget)
- [Authenticating Messaging Widget](https://developer.zendesk.com/documentation/zendesk-web-widget-sdks/sdks/web/sdk_api_reference/#authentication)

## SDK
The Zendesk Mobile SDK requires a JWT endpoint for authenticating its users.
It sends a payload to the endpoint. The payload contains a user identifier.

This can either be:
- the UUID of the user in the authentication service (which requires an extension of this script to retrieve the email and name of the user)
- an email adres of the user.

We use the latter in our script for simplicities sake.

{"user_token":"john@example.com"}

The endpoint is found at https://jwt.verschoren.com/sdk

It returns the following when handling a POST

### Status 201

{"jwt": "abc123def456...."}

which has a decoded structure of

{
"jti": random_string,
"iat": current_time_in_seconds,
"name": user_token,
"email": user_token
}

### Status 401
If the past token can't be found we send a status 401 which will be handled as unauthorized by the SDK

## Chat or Widget
The Zendesk Chat SDK and the Widget requires a JWT endpoint for authenticating its users.
It sends a payload to the endpoint. The payload contains email, name and an external_id
The external_id can be anything but is preferably the UUID of the user in the authentication service so we can extend the code to validate the user.

{"name":"John Appleseed","email":"john@example.com","external_id":"123456"}

The endpoint is found at https://jwt.verschoren.com/chat

It returns the following when handling a POST

### Status 201

{"jwt": "abc123def456...."}

which has a decoded structure of

{
"iat": current_time_in_seconds,
"name": name,
"email": email,
"external_id": external_id,
}

### Status 401
If the past token can't be found we send a status 401 which will be handled as unauthorized by the SDK

## Messaging
The Zendesk Messaging SDK and the Widget requires a JWT endpoint for authenticating its users.
It sends a payload to the endpoint. The payload contains email, name and an external_id
Expand Down Expand Up @@ -127,14 +60,4 @@ which has a decoded structure of
}

### Status 401
If the past token can't be found we send a status 401 which will be handled as unauthorized by the SDK


# Zendesk Widget Branding

![image](https://github.com/verschoren/zendesk_widget/assets/894026/9c178006-8383-4141-9e13-976bff806e84)
See this article on [Internal Note](https://github.com/verschoren/zendesk_widget_branding/blob/master/internalnote.com/ticket-sendmessage-for-support-apps)

![image](https://github.com/verschoren/zendesk_widget/assets/894026/78f933b5-2049-4b0a-bcd8-a759f4a29de3)

Demo on https://widget.internalnote.com/classiccustom.html
If the past token can't be found we send a status 401 which will be handled as unauthorized by the SDK

0 comments on commit 689bd24

Please sign in to comment.