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.
Related
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
I have an excel file in a directory on my nodejs server - Path to the file is - ./api/uploads/appsecuritydesign/output/appsecdesign.xlsx
On click of a button in my Angular 5 component I am just trying to download the file using FileSaver.
Below is my Angular component.
Here the template code for the button in Angular that will call the saveFile() function once clicked.
<a class="btn btn-primary" (click) = "saveFile()">Download</a>
Here is the saveFile() function.
saveFile(){
console.log("In ToolInput Component: ", this.token); //Okta token
console.log("In ToolInput Component: ", this.whatamidoing); //this variable has the server FilePath
this.fileService.getappsecdesignfile(this.token, this.whatamidoing).subscribe(res => {
let blobtool5 = new Blob([res], { type: 'application/vnd.ms-excel;charset=utf-8' });
FileSaver.saveAs(blobtool5, 'Application_Security_Design.xlsx');
},
(err: HttpErrorResponse) => {
if (err.error instanceof Error) {
console.log('An error occurred:', err.error.message);
console.log('Status', err.status);
} else {
console.log(`Backend returned code ${err.status}, body was: ${err.error}`);
console.log('Status', err.status);
}
});
}
At this point I checked the console.log in the browser. They are exactly what they are supposed to be. So I am passing the correct filepath and token to getappsecdesignfile method in my fileService.
Now Lets take a look at the getappsecdesignfile method in my fileService.
getappsecdesignfile ( token, tool5filepath ) : Observable<any>{
console.log("In Service tool5filepath: ", tool5filepath);
console.log("In Service token", token);
console.log("In Service GET url: ", this.getappsecdesignfileurl);
//Since the tool5filepath has / (slashes etc) I am encoding it below.
let encodedtool5filepath = encodeURIComponent(tool5filepath);
console.log('Encoded File Path: ', encodedtool5filepath);
let req = new HttpRequest('GET', this.getappsecdesignfileurl,{params: new HttpParams().set('path', encodedtool5filepath)},{headers: new HttpHeaders().set('Accept', 'application/vnd.ms-excel').set('Authorization', token)});
console.log(req);
return this.http.request(req);
}
That's all there is to the fileService method. Lets look at the console.logs from this method from the browser to ensure all the correct values are being set.
Now Lets take a look at the request itself before we go to the server part.
As far as I am concerned the headers are set correctly, params are set correctly. Two issues I see is that Angular's interceptors probably sets the responseType: json and adds a param op:s to my request.
Node/Express Server code.
app.get('/getappsecdesignfile', function(req, res){
console.log("In get method app security design");
accessTokenString = req.headers.authorization;
console.log("Okta Auth Token:", accessTokenString);
console.log("Tool5 File Path from received from Angular: ", req.query.path); //this is where the server console logs shows Tool5 File Path after decoding: ./undefined
oktaJwtVerifier.verifyAccessToken(accessTokenString)
.then(jwt => {
// the token is valid
console.log(jwt.claims);
res.setHeader('Content-Disposition', 'attachment; filename= + Application_Security_Design.xlsx');
res.setHeader('Content-Type', 'application/vnd.ms-excel');
let tool5filepath = './' + decodeURIComponent(req.query.path);
console.log("Tool5 File Path after decoding: ", tool5filepath);
res.download(tool5filepath);
}).catch(err => {
// a validation failed, inspect the error
res.json({success : false, message : 'Authorization error.'});
});
});
If I use Postman the api works fine. However somewhere between Angular to Node communication something happens that I don't understand.
Below is what the server logs. (Big question how does this become undefined)?
Tool5 File Path from received from Angular: undefined
Tool5 File Path after decoding: ./undefined
Error: ENOENT: no such file or directory, stat '<dirpath>/undefined'
Here is what I see in the browser log:
zone.js:2933 GET http://localhost:3000/getappsecdesignfile 404 (Not Found)
toolinput.component.ts:137 Backend returned code 404, body was: <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Error: ENOENT: no such file or directory, stat '<dirpath>/undefined'</pre>
</body>
</html>
Then the browser downloads a xlsx file that is corrupt and cannot be opened.
I have checked the file resides in the directory and is ready to be downloaded.
Thanks for any tips that can help me resolve this issue.
Finally figured it out.
2 specific changes made this work.
Change # 1 - Setting responseType : 'blob' and defining the params and headers first and then using them in http.get. (http is nothing but an object of type HttpClient from angular/common/http that has been injected into the service class.
getappsecdesignfile ( token, tool5filepath ) : Observable<any>{
console.log("In Service tool5filepath: ", tool5filepath);
console.log("In Service token", token);
console.log("In Service GET url: ", this.getappsecdesignfileurl);
let encodedtool5filepath = encodeURIComponent(tool5filepath);
console.log('Encoded File Path: ', encodedtool5filepath);
let getfileparams = new HttpParams().set('filepath', encodedtool5filepath);
let getfileheaders = new HttpHeaders().set('Accept', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet').set('Authorization', token);
return this.http.get(this.getappsecdesignfileurl, {responseType: 'blob', params: getfileparams, headers: getfileheaders});
}
Change # 2 - Component code - FileSaver. For some reason type: 'application/vnd.ms-excel' did not work in FileSaver. Here the res is nothing but the response from the http.get call.
let blobtool5 = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
FileSaver.saveAs(blobtool5, 'Application_Security_Design.xlsx');
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>
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
The problem is, as soon as pjaxed request finishes, pjax also initiates a normal GET request.
My codes are like this:
$(document).on('pjax:end', function(event){
alert("end");
inpjax = false;
});
$(document).on('pjax:timeout', function(event) {
alert("timeout")
event.preventDefault();
});
$(document).on('pjax:error', function() {
alert("error");
});
$(document).on('pjax:success', function() {
alert("success");
});
$(document).ready(function(e) {
inpjax = false;
$('.pj').click( function(e) {
e.preventDefault();
if(!inpjax)
{
inpjax = true;
$.pjax({
timeout: 5000,
url: $(this).attr('href'),
container: '#codeport'
});
}
});
});
As you can see, it should give me an alert on different stiuations, but I only get alert on pjax:end event, and after that alert, pjax initiates normal GET request, timing is like this:
[17:36:02.002] GET http://localhost/abstract?_pjax=%23codeport [HTTP/1.1 200 OK 86 ms]
[17:36:02.170] GET http://localhost/abstract [HTTP/1.1 200 OK 73 ms]
I don't get timeout, error or success alert.
What could be causing this? Please help...
SOLUTION:
The problem turned out to be that my serverside code was responding with a full page, and that was causing a second GET request. So if this problem happens to you too, make sure that your server side code responds correctly to PJAX requests.
example:
<!DOCTYPE html>
<html>
<head>
<!-- styles, scripts, etc -->
</head>
<body>
<h1>My Site</h1>
<div class="container" id="pjax-container">
Download content from the other site ?.
</div>
</body>
</html>
Try to add pjax to an element which you want to get event messages from like $(document).pjax('a', '#pjax-container')