Accessing Dropbox app from browser - javascript

I'm trying to test connecting to a Dropbox app (created on my account) from a web page running on localhost. I've chosen to generate an authorization code rather than using the redirect. It seems that any code that's generated and displayed on the code page (https://www.dropbox.com/1/oauth2/authorize_submit) produces an error in the console when I try to access the app folder's metadata:
window.open('https://www.dropbox.com/1/oauth2/authorize?client_id=<appId>&response_type=code');
POST https://api.dropboxapi.com/1/metadata/auto/ 401 (Unauthorized)
DropboxCloud # DropboxCloud.js:8
(anonymous) # MainWindowStandalone.js:45
DropboxCloud.js:10 {"error": "The given OAuth 2 access token doesn't exist or has expired."}
However, if I use an authorization code generated on the Dropbox app page I a can successfully reach the folder :
DropboxCloud.js:10 {"hash": "68a0fc8c0c5670ff10e8e98b7fefcde8", "thumb_exists": false, "bytes": 0, "path": "/", "is_dir": true, "icon": "folder", "root": "app_folder", "contents": [], "size": "0 bytes"}
My code:
var request = new XMLHttpRequest();
const url = 'https://api.dropboxapi.com/1/metadata/auto/';
request.open('post', url, true);
request.setRequestHeader('Authorization', 'Bearer ' + accessToken);
request.setRequestHeader('Content-Type', 'application/json');
request.send();
request.onload = () => {
console.log(request.response);
};
I'd like to grant others access using the code generation page to help me test my app. What else do I need to make it work?

The issue here is that "authorizations codes" are not the same as "access tokens", and cannot be used interchangeably.
When you retrieve a token using the OAuth 2 "token" flow, or via the "Generate" button on the app's page on the App Console, that gives you an actual Dropbox API OAuth 2 access token. That can be used to make API calls, such as to /1/metadata.
The string you get back from /oauth2/authorize when you use the OAuth 2 "code" flow is only an authorization code. That can't itself be used to make API calls. It is a temporary code that you can exchange for an access token, using /oauth2/token.
(Also, note that Dropbox API v1, such as /1/metadata, is deprecated.)

Related

How to get new messages using gmail api

I'm writing a Google Chrome browser extension. It uses gmail-api and I want to receive incoming messages coming to the email address of the user who is logged in. How do I implement this in the background script in terms of code. I know that gmail api uses post requests such as watсh, then I don’t know how to implement the code so that I can see messages that would come in real time and my background script would be updated during this event.
My application uses the methods of pull alerts, and accordingly the documentation says that I should use requests such as
https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/pull
https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions/acknowledge
How can I use all this in my code so that my script is constantly updated when I receive a new message and is it even possible in javascript?
function POST_request(method,url,_async,params)
{
let xhr= new XMLHttpRequest();
xhr.open(method,url,_async);
xhr.setRequestHeader('Authorization', 'Bearer ' + current_token);
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send(JSON.stringify(params));
return(xhr.responseText);
}
let tmp={
"topicName":"projects/myprofect/topics/mytopic",
"labelFilterAction":"include",
"labelIds": ["INBOX"]
};
console.log(POST_request("POST","https://www.googleapis.com/gmail/v1/users/me/watch",false,tmp));
This query works by returning the view body
{
"historyId": "678576",
"expiration": "1555318376357"
}

POST Request to Jira REST API using Oauth Header - Responds with 401 "Anonymous User" Error

I am building a web application which will have a form to submit bug reports. The bug submission form, when submitted, fires off an HTTP POST request to a JIRA instance using the jira/rest/api/2/issue endpoint to create a single issue based on what the user has entered into the form.
I've authenticated my application against the JIRA instance and obtained an Oauth bearer token to include in my HTTP request headers. However, when this POST request is fired, I receive a 401 error with the following error message:
Anonymous users do not have permission to create issues in this project. Please try logging in first.
I'm not sure why the JIRA server considers this request Anonymous, since the request contains the "Authorization" header with an Oauth token included, which I believe should authenticate the request as a certain user. But perhaps I am misunderstanding the relationship between the Oauth token and the JIRA instance.
This is what the function that fires off the request looks like (using React):
submitBug() {
var jira_create_issue_api_url = "https://placeholder.org/jira/rest/api/2/issue";
var xhttp = new XMLHttpRequest();
xhttp.open("POST", jira_create_issue_api_url, true); //async POST to API resource
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.setRequestHeader("Accept", "application/json");
xhttp.setRequestHeader("X-Atlassian-Token", "no-check");
xhttp.setRequestHeader("Authorization", "Bearer <oauth token here>");
xhttp.onload = () => {
console.log("JIRA REST API responded: ");
console.log(xhttp.status);
console.log(xhttp.response);
};
var summary_text = this.props.bug_summary; //filled out by user in form
var desc_text = this.state.bug_description; //filled out by user in form
var bug_data = {
fields: {
project: {
key: "KEY"
},
summary: summary_text,
description: desc_text,
issuetype: {
name: "Bug"
}
}
};
xhttp.send(JSON.stringify(bug_data));
}
Any insight is greatly appreciated! I'm new to developing with the JIRA REST API so I may be missing something obvious.
Edit: As requested, the headers as they appear in Chrome:
Accept: application/json
Authorization: Bearer [oauth token here]
Content-type: application/json
Origin: [app url]
Referer: [app url]
User-Agent: [browser-specific info]
X-Atlassian-Token: no-check

Tumblr API OAuth with local test server

I'm trying to get posts from my tumblr blog and put them on a separate website page. To do this I registered an app on their OAuth page, but I'm having some issues when I try to actually request the authorization. My console spits out this message—
XMLHttpRequest cannot load https://api.tumblr.com/v2/blog/myblog.tumblr.com/posts?api_key=(MY_KEY).
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://127.0.0.1:63342' is therefore not allowed access.
(I've omitted the key value here for obvious reasons).
Now, my site isn't actually live yet, and I have a test server running at localhost:63342 but on their OAuth app settings page I have these options that I must fill out—
Is there a way to get this to work with my local test server? Here's the code that I'm calling to request access.
var request = new XMLHttpRequest();
request.open('GET', 'https://api.tumblr.com/v2/blog/myblog.tumblr.com/posts?api_key=(API_KEY)', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
// Success!
var data = JSON.parse(request.responseText);
console.log(data);
} else {
// We reached our target server, but it returned an error
console.log('server error');
}
};
request.onerror = function() {
// There was a connection error of some sort
console.log("ERROR!!!");
};
request.send();
Any help would be appreciated! Thanks!
Turn out my issue was using JSON instead of JSONP, which bypasses the Access-Control-Allow-Origin issue. I downloaded this JSONP library for Javascript ( I am not using JQuery in my project ) and was able to access the api by writing this:
JSONP('https://api.tumblr.com/v2/blog/myblog.tumblr.com/posts?api_key=(API_KEY)'
, function(data) {
console.log(data);
});
Which returns a JSON Object which I can then data from using something like data.response or whatever objects are in the array.
Again, my issue was not Tumblr not authorizing my test server. I was able to get this to work using 127.0.0.1:port as my application website & callback url.

GMail API access from chrome extension? 403 Forbidden

I have an application that accesses Google APIs out of a Chrome extension via the workflow outlined here.
Chrome Extensions OAuth Tutorial
The basics of the workflow are to initialize the OAuth flow
var oauth = ChromeExOAuth.initBackgroundPage({
'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken',
'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken',
'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken',
'consumer_key': '{MY_CLIENT_ID}',
'consumer_secret': '{MY_CLIENT_SECRET}',
'scope': 'https://www.google.com/m8/feeds/ https://apps-apis.google.com/a/feeds/emailsettings/2.0/ https://mail.google.com/',
'app_name': 'Gmail Plugin',
'callback_page': 'src/google-oauth/chrome_ex_oauth.html'
});
Upon installing the extension, the user is taken to dialog page to authenticate and agree to the scopes I ask for. From here I infer that my consumer key and secret are OK. I have allowed access to the GMail, Contacts, and Admin SDK in the Google Developers console.
Prior to this I had requests working with the Contacts API and Admin SDK API. I'm now trying to add some features that utilize the Gmail REST API.
The next step in setting up a request is to make a request from the background page.
function getSentEmails() {
var emailCollection;
var url = "https://www.googleapis.com/gmail/v1/users/me/messages";
var request = {
'method': 'GET',
'parameters': {
'labelIds': 'SENT'
}
};
var callback = function(response, xhr) {
emailCollection = JSON.parse(response);
console.dir(emailCollection);
}
oauth.sendSignedRequest(url, callback, request);
};
The way the signed requests work is to call a method to complete the next step of the OAuth dance,
oauth.authorize(function() {
getSentEmails();
});
This results in a 403 Forbidden every time. I seem to have no issue accessing the other APIs I mentioned though this OAuth flow. I've allowed the scope in my manifest.json
manifest.json
"permissions": [
"tabs",
"storage",
"https://mail.google.com/*",
"https://www.google.com/m8/feeds/*",
"https://apps-apis.google.com/a/feeds/emailsettings/2.0/*",
"https://www.googleapis.com/gmail/v1/users/*",
"https://www.googleapis.com/auth/gmail.modify/*",
"https://www.googleapis.com/auth/gmail.compose/*",
"https://www.googleapis.com/auth/gmail.readonly/*",
"https://www.google.com/accounts/OAuthGetRequestToken",
"https://www.google.com/accounts/OAuthAuthorizeToken",
"https://www.google.com/accounts/OAuthGetAccessToken"
]
I tried an alternate method of building the HTTP request as outlined in the link above.
function stringify(parameters) {
var params = [];
for(var p in parameters) {
params.push(encodeURIComponent(p) + '=' +
encodeURIComponent(parameters[p]));
}
return params.join('&');
};
function xhrGetSentEmails() {
var method = 'GET';
var url = 'https://www.googleapis.com/gmail/v1/users/me/messages';
var params = {'labelIds': 'SENT'};
var callback = function(resp, xhr) {
console.log(resp);
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(data) {
callback(xhr, data);
};
xhr.open(method, url + '?' + stringify(params), true);
xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
xhr.send();
}
I get the same 403 doing this.
I believe I'm authenticating properly though, because if I change
xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
to
xhr.setRequestHeader('Authorization','foo' + oauth.getAuthorizationHeader(url, method, params));
I get a 401 Unauthorized instead.
Again, no trouble accessing the other APIs I mentioned.
Any input would be much appreciated.
This question is probably fairly obscure, so I'll share how I ended up resolving it.
I moved my chrome extensions OAuth 2.0 workflow to the newer (since Chrome 29) chrome.identity setup for apps and extensions.
Detailed instructions for setting up OAuth 2.0 for an extension are here.
Chrome Identity API User Authentication
Now I can use
chrome.identity.getAuthToken(function(token) {
// Do HTTP API call with token
});
And none of my HTTP requests come up forbidden (403) anymore.
Hope this is helpful to extension builders out there!

301 Redirect Preventing CORS OPTIONS Request on Openshift

I'm writing a RESTful api with Laravel 4 that will be used by a Backbone.js app.
When I deploy my code using GIT, I receive a message saying:
Application directory "public/" selected as DocumentRoot
When using the Backbone.js app, PUT, GET and DELETE requests are handled appropriately, but the preflight request (OPTIONS) fails because of the redirect when I try to make a POST request:
Request Method: OPTIONS
Status Code: 301 Moved Permanently
With this error on the console:
XMLHttpRequest cannot load http://MY-DOMAIN.rhcloud.com/projetos/. The request was redirected to 'http://MY-DOMAIN.rhcloud.com/projetos', which is disallowed for cross-origin requests that require preflight.
This happens because of the CORS Policy:
If the response has an HTTP status code of 301, 302, 303, 307, or 308
Apply the cache and network error steps.
How can I overcome this problem? Is there a way to bypass or configure the Openshift redirect?
>>>EDIT
I am getting this error on the Chrome javascript console, because my Backbone App is in development fase still. Here the steps to replicate the problem:
I have a global namespace "App", and my project is organized in this form: App.Models, App.Collections, etc.
The Model
App.Models.Projeto = Backbone.Model.extend({
defaults : {
codigo : '',
titulo : '',
url : '',
status : ''
}
});
The Collection
App.Collections.Projetos = Backbone.Collection.extend({
model : App.Models.Projeto,
url : 'http://MY-DOMAIN.rhcloud.com/projetos'
});
On the Console
var projetos = new App.Collections.Projetos;
projetos.create({
titulo : "blablabla",
codigo : "12jk4h3",
url : "example.com",
status : 0
});
I am able to fetch, edit and delete models in the collection. The only thing I cannot do is to create a new one.
One last thing, the URL I'm redirected to is the same URL, but without a "/" at the end.
So even if the "url" property in the collection is set to http://MY-DOMAIN.rhcloud.com/projetos it seems like Backbone adds a "/", and then in the server, it gets redirected.

Categories

Resources