Sending a message from parent page to AWS Lex Bot - aws-lambda

I'm trying to restrict my Lex Bot to only show results of a SQL Search that a certain User has access to. For example, if User A only has access to records that belong to User A, the Bot will not allow User A to search for records that belong to User B.
Right now, I've got my Bot set up on a website that I've hosted via AWS S3. The issue I'm facing right now is getting my user's login information from the parent page (the website I've set up in S3) and sending it to my Lex Bot (which I've embedded as an Iframe).
The login to the page is done via Google Login which saves an Access Token in my SQL Database. I'd like to know how I can send this access token to my Lex Bot so I can authenticate it via Lambda. (I've already got the Lambda portion done, just need to know how to get the message from the parent page. Ideally, this part happens before the User talks to the Bot, which means a postback message so the user cannot see this information)
Things I've tried:
- I've tried doing a separate lambda function to handle this part only but don't really know how to integrate it into the website.
- I've tried using event listeners but am not very sure if the message goes to the bot or just the IFrame.
Right now, I'm out of ideas and any help would be greatly appreciated.

I managed to finally do it by adding a Javascript function to post a message. It doesn't look very professional but it works.
function isBotMinimized() {
return $('.' + lexWebUi.options.containerClass)
.hasClass('lex-web-ui--minimize');
}
function sendMessage() {
return Promise.resolve()
.then(function () {
return !isBotMinimized() ||
lexWebUi.sendMessageToIframe({ event: 'toggleMinimizeUi' });
})
.then(function () {
return lexWebUi.sendMessageToIframe({ event: 'postText', message: "Welcome"});
})
.then(function () { console.log('message succesfully sent'); })
.catch(function (error) { console.error('error sending message ', error); });
}

Related

Problem with Sign-in to Nativescript app with google provider

I try to use google provider to log in to my angular nativescript app. My web app works properly, for mobile added SHA-1 to firebase console.
I have two problems:
After try to log in with google provider firebaseWebApi.auth().onAuthStateChanged not fired (login function returns User properly).
When Sign-in with google provider is not possible I try to simply log in with firebaseWebApi.auth().signInWithEmailAndPassword(), but I have an error message: "Logging in the user failed. com.google.firebase.auth.FirebaseAuthRecentLoginRequiredException: This operation is sensitive and requires recent authentication. Log in again before retrying this request."
It's weird because without trying to log in with google provider, signInWithEmailAndPassword works properly.
public async startLoginGoogle(): Promise<firebase.auth.UserCredential> {
const user = await firebase.login({
type: firebase.LoginType.GOOGLE
});
// user with getIdTokenResult() is available here
return user.getIdTokenResult();
}
firebaseWebApi.auth().onAuthStateChanged((user: firebase.User) => {
// nothing
subject.next(user);
});
Any idea?

Azure Bot - Directline token generation from html page hiding secret

I was trying to do some work around with azure bot service using Direct Line Channel from html page.
Script within html page is as follows:
index.html
var directLine = new window.WebChat.createDirectLine({ secret: 'SECRET' });
directLine.postActivity({
from: { id: 'myUserId', name: 'myUserName' }, // required (from.name is optional)
type: 'message',
text: 'hi'
}).subscribe(
id => console.log("Posted activity, assigned ID ", id),
error => console.log("Error posting activity", error)
);
directLine.activity$
.filter(activity => activity.type === 'message')
.subscribe(
message => console.log("received message ", message)
);
I found API "https://directline.botframework.com/v3/directline/tokens/generate" where secret can be exchanged with token but SECRET has to be added in Authorization header.
Is there a way to hide SECRET in html page without using MVC architecture? Or any other method to interact without exposing SECRET key.
No, there is no way to hide the secret. If it's in the web page, then it is accessible to anyone who inspects the source.
You don't necessarily have to opt for an MVC setup, however. All you need to do is create a service with APIs you can then access.
If you look over the latter half of this solution I previously provided, I demonstrate a simple setup that I run locally for development purposes. From the page hosting the Web Chat instance, I make a call to my custom /directline/token endpoint. The service, appended to my bot's index.js file gets a token and returns it back for use in Web Chat.
In production, I put the "token server" in its own file, and deploy it with the web app. It runs in the background on the server remaining inaccessible (as a file) but accessible via the APIs. Just lock down the API resources and you should be good to go.

Google Calendar Unable to Update Events

I had my Google calendar application almost working, I am still able to list all the events on the Primary Calendar and I can edit on Google and see the updated results on my calendar.
The problem is that my:
var eventToUpdate = gapi.client.calendar.events.get({
is getting an error 404.
From what I've been reading people who have had this issue previously were sending the wrong Key or wrong Event ID. But I've tested the values using
https://developers.google.com/calendar/v3/reference/events/update
& I get a success 200 back from Google.
Here is my event drop:
eventDrop: function( eventDropInfo ) {
gapi.auth.setToken('<?php echo $google_auth['access_token']; ?>');
handleAuthClick;
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
}, function(error) {
appendPre(JSON.stringify(error, null, 2));
});
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
var eventToUpdate = gapi.client.calendar.events.get({
"calendarId": 'primary',
"eventId": eventDropInfo.id
});
There's more but that's the main Google APIs part.
I thought it could be the Key, however the Key works to grab the calendar information and is able to be used for my other Google stuff. (Drive, Login etc.)
I thought maybee it was the wrong calendar ID but using the Google "Try This API" It seems the Calendar ID + Event ID is perfect as Google gives me success.
Below you can see the console error, apologies if I've missed off anything important.
Thank You!
Error 404 From Console
--- Updated with more info
This shows Google References accepting the event ID and updating the event
This is the data I've entered to get the 200 success above
This is the URL showing the JSON google print out
Just to note, I've checked the scopes and the 2 I am using are:
var SCOPES = "https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events";
The only others I can find are Read Only so I doubt it's the scopes.
Also the code seems to work as the only error I see is Google giving a 404, the loading of the events and calendar work it's just update that gives the 404.
As you can see through the screenshots I've updated the event ID i'm using to test is the same in my code as in the References test.
This is now working.
The problem was with my script not setting the OAuth Token correctly. It was saving the full JSON string instead of just the token.
After amending the login and getting the correct OAuth it works as it should :)
Thanks for the help!

How to check if user is still logged in google?

I am using Google OAuth through Laravel Socialite to authenticate all the users in my web app.
I need the user session to end as soon as possible if user logs out of his google account.
I am trying to set up a middleware that would perform regular checks if user is still signed in with google. But I can't find a way to ask "Is user#example.com still the current user on google?"
I tried to get \Socialite::driver('google')->user() in the middleware but that doesn't seem to work without doing a redirect to google beforehand. I would like this check to be as quick and unobtrusive as possible. It should also work during a background ajax call.
It seems that it would be trivial using the client side authentication as there is gapi.auth2.init().isSignedIn.get(). However, that would mean I have to ask users for two authorizations (server side and client side) which seems wrong.
Looking at the docs at google, I see nothing that would let me check their authentication status apart from reauthenticating. Access token won't expire on logout... Is there a workaround?
It turns out that we can actually use gapi javascript in tandem with Socialite - just use the same client token. I didn't suspect that I will just get all the info without logging in separately for browser session, but it works.
I added the following code to the end of my master blade template to check state for authorized users.
#auth
<script>
var currentUserEmail = '{{Auth::user()->email}}'; // user "sameness" criterion
var googleClientId = '{{env('GOOGLE_ID')}}'; // the same oauth client id
</script>
<script src="https://apis.google.com/js/platform.js"></script>
<script src="{{mix('js/checkGoogleAuth.js')}}"></script>
#endauth
The script checkGoogleAuth is a simple then, I copied the google tutorial and shortened it:
var auth2; // The Sign-In object.
var googleUser; // The current user.
/**
* Initializes Signin v2 and sets up listeners.
*/
var initSigninV2 = function() {
auth2 = gapi.auth2.init({
client_id: googleClientId,
scope: 'profile'
});
// Listen for sign-in state changes.
auth2.isSignedIn.listen(checkState);
auth2.currentUser.listen(checkState);
};
var checkState = function (user) {
//if signed out or changed user
if (!auth2.isSignedIn.get() || currentUserEmail != auth2.currentUser.get().getBasicProfile().getEmail())
$('.logout-username').click(); //click logout button
};
gapi.load('auth2', initSigninV2); //launch it
I hope it helps someone else as well!

Where does request.user come from in Parse Server

I'm trying to port my Parse.com app to Parse server.
According to the Parse migration guide, Parse.User.current() can no longer be used and instead you should fetch the current user via 'request.user'.
However, request.user is always undefined for me.
For example, when I successfully login a user and then redirect to another path (/mypath), the incoming request at mypath does not contain a user object.
Parse.User.logIn(username, password, {
success: function(user) {
res.redirect('/mypath');
}
})
// Index of the /mypath controller
exports.index = function(request, response) {
// request.user is undefined here
}
How do I work with the active user after I logged in sucessfully?
I think I figured it out.
When working in Cloud Code there is no magic request.user. Rather when logging in you need to manually store the user info in the current session. In the Parse.com days this would've been managed by the parse-express-cookie-session middleware. This is explained in the cloud code guide. With Parse-Server you can insert your own middleware to manage the user as is described here.
However, the request.user will be available when receiving requests from a client SDK using an authenticated user.

Resources