Saving FB access token from FB JS SDK to DB - node.js

I am implementing 'Login with FB' for my web app using FB JS SDK. I have got the user to return the access token in the response inside the statusChangeCallback function. However, I am not sure about the best method to store this info to a DB for later use (getting data from graph api). How can the access token and other user info be saved into a DB?
In an attempt to post this data on an API, I have tried to serve this html using an express app but the facebook login popup shows blank where it should say "continue as such and such.."
Should there be a separate API that I should post this data to?
Any clue is appreciated!
<!DOCTYPE html>
<html>
<head>
<title>Facebook Login JavaScript Example</title>
<meta charset="UTF-8">
</head>
<body>
<script>
function statusChangeCallback(response) { // Called with the results from FB.getLoginStatus().
console.log('statusChangeCallback');
console.log(response); // The current login status of the person.
if (response.status === 'connected') { // Logged into your webpage and Facebook.
testAPI();
} else { // Not logged into your webpage or we are unable to tell.
document.getElementById('status').innerHTML = 'Please log ' +
'into this webpage.';
}
}
function checkLoginState() { // Called when a person is finished with the Login Button.
FB.getLoginStatus(function(response) { // See the onlogin handler
statusChangeCallback(response);
});
}
window.fbAsyncInit = function() {
FB.init({
appId : '{app-id}',
cookie : true, // Enable cookies to allow the server to access the session.
xfbml : true, // Parse social plugins on this webpage.
version : '{api-version}' // Use this Graph API version for this call.
});
FB.getLoginStatus(function(response) { // Called after the JS SDK has been initialized.
statusChangeCallback(response); // Returns the login status.
});
};
function testAPI() { // Testing Graph API after login. See statusChangeCallback() for when this call is made.
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Successful login for: ' + response.name);
document.getElementById('status').innerHTML =
'Thanks for logging in, ' + response.name + '!';
});
}
</script>
<!-- The JS SDK Login Button -->
<fb:login-button scope="public_profile,email" onlogin="checkLoginState();">
</fb:login-button>
<div id="status">
</div>
<!-- Load the JS SDK asynchronously -->
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js"></script>
</body>
</html>
This code is taken from facebook docs: https://developers.facebook.com/docs/facebook-login/web#example

Related

Redirect even if user uses back button (Node.js)

I have made a login system with jwt and, basically, the user redirects to the homepage (homepage/) if login (homepage/login) is successfull. After that, even if the user types (homepage/login) in the url, they get redirected back to the homepage because (and as long as) they have the jwt token.
I have the following code:
app.get('/login', (req, res) => {
const token = req.cookies.jwt
if(token) {
res.redirect('/')
} else {
res.render('login')
}
})
HOWEVER, if the user goes to (homepage/login) through the "back button", they are no longer redirected even though they have the token.
How can I include a redirect if the back button is pressed ?
Redirection is happening on client side.
So, simply include a frontend javascript code that checks if token is there. If not present, redirect.
In html code, include this script in head tag (assuming you are using localstorage to store token:
<html>
<head>
..
..
<script>
const token = localstorage.getItem("token");
if(token == null) {
window.location.replace("-path-to-home-page-");
}
</script>
</head>
<body>
..
..
..
</body>
</html>

No pem found for envelope: {"alg":"RS256","kid":"5a66482db3800c83c63","typ":"JWT"}

I'm trying to verify and decode id token sent by front-end.
I get this error when i run the verifyfunction.
Sometimes it might work.
No pem found for envelope: {"alg":"RS256","kid":"53c666482db3800c83c63","typ":"JWT"}
This is my code
const ticket = await client.verifyIdToken({
idToken: token,
audience: '804312674051-5o4.apps.googleusercontent.com',
});
const payload = ticket.getPayload();
I finally found the answer today.
The Firebase tool will connect the native Google to the third-party login token, and then encapsulate another layer. The token obtained at this time is no longer the original token given to us by Google.
A1:
Original Token: GoogleDesignInAccount Account = Task.getResult(ApiException.class);
Account.getidToken () // This is the original token
B1:
Firebase token: FireBaseUser currentUser = Mauth.getCurrentUser ();
String token = currentUser.getIdToken(false).getResult().getToken();
A2:
Google officially provides a method to verify the token
B2:
Firebase officially provides the authentication token method
We use code names for the four data points above. If you need to verify the validity of tokens in the background, they must correspond to each other, A1 to A2 and B1 to B2. If you use A2 to validate the B1, it will fail
I got the same problem....using a idToken that I got from my firebase login at my reactJS app.
I found that in the google src files
if (!certs.hasOwnProperty(envelope.kid)) {
// If this is not present, then there's no reason to attempt verification
throw new Error('No pem found for envelope: ' + JSON.stringify(envelope));
}
But I have no idea what that means.
The problem is the token used.
you can use this example for generate the token, only change the content="YOUR_CLIENT_ID.apps.googleusercontent.com" for a valid cliente id google
Test with the generated token in console.log
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
<title>Demo Sing-In</title>
</head>
<body>
<h1>Google Sing-In</h1>
<div class="g-signin2" data-onsuccess="onSignIn"></div>
Sign out
<script src="https://apis.google.com/js/platform.js" async defer></script>
<script>
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
var id_token = googleUser.getAuthResponse().id_token;
console.log(id_token);
}
function signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
</script>
</body>
</html>

amazon pay error client_Id undefined

I am integrating the amazon pay API in my asp.net code. I have write the following code
<!-- language: lang-js -->
<script type='text/javascript'>
window.onAmazonLoginReady = function () {
amazon.Login.setClientId('<%=ConfigurationManager.AppSettings["lwa_client_id"]%>');
amazon.Login.setUseCookie(true);
};
</script>
<script async type='text/javascript' src='https://static-na.payments-amazon.com/OffAmazonPayments/us/sandbox/js/Widgets.js'></script>
<script type='text/javascript'>
OffAmazonPayments.Button("AmazonPayButton", '<%=ConfigurationManager.AppSettings["merchant_id"]%>', {
type: "PwA",
authorization: function () {
debugger;
loginOptions = { scope: "profile postal_code payments:widget payments:shipping_address", popup: true };
amazon.Login.authorize(loginOptions, "/AmazonProcessing");
},
onError: function (error) {
// something bad happened
}
});
</script>
It render the Amazon Pay button. But when I click on it, It will show the popup with error of 404.
It was working before. I do not change any setting on the Amazon. I have checked the JavaScript Cross origin. I have added the localhost with port.
How to resolve this issue?
The value for client ID is probably not populated correctly from your application settings (error "Unknown client_id" and in the error summary "client_id=undefined").
You should be able to set a breakpoint in the JavaScript on the line with "setClientId" to verify whether the client ID has a value or not.

PubNub keeps receiving one message over and over

Just started with PubNub, and seems that I fail to understand even the simplest possible scenario. I created the following test page:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.15.1.js"></script>
<script>
const pubnub = new PubNub({
publishKey : '<guid>',
subscribeKey : '<one more guid>'
});
pubnub.subscribe({channels: ['3']});
pubnub.addListener({
message: v => {
console.log("on message", v);
},
});
function onClick() {
pubnub.publish({channel: '3', message: 'foo'});
}
</script>
</head>
<body>
<button onclick="onClick()">start</button>
</body>
</html>
Opening it with latest Chrome and clicking "start" button will result in test message being received endlessly over and over. I was under impression that after single client receives a message from a bus, this client will not receive it again. why such behaviour? I understand that I can read all the docs and most probably answer is somewhere deep inside, but tutorial + quickstart gives no clues, and rest of docs are quite huge.
Your example code works perfectly for me. The message published is received one time on the channel "3". One way to validate this is to simultaneously have the PubNub Console open (https://www.pubnub.com/docs/console). Make sure you enter your Publish and Subscribe keys into the console, along with the channel "3". After clicking the "Subscribe" button in the PubNub Console, you should see your test message "foo" appearing once in the "messages" section at the bottom each time you click the "start" button on your test page.
I can see that you're using the latest SDK-JS V4 (perfect starting point)
Your code works!
I would like to point you to a bit of a diff way to init PubNub and few functionalities.
(which are available in their docs)
Please look at the attached link to view my PubNub demo
<script type="text/javascript">
console.log('init PubNub.');
pubnub = new PubNub({
publishKey: 'demo',
subscribeKey: 'demo',
uuid: 'myDemo'
})
console.log("addListener..");
pubnub.addListener({
status: function(statusEvent) {
if (statusEvent.category === "PNConnectedCategory") {
console.log("PNConnectedCategory..");
publishSampleMessage();
}
},
message: function(message) {
console.log("New Message!!", message.message);
},
presence: function(presenceEvent) {
//handle presence
}
})
console.log("Subscribing..");
pubnub.subscribe({
channels: ['myDemo']
});
function publishSampleMessage() {
console.log("Since we're publishing on subscribe connectEvent, we're sure we'll receive the following publish.");
var publishConfig = {
channel: "myDemo",
message: "I'm here, I'm alive!!"
}
pubnub.publish(publishConfig, function(status, response) {
console.log(status, response);
})
}
function onClick() {
publishSampleMessage();
}
</script>

Can't get token when log in with Azure Active Directory using msal.js

I have problem with get token when log in with Azure Active Directory using msal.js.
Maybe I'll describe you how the app works in several situations.
I. Automatic login with Active Directory Authentication is disabled. Callback on Application Registration Portal is set to home page of the app. I used the code from https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/devApps/VanillaJSTestApp/index_LoginPopup.html
Enter the app without authorization
Click on button which runs loginPopup, after log in get token.
Everything works, but I want authorization with Active Directory Authentication
II. Automatic login with Active Directory Authentication is enabled. Callback on Application Registration Portal is set to "***.auth/login/aad/callback". I used the code from https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/devApps/VanillaJSTestApp/index_LoginPopup.html
Enter the app with authorization and log in with Active Directory Authentication
acquireTokenSilent is sending error like "user_login_error:User login is required".
Click on button which runs loginPopup, after log in I get error like "The reply address **** does not match the reply addresses configured for the application"
UPDATE: After set userAgentApplication.redirectUri = '****/.auth/login/aad/callback' and run loginPopup, token is delivered, but it's still double log in.
To summarize, after login with Azure I get error from acquireTokenSilent "user_login_error:User login is required".
III. I would like the app to behave as follows:
Enter the app with authorization and log in with Active Directory Authentication
Get token
Can I do it like this?
You were mixing the Easy Auth and protecting the site manually using MSAL.
If you want the popup page for login with Azure Active Directory popup automatically, you can modify the source to add the function to execute the loginPopup() method when the document is loaded completely. Here is an code sample for your reference:
<html>
<head>
<title>authentication with Msal.js app</title>
<style>
.hidden {
visibility: hidden
}
.visible {
visibility: visible
}
</style>
</head>
<body>
<!-- bluebird only needed if this page needs to run on Internet Explorer -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js" class="pre"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/0.1.1/js/msal.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js" class="pre"></script>
<h1>Sending an email with msal.js and Microsoft Graph</h1>
<div>
<div id="label">Sign-in with Microsoft</div>
<button id="auth" onclick="loginPopup();">Login (with Popup)</button>
</div>
<div id="sendEmail" class="hidden">
<input id="emailToSendTo" type="text" />
<button id="auth" onclick="sendEmail();">Send email</button>
</div>
<pre class="response"></pre>
<script class="pre">
var applicationConfig = {
clientID: '1e6af2ed-686c-4914-96ed-0cd7b1673cbb',
graphEndpoint: "https://graph.microsoft.com/v1.0/me/sendMail",
graphScopes: ["user.read", "mail.send"]
};
</script>
<script>
var userAgentApplication = new Msal.UserAgentApplication(applicationConfig.clientID, applicationConfig.authority, authCallback);
function authCallback(errorDesc, token, error, tokenType) {
//This function is called after loginRedirect. msal object is bound to the window object after the constructor is called.
if (token) {
}
else {
log(error + ":" + errorDesc);
}
}
function loginPopup() {
userAgentApplication.loginPopup(applicationConfig.graphScopes).then(function (idToken) {
//Login Success
userAgentApplication.acquireTokenSilent(applicationConfig.graphScopes).then(function (accessToken) {
//AcquireToken Success
updateUI();
}, function (error) {
//AcquireToken Failure, send an interactive request.
userAgentApplication.acquireTokenPopup(applicationConfig.graphScopes).then(function (accessToken) {
updateUI();
}, function (error) {
console.log(error);
});
})
}, function (error) {
console.log(error);
});
}
function updateUI() {
var authButton = document.getElementById('auth');
authButton.innerHTML = 'logout';
authButton.setAttribute('onclick', 'logout();');
var label = document.getElementById('label');
label.innerText = "Hello " + userAgentApplication.getUser().name + "! Please send an email with Microsoft Graph";
// Show the email address part
var sendEmailSpan = document.getElementById('sendEmail');
sendEmailSpan.className = "visible";
var emailAddress = document.getElementById('emailToSendTo');
emailAddress.value = userAgentApplication.getUser().displayableId;
}
function logout() {
// Removes all sessions, need to call AAD endpoint to do full logout
userAgentApplication.logout();
}
function sendEmail() {
userAgentApplication.acquireTokenSilent(applicationConfig.graphScopes)
.then(function (token, error) {
$.ajax({
type: "POST",
contentType: "application/json",
dataType: 'json',
beforeSend: function (request) {
request.setRequestHeader('Authorization', 'bearer ' + token);
},
url: applicationConfig.graphEndpoint,
data: JSON.stringify({ 'message': getEmail(), 'saveToSentItems': true }),
processData: false,
success: function (msg) {
log('Mail sucessfully sent.');
},
statusCode: {
200: function () {
log('Mail sucessfully sent.');
},
202: function () {
log('Mail sucessfully sent.');
}
}
});
});
}
function log(s) {
document.body.querySelector('.response').appendChild(document.createTextNode("\n\n" + JSON.stringify(s, true, 2)));
}
function getEmail() {
var email = {
Subject: 'Welcome to Microsoft Graph development with Msal and the Microsoft Graph sample',
Body: {
ContentType: 'HTML',
Content: getEmailContent()
},
ToRecipients: [
{
EmailAddress: {
Address: userAgentApplication.getUser().displayableId
}
}
]
};
return email;
}
// Get the HTMl for the email to send.
function getEmailContent() {
return "<html><head> <meta http-equiv=\'Content-Type\' content=\'text/html; charset=us-ascii\'> <title></title> </head><body style=\'font-family:calibri\'> <p>Congratulations " + userAgentApplication.getUser().name + ",</p> <p>This is a message from the Microsoft Graph Connect sample. You are well on your way to incorporating Microsoft Graph endpoints in your apps. </p> <h3>What’s next?</h3><ul><li>Check out <a href='https://graph.microsoft.io' target='_blank'>graph.microsoft.io</a> to start building Microsoft Graph apps today with all the latest tools, templates, and guidance to get started quickly.</li><li>Use the <a href='https://graph.microsoft.io/graph-explorer' target='_blank'>Graph explorer</a> to explore the rest of the APIs and start your testing.</li><li>Browse other <a href='https://github.com/microsoftgraph/' target='_blank'>samples on GitHub</a> to see more of the APIs in action.</li></ul> <h3>Give us feedback</h3> <ul><li>If you have any trouble running this sample, please <a href='https://github.com/microsoftgraph/angular-connect-rest-sample/issues' target='_blank'>log an issue</a>.</li><li>For general questions about the Microsoft Graph API, post to <a href='https://stackoverflow.com/questions/tagged/microsoftgraph?sort=newest' target='blank'>Stack Overflow</a>. Make sure that your questions or comments are tagged with [microsoftgraph].</li></ul><p>Thanks and happy coding!<br>Your Microsoft Graph samples development team</p> <div style=\'text-align:center; font-family:calibri\'> <table style=\'width:100%; font-family:calibri\'> <tbody> <tr> <td><a href=\'https://github.com/microsoftgraph/angular-connect-rest-sample\'>See on GitHub</a> </td> <td><a href=\'https://officespdev.uservoice.com/\'>Suggest on UserVoice</a> </td> <td><a href=\'https://twitter.com/share?text=I%20just%20started%20developing%20%23Angular%20apps%20using%20the%20%23MicrosoftGraph%20Connect%20sample!%20&url=https://github.com/microsoftgraph/angular-connect-rest-sample\'>Share on Twitter</a> </td> </tr> </tbody> </table> </div> </body> </html>";
};
$(document).ready(function () {
loginPopup();
});
</script>
</body>
</html>
If you want to authenticate the user by the client using msal.js and also protect your Web API, then disable the 'App Service Authentication' in Azure. Protect your Web API using OWIN middleware instead.
This following sample shows a Web API protected by Azure AD Endpoint V2 using msal.js: https://github.com/Azure-Samples/active-directory-javascript-singlepageapp-dotnet-webapi-v2

Resources