How to make REST call to MS Graph/OneDrive method with OAuth2 - rest

I am trying to use the OneDrive API and I have successfully registered my app through their Application Registration Portal. I can call successfully call the Javascript FilePicker SDK to upload and download files
That demonstrates that I have my app registered properly and the proper app/client-id's.
Now I'd like to use the REST services to upload and download files but I'm not sure how to send authentication and I don't know how to make the call to the proper URL.
My first question is: How can I use the token I created in the reg service to make a REST call?
My second question is: What syntax should I use to upload a file? I don't know where to put the URL to make the call.
The PUT documentation for their upload is found here
<script type="text/javascript">
function launchSaveToOneDrive(){
var xhttp = new XMLHttpRequest();
//Authorization: bearer {token}
xhttp.open("PUT", "/drive/items/{parent-id}:/{filename}:/content", false);
xmlhttp.setRequestHeader("Authorization", "Bearer-xxxxxxxxxxxxxxxxxxx");
xhttp.setRequestHeader("Content-type", "text/plain");
xhttp.send();
var response = JSON.parse(xhttp.responseText);
}
</script>

One option is to use the Microsoft Graph JavaScript SDK that can help with REST calls including uploading files to OneDrive through the MS Graph. The library works with client side JavaScript and Node for JavaScript server apps.
Check the Browser folder under samples to see how to use the SDK in a client app. Uploading a file would look something like this (see that link for the full code):
// file variable is from the contents of an input field for example
var file = document.querySelector('input[type=file]').files[0];
// after user selects a file from the file picker
client
.api('/me/drive/root/children/Book.xlsx/content')
.put(file, (error, response) => {
// supports callbacks and promises
});

Related

Redirect URL using Firebase Dynamic / Deep Links is losing query parameters

In my Flutter (Android/iOS) app I am using Firebase Dynamic Links for Patreon.com OAuth2 apis.
My dynamic link is https://myappname.page.link/patreon
The deep link is https://myappname.net/patreon
Patreon is using the https://myappname.page.link/patreon as a redirect_url , and is supposed to append some parameters to it, so it looks like
https://myappname.net/patreon?code=xxx
However, all I receive inside my app is the naked url https://myappname.net/patreon
There are no parameters attached to it.
So how can I tell Firebase to preserve the query parameters Patreon is attaching to the redirect_url?
As an alternate question, is there a better way to listen for incoming response inside of a Flutter app, without the use of Dynamic Links?
You loose all parameters by using that.
If you're relying on Patreon to send back that parameter I'd suggest to generate a small proxy where you can redirect your calls to the dynamic link by generating it on the fly.
So:
Patreon shares www.myhost.com/supah-link?p1=aaa&p2=bbb
Your micro-service which runs on www.myhost.com/supah-link receives the call
You generate a dynamic link like the following:
https://example.page.link/?link=https://www.example.com/someresource&apn=com.example.android&amv=3&ibi=com.example.ios&isi=1234567&ius=exampleapp&p1=aaa&p2=bbb
NOTE: Pay attention to the &p1=aaa&p2=bbb parameters added
Return a 302 and redirect to your newly generated link
Based on how you configure it from the console this link can redirect to the store or your app, in your app you can listen for the link as follows:
FirebaseDynamicLinks.instance.onLink(
onSuccess: (dynamicLink) async => handleDeepLink(dynamicLink?.link),
);
In handleDeepLink you can parse your custom query parameters.
NOTE: The URL parameter you pass via the dynamic link HAS TO BE ENCODED! Which means your link will look more like this:
https://example.page.link/?link=https%3A%2F%2Fwww.example.com%2Fsomeresource%26apn%3Dcom.example.android%26amv%3D3%26ibi%3Dcom.example.ios%26isi%3D1234567%26ius%3Dexampleapp%26p1%3Daaa%26p2%3Dbbb

SharePoint Online: Redirect URIs for multi-site environment

We have a multi-site environment where each site has its own redirect URL. We want to use a single Client ID and Secret for our application but register multiple redirect URIs to it. Is it possible to add multiple URLs in below registration form:
I don't think there is possible solution to add on multiple URLs on the SharePoint online app registration form.
But from what i understand there is another way to achieve use a single Client ID and Secret for application and perform multiple redirects.
You can control the redirect url using the appredirect.aspx by specifying the redirect_uri parameter if you need to redirect from the default one check here for reference.
Basiclly it call the subsite page containing the below JS to install the app.
var url = String.format(
"{0}/_layouts/15/appredirect.aspx?client_id={1}&redirect_uri=https://***.azurewebsites.net/<<controller>>/<<view method containing the code to install the app>>?{{StandardTokens}}",
<<subsite url>>, "<<client id>>");
window.location.href = url;
The above javascript calls the appredirect.aspx page which then calls the app site as below,
https://****.azurewebsites.net/home?SPHostUrl=<<subsiteurl>>&SPLanguage=en-US&SPClientTag=1&SPProductNumber=**&SPAppWebUrl=<<weburl>>
Note: The above can be extended to check for the successful installation of the app and display an error message accordingly.
SPWeb.LoadAndInstallWeb equivalent REST / Javascript CSOM is also available here.
Here are some relevant links:
Use the redirect URL in an add-in that asks for permissions on the fly
Redirect URIs and a sample redirect page

Customizing "PayPal" button for PayPal Marketplace (API)

I am developing my app with PayPal Marketplace API for the first time.
Among other steps, I need to customize a "PayPal checkout" button. I did this by following instructions on this page.
In function "payment" (see the original code segment below), I supposed to provide a call-back url for CREATE_URL:
// payment() is called when the button is clicked
payment: function() {
// Set up a url on your server to create the payment
var CREATE_URL = '/demo/checkout/api/paypal/order/create/';
// Make a call to your server to set up the payment
return paypal.request.post(CREATE_URL)
.then(function(res) {
return res.id;
});
}
By reading this, I am puzzled why the CREATE_URL value is not a fullpath url starting with "http" or "https"? I have the similar question for EXECUTE_URL in an ensuing segment of the html file.
What type of RequestBody should my REST controller expect?
What action should my app take at the url for "CREATE_URL"? My intuition is to call the Order API to create an order (among other things in my database). Is this correct?
I can address your questions one at a time:
By reading this, I am puzzled why the CREATE_URL value is not a fullpath url starting with "http" or "https"? I have the similar question for EXECUTE_URL in an ensuing segment of the html file.
You don't have to have a full path URL (known as absolute path) because the path that you provide for CREATE_URL is on your own server. So the code where you have your button is on a page like exampleButton.html and when you click the button, it takes you to a script, such as
var CREATE_URL = '/demo/checkout/api/paypal/order/create/';
which is an index page which will run the Create Order API method with the data that you pass. Here is another example implementing a payment button with checkout.js using a server side language.
What type of RequestBody should my REST controller expect?
Your request body will receive the payment data from the JavaScript data parameter, which should be JSON format. You then pass this to the server side when you receive the POST data.
An even simpler implementation is to use the client-side integration to create the order.
What action should my app take at the url for "CREATE_URL"? My intuition is to call the Order API to create an order (among other things in my database). Is this correct?
Your app should automatically run the create order method. This script works with JavaScript promises, so will wait for a response, like getting a successful authorization (or failure) from the customer before attempting to execute the payment.

Download file from webservice

I want to download file on clik of image. We have rest api which download the zip file when called. I am.able to get desired output when call that api from browser and rest console. However when I try to call it from ajax call it gives cross domain origine present method not allowed error.
Any help will be appreciated.
It seems like you overcomplicated it. If you can test your API from your browser, I assume it's a simple HTTP GET call so you don't need fancy stuff like Ajax: just open the link, your browser know how to download a file.
Opening in the same window: location.href = 'http://my_server.com/my_api/downloadFile/54ef654zeze4'
Opening in a new window: parent.open('http://my_server.com/my_api/downloadFile/54ef654zeze4')

Downloading a PDF from an HTTP POST call

Here is what I'm trying to accomplish (IE 9+, Chrome, FF, Safari) without the use of JQuery:
Make an http POST call to my API endpoint with some data
Server dynamically generates a PDF and returns the PDF as a binary attachment
Browser does default download behavior and downloads the PDF without refreshing the page
Basically I want to get the behavior similar to <a href="test.pdf"> but for a dynamically generated PDF after making a POST call instead of a GET call.
I've tried lots of different things, but they either didn't work cross browser (such as using $window.open() with a blob URL), were blocked by popup blockers (any $window call outside of the click scope), or didn't cause the PDF to be automatically downloaded (any $http POST solution).
I finally found one solution that seems to work which creates a form using javascript and submits it.
var form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('action', myurl);
var params = {foo: 'bar'};
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement('input');
hiddenField.setAttribute('type', 'hidden');
hiddenField.setAttribute('name', key);
hiddenField.setAttribute('value', params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
This successfully accomplishes the 3 steps above, but now I've run into a new problem. There is no way to determine when the PDF file has been successfully downloaded. This is preventing me from removing the form and from displaying a friendly 'Please wait...' message to the user. There is also the additional problem that submitting the form cancels any outstanding ajax requests as well which isn't optimal.
I have full control over both the server and the client, so what's the best way to fix this? I don't want to have to save the PDF on the server so passing back a url and doing a second GET request from the client won't work in this case. Thanks!
You can make an server response behave as a download by applying some HTTP headers:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="SOME_NAME.pdf"
Content-Transfer-Encoding: binary
If you're initiating the download through JS only (instead of having the user click a download link), then check out this question for some caveats.
Update: Syntax for POST
Better Update: Form solution with iframe target
You can detect that your server-side script has finished (and subsequently, that the download is ready to begin) by having the form target an iframe. I believe this should also fix the issue of cancelling outstanding Ajax calls, but I'm not certain. Here is the code to do it (just stick this into your code example after the for loop and before document.body.appendChild(form);):
var frame = document.createElement('iframe');
frame.setAttribute('id', 'pdfFrame');
frame.onload = function(){
document.body.removeChild(form);
document.body.removeChild(frame);
alert('Download ready!');
}
document.body.appendChild(frame);
form.setAttribute('target', 'pdfFrame');
You can replace my alert with your code to remove the 'Please wait...'.