Context: Windows 7, IE10, JScript, Google Adwords, OAuth2
I have generated an access_token and a refresh_token using the using the urn:ietf:wg:oauth:2.0:oob technique and all appears to be okay. The tokens I've generated this way are working fine with Analytics calls. This issue is with Adwords calls to https://adwords.google.com/api/adwords/reportdownload/v201309 . The header and data is as follows:
Authorization: GoogleLogin auth=ya29.blahblah
developerToken: blahblah
clientCustomerId: blahblah
returnMoneyInMicros: false
Content-Type: application/x-www-form-urlencoded
__rdxml=<reportDefinition xmlns="https://adwords.google.com/api/adwords/cm/v201309"> <selector> <fields>CampaignId</fields> <fields>Id</fields> <fields>Impressions</fields> <fields>Clicks</fields> <fields>Cost</fields> <predicates> <field>Status</field> <operator>IN</operator> <values>ENABLED</values> <values>PAUSED</values> </predicates> </selector> <reportName>Custom Adgroup Performance Report</reportName> <reportType>ADGROUP_PERFORMANCE_REPORT</reportType> <dateRangeType>LAST_7_DAYS</dateRangeType> <downloadFormat>CSV</downloadFormat> </reportDefinition>
The report XML is straight off the documentation.
When I submit that request I get the following error:
AuthenticationError.GOOGLE_ACCOUNT_COOKIE_INVALID
LATER
I changed the header
Authorization: GoogleLogin auth=ya29.blahblah
to
Authorization: Bearer ya29.blahblah
and am now getting
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<reportDownloadError>
<ApiError>
<type>AuthenticationError.OAUTH_TOKEN_INVALID</type>
<trigger><null></trigger>
<fieldPath></fieldPath>
</ApiError>
</reportDownloadError>
The token, however, is current, having been regenerated just before the test.
FINALLY
Changed the scope to
https://adwords.google.com/api/adwords/
and also referred to a non-MCC account.
for Mikeys4u
function OAuthConnect(client_id, scope, login_hint) {
var url = XMAP("https://accounts.google.com/o/oauth2/auth?[1]&[2]&[3]&[4]&[5]&[6]",
"response_type=code",
"client_id=" + client_id,
"redirect_uri=" + "urn:ietf:wg:oauth:2.0:oob",
"scope=" + escape(scope),
"state=acit",
"login_hint=" + login_hint);
var oIE = new ActiveXObject("InternetExplorer.Application");
oIE.Visible = true;
oIE.Navigate(url);
while (oIE.busy) {
WScript.Sleep(10);
};
var status = oIE.Document.title;
while (status.indexOf("state=acit") === -1) {
WScript.Sleep(100);
status = oIE.Document.title;
}
// WScript.Echo(status);
oIE.Quit();
var code = RightOf(status, "&code=");
return code;
}
That's referring to a lot of helper code (like XMAP and RightOf) but you should be able to get the drift.
The call of that code looks like
if (accessToken === "") {
code = OAuthConnect(secrets.client_id, oCFG.retrieve(client + ".scope"), oCFG.retrieve(client + ".login_hint"));
This is JScript, by the way.
Related
I am implementing a client with Spring Security OAuth2 to use resources through an API, I have to customize the request like this:
POST https://example.com/v2/oauth2/token HTTP / 1.1
Authorization: Basic xxxXXXXxxXXXXXXxXXxxXX
Content-Type: application / x-www-form-urlencoded
Accept: application / json; charset = UTF-8
grant_type = authorization_code & code = 12345678901234567890
Where: grant_type = authorization_code & code = 12345678901234567890
it is contained in the body as raw data.
How can I put the grant_type and code parameters on the body?
At the moment my code is formalized in this way:
AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails ();
resource.setAccessTokenUri ( "https://example.com/v2/oauth2/token");
resource.setClientId ( "xxxxx");
resource.setClientSecret ( "xxxxx");
resource.setGrantType ( "authorization_code");
resource.setUseCurrentUri (false);
AccessTokenRequest atr = new DefaultAccessTokenRequest ();
atr.setPreservedState (new Object ());
atr.setAuthorizationCode(authCode);
AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider ();
try {
OAuth2AccessToken accessToken = provider.obtainAccessToken (resource, atr);
}
catch (Exception e) {
System.out.println ("DEBUG" + e);
}
Maybe you can use a filter to intercept the request to the token endpoint before the authorization server completes the process of authorization.
This is my implementation of OAuth2 using a json as a body instead of URL-encoded format.
https://github.com/aldwindelgado/spring-boot-oauth2-server/blob/master/src/main/java/com/github/oauth2/server/JsonToUrlEncodedAuthenticationFilter.java
Add atr.setAuthorizationCode("12345678901234567890"); to set the auth code to the Access Token Request.
I'm writing a simple desktop application to get information from QuickBooks(developer account using demo account(UK) data) and in this regard I've been able to go past the OAuth flow. However, I've not been able to get the basic company information
The below is a capture of the Fiddler request and response:
GET https://quickbooks.api.intuit.com/v3/company/123145829830639/companyInfo/123145829830639 HTTP/1.1
Authorization: oauth_token="****", oauth_nonce="z4x0a196", oauth_consumer_key="****", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1499283607", oauth_version="1.0", oauth_signature="EGw6Ty%2BKFAawrH1%2FSxQuFwaMcEo%3D"
Content-Type: application/json
Host: quickbooks.api.intuit.com
The generation of the header is similar to https://developer.intuit.com/v2/apiexplorer?apiname=V3QBO#?id=CompanyInfo but I end up getting the following response(Fiddler partial response) based on the request
intuit_tid: gw-c4e19f89-df78-42a5-ae7e-216187421143
Set-Cookie: JSESSIONID=21BF1FFEE48B39538E82485FD25C4280.c51-pprdsbxas901; Path=/; Secure; HttpOnly
QBO-Version: 1706.912
ErrorCode: 100
ErrorCause: AuthenticationErrorGeneral: SRV-110-Authentication Failure , statusCode: 401
Message: General Authentication Error
The code to access company information is as below:
string companyInfo = String.Format("company/{0}/companyInfo/{0}", authenticator.OAuthProfile.realmId);
string ciUrl = BASE_URL + companyInfo; //https://quickbooks.api.intuit.com/v3/
var sb = new System.Text.StringBuilder();
sb.AppendFormat("oauth_token=\"{0}\", oauth_nonce=\"{1}\", oauth_consumer_key=\"{2}\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"{3}\", oauth_version=\"1.0\", oauth_signature=\"{4}\"",
Manager.UrlEncode(_token),
Manager.UrlEncode(_nonce),
Manager.UrlEncode(_consumer_key),
Manager.UrlEncode(_timestamp),
Manager.UrlEncode(_signature));
var authorisationHeader = sb.ToString().TrimEnd(' ').TrimEnd(',');
// Request Company Information
var request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(ciUrl);
request.Headers.Add("Authorization", authorisationHeader);
request.Method = "GET";
request.ContentType = "application/json";
using (var response = (System.Net.HttpWebResponse)request.GetResponse())
{
// get 401
}
Used sandbox URL and added minorversion to the base URL
I attempted setting BASE_URL set to the sandbox url(https://sandbox-quickbooks.api.intuit.com/v3) and also set minorversion to be 4.
Any help is much appreciated.
Hopefully this helps, but here is a Java snippet using their SDK that works for me:
OAuthAuthorizer oauth = new OAuthAuthorizer(System.env.QB_OAUTH_CONSUMER_KEY, System.env.QB_OAUTH_CONSUMER_SECRET,
vendor.intuitOAuthAccessToken, vendor.intuitOAuthAccessSecret);
UUID trackingID = UUID.randomUUID()
log.info("About to init Context companyID=" + vendor.realmId + ", app_token=" + System.env.QB_APP_TOKEN + ", uuid=" + trackingID.toString())
Context context = new Context(oauth, System.env.QB_APP_TOKEN, ServiceType.QBO, vendor.realmId)
context.setMinorVersion("4")
context.setTrackingID(trackingID)
log.info("About to set BaseURL")
Config.setProperty(Config.BASE_URL_QBO, System.env.QB_BASE_URL + "/v3/company");
log.info("About to init DataService")
// get all customers
log.info("About to executeQuery")
DataService service = new DataService(context)
QueryResult queryResult = service.executeQuery("select * from customer");
In my case, QB_BASE_URL=https://sandbox-quickbooks.api.intuit.com
*NOTE there isn't a trailing slash
vendor.intuitOAuthAccessToken and vendor.intuitOAuthAccessSecret are the values you get back after the oauth flow
I'm trying to find Twitter handles from a spreadsheet containing names of people.
I can't get it work with this request, which I believe is the one I should be using as I only have peoples names (e.g. Adam Smith): api.twitter.com/1.1/users/search.json?q=
I get the following error:
Request failed for api.twitter.com/1.1/users/search.json?q=Name returned code 403. Truncated server response: {"errors":[{"message":"Your credentials do not allow access to this resource","code":220}]} (use muteHttpExceptions option to examine full response) (line 38).'
I've tried searching this error but that hasn't helped me so far.
If I use, for example, this request, it works: api.twitter.com/1.1/users/show.json?screen_name=
So I can get the screen_name back in the spreadsheet, but that's pointless obviously because it needs the screen name to work in the first place...
The whole thing is based on this work, all the requests in that code work for me. It's just this search request that doesn't work. What's going wrong?
var CONSUMER_KEY = 'x';
var CONSUMER_SECRET = 'x';
function getTwitterHandles(name) {
// Encode consumer key and secret
var tokenUrl = "https://api.twitter.com/oauth2/token";
var tokenCredential = Utilities.base64EncodeWebSafe(
CONSUMER_KEY + ":" + CONSUMER_SECRET);
// Obtain a bearer token with HTTP POST request
var tokenOptions = {
headers : {
Authorization: "Basic " + tokenCredential,
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
method: "post",
payload: "grant_type=client_credentials"
};
var responseToken = UrlFetchApp.fetch(tokenUrl, tokenOptions);
var parsedToken = JSON.parse(responseToken);
var token = parsedToken.access_token;
// Authenticate Twitter API requests with the bearer token
var apiUrl = 'https://api.twitter.com/1.1/users/search.json?q=screen_name='+name;
var apiOptions = {
headers : {
Authorization: 'Bearer ' + token
},
"method" : "get"
};
var responseApi = UrlFetchApp.fetch(apiUrl, apiOptions);
var result = "";
if (responseApi.getResponseCode() == 200) {
// Parse the JSON encoded Twitter API response
var tweets = JSON.parse(responseApi.getContentText());
return tweets.id
}
Logger.log(result);
}
Edit: deleted the https a few times because of the URL limit
You can not search for users using application-only authentication (bearer token). See https://dev.twitter.com/oauth/application-only. A user context (access token) is needed for that request. You can get your own access token from https://apps.twitter.com.
I had a Google Apps Script to take appointments from my Google Calendar, copy them into a Google Sheet, convert it to XLS and email it. It was working fine until this week.
The initial problem was a 302 error, probably caused by the new version of Sheets. This has been discussed here: Export (or print) with a google script new version of google spreadsheets to pdf file, using pdf options
I got the new location of the file by muting the HTTP exceptions and adjusting the URL accordingly. I also updated the OAuth scope to https://docs.google.com/feeds/ as suggested.
The program is failing with an "OAuth error" message. When muteHttpExceptions is set to true, the message is "Failed to authenticate to service: google".
I guess this is a scope problem but I really can't see what I've done wrong. Naturally, I've tried a few other possibilities without luck.
I've included the code below. Commented code is the instruction that worked until this week.
function getSSAsExcel(ssID)
{
var format = "xls";
//var scope = "https://spreadsheets.google.com/feeds/";
var scope = "https://docs.google.com/feeds/";
var oauthConfig = UrlFetchApp.addOAuthService("google");
oauthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
oauthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope=" + scope);
oauthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
oauthConfig.setConsumerKey("anonymous");
oauthConfig.setConsumerSecret("anonymous");
var requestData = {
//"muteHttpExceptions": true,
"method": "GET",
"oAuthServiceName": "google",
"oAuthUseToken": "always"
};
//var url = "https://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=" + ssID
var url = "https://docs.google.com/spreadsheets/d/" + ssID
+ "/feeds/download/spreadsheets/Export?"
+ "&size=A4" + "&portrait=true" +"&fitw=true" + "&exportFormat=" + format;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
return contents;
}
Thanks for your help!
Instead of using OAuthConfig (which must be auth'ed in the Script Editor) you can pass an OAuth2 token instead, retrievable via ScriptApp.getOAuthToken().
The code snippet below uses the Advanced Drive service to get the export URL, but if you hand construct the URL you'll need to ensure that the Drive scope is still requested by your script (simply include a call to DriveApp.getRootFolder() somewhere in your script code).
function exportAsExcel(spreadsheetId) {
var file = Drive.Files.get(spreadsheetId);
var url = file.exportLinks[MimeType.MICROSOFT_EXCEL];
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
return response.getBlob();
}
ok after two days of tryouts i still cant my titanium application to play well with twitter request_token api 1.1, i am always getting 401 unauthorized error .below is my code. i am blocked so any help is appreciated.
var httpClient = Ti.Network.createHTTPClient({
onerror : function(e) {
alert(this.status + ":" + e.error);
},
onload : function(e) {
alert(this.responseText);
if (this.readyState == 4) {
var resposeText = this.responseText;
}
}
});
httpClient.open('POST', "https://api.twitter.com/oauth/request_token");
httpClient.setRequestHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8");
var now = new Date().getTime();
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var nonce = "";
for (var i = 0; i < 10; ++i) {
var rnum = Math.floor(Math.random() * chars.length);
nonce += chars.substring(rnum, rnum + 1);
}
var parameters = "oauth_callback=" + Ti.Network.encodeURIComponent("http://apicallback.stc.com.sa");
var signature = "POST&" + Ti.Network.encodeURIComponent("https://api.twitter.com/oauth/request_token") + "&" + Ti.Network.encodeURIComponent(parameters);
var header = "OAuth oauth_callback=\"" + Ti.Network.encodeURIComponent("http://apicallback.stc.com.sa") + "\",oauth_consumer_key=\"wPdlchopdYaqHhab8H8jMA\",oauth_nonce=\"" + nonce + "\",oauth_signature=\"" + signature + "\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"" + now + "\",oauth_version=\"1.0\"";
httpClient.setRequestHeader("Authorization", header);
httpClient.send(parameters);
There were several errors :
Your nonce seems to be built incorrectly. Generate a string with 32 letters and encode it with Base 64.
Your signature is not built correctly too. Refer to the Twitter Developers documentation about making signatures. Here are your errors :
All the OAuth arguments are missing but oauth_callback. The OAuth arguments which are used in the Authorize header have to be included in the parameters for the signature
You do not build the key to sign datas.
You do not use the signature method (oauth_signature_method which is set to "HMAC-SHA1") to sign your datas.
Your timestamp is too big. It is the number of seconds since the Unix Epoch time, not the milliseconds. Add a "/1000" :
var now = new Date().getTime() / 1000
More generally have a look at Twitter Developers documentation about authorizing requests : https://dev.twitter.com/docs/auth/authorizing-request
by chance i found javascript library posted in twitter list of libraries. check it out jsOAuth. there is also API doc for the library :). now i am able to get the authorization token but when i perform search by posting to https://api.twitter.com/1.1/search/tweets.json i get 401 (unauthorized) error. now i am stuck again. any idea what might be the problem...
There are multiple twitter libraries out there for appcelerator that already work, I would suggest starting with one of them.
http://www.clearlyinnovative.com/blog/post/33810421717/titanium-appcelerator-quickie-posting-images-to-twitter-with-social_plus-js
see link to github repo at bottom of posting