This is my first time working on HMAC,
I have this method to create hash string for HMAC:
var msg = method + publicKey + path + privateKey
//like:
var msg = 'GET' + 'MY-PUBLIC-KEY' + '/api/account' + 'MY_PRIVATE_KEY';
I'm using this library for converting msg to md5.
in the backend code I see
string expectedValue = Hashing.GetHashHMACCMD5OfString(msg, PublicKey)
....
public static string GetHashHMACCMD5OfString(string value, string key)
{
using (var cryptoProvider = new HMACMD5(Encoding.UTF8.GetBytes(key)))
{
var hash = cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(value));
return Convert.ToBase64String(hash);
}
}
I don't know about .net, is it enough just to convert msg as
var md5Msg = md5(msg, publickey);
// and request
$http({
url: url,
method: 'GET',
headers: {
'Authentication': md5Msg + ' ' + publickey
}
});
in javascript or I need any other conversion (like toBase64) to do?
Related
I am writing below code in Javascript to retrieve comment and navigating same page after repopulating the data
function MoveItem() {
var empId = document.getElementById('EMP_ID').value;
var commentValue = $("#RESPONSE").val();
if ($.trim(commentToSave).length > 0) {
showAjaxLoading();
var empData= "APPROVE";
var baseControllerUrl = '/Employee/EmpManagement/PushItem';
window.location.href = baseControllerUrl + "/" + empId + "?comment=" + commentValue + "&empData=" + empData + "¤tItem=" + itemData;
} else {
aet('Pelase enter comments', 'E');
}
}
In controller the method written as
[HttpGet]
public async Task<ActionResult> MoveItem(int id, string comment, string decision, string currentworkflow)
{
return RedirectToAction("EditEmpManagemnt", "EmpManagement", new { id = id });
}
I want to convert MoveItem action method to a [HttpPost] type and what all changes are needed in Javascript & action method ? Can anyone explain with a sample code.
You can send a POST request using the fetch method. We send the data with the JSON format. Replace your javascript with this:
function MoveItem() {
var empId = document.getElementById('EMP_ID').value;
var commentValue = $("#RESPONSE").val();
if ($.trim(commentToSave).length > 0) {
showAjaxLoading();
var empData = "APPROVE";
var baseControllerUrl = '/Employee/EmpManagement/PushItem';
var url = baseControllerUrl + "/" + empId;
//here we put the url as a first parameter
//then we configure the http method
//and in the body we pass in the object in JSON format
fetch(url, {
method: "POST",
body: JSON.stringify({
"comment": commentValue,
"empData": empData,
"currentItem": itemData
})
}).then(result => {
//do something with the result you get back
console.log("Completed with result: " + result);
}).catch(err => {
//if any error occured, then show it here
console.log("There is an error: " + err);
});
} else {
aet('Please enter comments', 'E');
}
}
And in your C# code just replace [HttpGet] attribute with [HttpPost]
I work with Java/ Sprig MVC RESTful app and the client consumes it. I have 2 RESTful methods in the same input parameters and different return types. The methods are provided below,
// this method should return the `String`
#RequestMapping(value = "wallets/{currencyName}/{walletName}", method = RequestMethod.GET
, produces = "text/html")
public ResponseEntity<String> getAddressWithCurrencyAndWalletName(#PathVariable("currencyName") String currencyName,
#PathVariable("walletName") String walletName) {
logger.info("The currency name is {} and wallet name is {}", currencyName, walletName);
WalletInfo walletInfo = walletService.getWalletInfoWithCurrencyAndWalletName(currencyName, walletName);
if (Objects.isNull(walletInfo)) {
return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
}
String address = walletInfo.getAddress();
return new ResponseEntity<String>(address, HttpStatus.OK);
}
// this method should return the `Long`
#RequestMapping(value = "wallets/{currencyName}/{walletName}", method = RequestMethod.GET,
produces = "text/html")
public ResponseEntity<Long> getWalletIdWithCurrencyAndWalletName(#PathVariable("currencyName") String currencyName,
#PathVariable("walletName") String walletName) {
logger.info("The currency name is {} and wallet name is {}", currencyName, walletName);
WalletInfo walletInfo = walletService.getWalletInfoWithCurrencyAndWalletName(currencyName, walletName);
if (Objects.isNull(walletInfo)) {
return new ResponseEntity<Long>(HttpStatus.NOT_FOUND);
}
Long walletId = walletInfo.getId();
return new ResponseEntity<Long>(walletId, HttpStatus.OK);
}
In the client-side, I have UI like this,
If the Balance button is clicked, I would like to open a new page with URL of http://localhost:63342/WalletClient/balance.html?walletId=someValue and I would like to use the 2nd RESTful method for the very purpose. I imagine the client code to be like;
$(document).ready(function () {
var walletName, selectedCurrency;
// generic request function with the URL, method name and
// the request (GET, POST, PUT, DELETE etc) data
function request(url, method, data) {
$.ajax({
url: baseUrl + url,
// url: url,
method: method,
data: data
})
}
// some code
// we have the walletName and selectedCurrency values extracted
$("#balance").click(function () {
console.log("Open the balance page");
var url = "/rest/wallets/?" + "currencyName=" + selectedCurrency + "&" + "walletName=" + walletName;
// get the wallet Id from the cureny name and the wallet name
request(url, "GET").done(function (data) {
window.open("/WalletClient/balance.html?walletId=" + data);
});
});
}
The URL comes from the RESTful method and I expect it to return the Long. I have few questions in this scenarios,
a. Will it work as the same GET request could potentially return the String and Long?
b. is the data is already the String or the Long or I need to do something on over it?
Obvously, I can write it like window.open("/WalletClient/balance.html?" + "currencyName=" + selectedCurrency + "&" + "walletName=" + walletName);.
However, in this case the currencyName and the walletName will be exposed to the user and I would much prefer to hide it in the URL.
UPDATE
I changed the code to accomodatean optional parameter to distinct between the Long and the String,
/**
* get the wallet address with the currency name and the wallet name
*
* returns the Long value for the walletInfo
* curl -i -H "Accept: text/html" http://localhost:8080/rest/wallets/bitcoin/puut | json
*
*
* returns the String value for the walletInfo address
* curl -i -H "Accept: text/html" http://localhost:8080/rest/wallets/bitcoin/puut/true | json
*
* #param currencyName
* #param walletName
* #return
*/
#RequestMapping(value = "wallets/{currencyName}/{walletName}", method = RequestMethod.GET
, produces = "text/html")
public ResponseEntity<?> getAddressWithCurrencyAndWalletName(#PathVariable("currencyName") String currencyName,
#PathVariable("walletName") String walletName
, #RequestParam(value = "address", required = false) boolean address) {
logger.info("The currency name is {} and wallet name is {}", currencyName, walletName);
WalletInfo walletInfo = walletService.getWalletInfoWithCurrencyAndWalletName(currencyName, walletName);
if (Objects.isNull(walletInfo)) {
return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
}
// address values is expected
if(address){
String addressValue = walletInfo.getAddress();
return new ResponseEntity<String>(addressValue, HttpStatus.OK);
}
else {
Long walletId = walletInfo.getId();
return new ResponseEntity<Long>(walletId, HttpStatus.OK);
}
}
The client side URL will be like this,
var url = "/rest/wallets/?" + "currencyName=" + selectedCurrency + "&" + "walletName=" + walletName;
Is this correct now?
You can change your method and return ResponseEntity<?> type.
It would be:
#RequestMapping(...)
public ResponseEntity<?> yourMethod(...) {
// business-logic
if (some condition) {
return new ResponseEntity<String>(address, HttpStatus.OK);
} else if (...) {
return new ResponseEntity<Long>(walletId, HttpStatus.OK);
}
}
Trying to finish an OAuth2 flow, but keep getting an uncaught referenceerror. Fairly new to Node.js and cant seem to find out what's going on.
// require the blockspring package.
var blockspring = require('blockspring');
var request = require('request');
// pass your function into blockspring.define. tells blockspring what function to run.
blockspring.define(function(request, response) {
// retrieve input parameters and assign to variables for convenience.
var buffer_clientid = request.params["buffer_clientid"];
var buffer_secret = request.params["buffer_secret"];
var redirectURI = request.params["redirectURI"];
var tokencode = request.params["tokencode"];
request({
method: "POST",
url: "https://api.bufferapp.com/1/oauth2/token.json",
headers: {
'User-Agent': 'request',
},
body: client_id=buffer_clientid&client_secret=buffer_secret&redirect_uri=redirectURI&code=tokencode&grant_type=authorization_code
}, function(error, response, body){
console.log(body);
// return the output.
response.end();
});
});
That's not valid JavaScript syntax:
body: client_id=buffer_clientid&client_secret=buffer_secret&redirect_uri=redirectURI&code=tokencode&grant_type=authorization_code
I'm assuming you are trying to concatenate your variable values to a string? Try this instead:
body: "client_id=" + buffer_clientid + "&client_secret=" + buffer_secret + "&redirect_uri=" + redirectURI + "&code=" + tokencode + "&grant_type=" +authorization_code
Strings in nodejs need to be quoted. In your request function, you're passing a key of body, with a value of what appears to be a giant variable. Because there are no quotes around client_id=buffer_clientid&client_secret=buffer_secret&redirect_uri=redirectURI&code=tokencode&grant_type=authorization_code, it's trying to treat this as a variable. When the parser gets to the = sign, it's trying to then set client_id = the following. This is throwing the error.
Simply quote the entire string or if you need to use variables concat using 'string' + variable + 'string'.
Judging by your variable names, you can simple rewrite it as follows:
request({
method: "POST",
url: "https://api.bufferapp.com/1/oauth2/token.json",
headers: {
'User-Agent': 'request',
},
body: 'client_id=' + buffer_clientid + '&client_secret=' + buffer_secret + '&redirect_uri=' + redirectURI + '&code=' + tokencode + '&grant_type=authorization_code'
}, function(error, response, body){
console.log(body);
// return the output.
response.end();
})
I'm currently working on incorporating an authorization feature for Twitter following the approach described here: https://dev.twitter.com/docs/auth/implementing-sign-twitter. I'm using Ajax to send my POST 'http' request, but I've been constantly running into a '401: Unauthorized' error. My code is below:
function getTweets() {
var time = generateTimestamp();
var nonce = generateNonce();
var signature = generateSignature(time, nonce);
var headers = {
"Authorization": 'OAuth oauth_callback="http%3A%2F%2Fwww.google.com%2F", oauth_consumer_key="eEeAAz9fakedtAOlIUhPgQ", oauth_nonce="bbc34b2ca6faabogus6dfc025907fa334", oauth_signature="' + signature + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + time + '", oauth_version="1.0"'
};
$.ajax({
type: "POST",
url: "https://api.twitter.com/oauth/request_token",
dataType: "text",
headers: headers,
success: function(data) {
alert("Success!");
console.log(data);
},
error: function(jq) {
alert("Request Failed.");
console.log(jq.statusText);
}
});
}
function generateTimestamp() {
var currentTime = new Date;
currentTime = Math.floor(currentTime.getTime() / 1000);
return currentTime;
}
function generateNonce() {
var code = "";
for (var i = 0; i < 20; i++) {
code += Math.floor(Math.random() * 9).toString();
}
return code;
}
function generateSignature(timestamp, nonce) {
var http_method = "POST";
var base_url = "https://api.twitter.com/oauth/request_token";
var consumer_key = "eEeAAz9hUKtdjunkeIUhPgQ";
var consumer_secret = "c7wHxnjubxVDcc5hYFqnotactuallymysecretWs2XazUFde0lPRBtBQ";
var signature_method = "HMAC-SHA1";
var token = "609493744-kNPzLKSI4Hg9NWQnopeFPb91eXFUutFm1nZ2hDk2";
var token_secret = "15WOJS9Ji1AXsKRkyAZrxKdsalted5Gj5ZyEAb9aVrJxI";
var version = "1.0";
var parameter_string = "oauth_callback=" + encodeURIComponent(base_url) + "&oauth_consumer_key=" + consumer_key + "&oauth_nonce=" + nonce + "&oauth_consumer_key=" + consumer_key + "&oauth_signature_method=" + signature_method + "&oauth_timestamp=" + timestamp +"&oauth_version=" + version;
var base_string = http_method + "&" + encodeURIComponent(base_url) + "&" + encodeURIComponent(parameter_string);
var signing_key = encodeURIComponent(consumer_secret) + "&";
var signature = encodeURIComponent(window.btoa(CryptoJS.HmacSHA1(base_string, signing_key)));
alert(signature);
return signature;
}
Feel free to post below if there's any other information that would make this error clearer. Thanks.
I created a node.js library to mess around with the Twitter OAuth dance and API. Code is here, tweeter.js
You're welcome to walk through the logic for creating the header and signature (starting at line 348 )
One thing I don't see in the code you've posted and which will make a huge difference is that the signature string must be generated to include the original header, then the header must be rebuilt with the generated string. It's a huge pain and it took me a while to figure it out.
Although the code I wrote is geared toward node.js, you should be able to reuse a lot of the logic to meet your needs.
EDIT
I found a site called hueniverse documented OAuth very well. In fact, there is a utility here to build your own headers for validating your logic (select the 'Create your own' radio button).
EDIT 2
To better explain including the oauth_signature value in the header, suppose you have all of the data up to this point:
var headerObj = {
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0"
};
You create the HMAC-SHA1 signature and receive: "jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
You would then add that return value to headerObj, giving you:
headerObj = {
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0",
oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
};
And this modified version of headerObj is what you build your HTTP headers from.
GET / HTTP/1.1
Host: api.twitter.com:443
Authorization: OAuth realm="https://api.twitter.com/",
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0",
oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
NOTE: I didn't verify the host/realm/port, so these are probably wrong. Check the API for those.
The reason this is done is that on Twitter's side (this is an OAuth implementation detail), the oauth_signature value is removed and the rest of the header is hashed and its return value is compared to the value sent in oauth_signature. It's sort of like a wax seal on an envelope... if the hash of the rest of the header doesn't match the hash value you sent in oauth_signature, Twitter knows not to trust the sender or the contents.
EDIT 2.5
I'm moving this from the comment to the answer.
If you check out this line in tweeter.js, you'll see the logic.
var signature = self.oauthSignature(method, path, headerObj, query);
headerObj.oauth_signature = qs.escape(signature);
// concat the header object into a csv string
var header = 'OAuth realm="Twitter API",';
var oauthParts = [];
for (var h in headerObj) {
oauthParts.push(h + '="'+headerObj[h]+'"');
}
header+= oauthParts.join(',');
//...
return header;
This bit of code does as I've explained in EDIT 2, by converting a JSON object into key="value" strings stored in oauthParts[], then joins each element in that array into a single comma-separated string which begins with OAuth realm="Twitter API",
Is there any javascript function, to parse the first line of the http header?
GET /page/?id=173&sessid=mk9sa774 HTTP/1.1
The url is encoded.
I would like to get an object, like this:
{
"method" : "GET",
"url" : "/page/",
"parameters": {
"id" : 173,
"sessid" : "mk9sa774"
}
}
I searched a lot, but I haven't found anything useful.
thanks in advance,
First you can split on spaces:
var lineParts = line.split(' ');
Now you can get the method, unparsed path, and version:
var method = lineParts[0];
var path = lineParts[1];
var version = lineParts[2];
Then you can split up the path into the query string and non-query string parts:
var queryStringIndex = path.indexOf('?');
var url, queryString;
if(queryStringIndex == -1) {
url = path, queryString = '';
}else{
url = path.substring(0, queryStringIndex);
// I believe that technically the query string includes the '?',
// but that's not important for us.
queryString = path.substring(queryStringIndex + 1);
}
If there is a query string, we can then split it up into key=value strings:
var queryStringParts = [];
if(queryStringIndex != -1) {
queryStringParts = queryString.split('&');
}
Then we can unescape them and stuff them into an object:
var parameters = {};
queryStringParts.forEach(function(part) {
var equalsIndex = part.indexOf('=');
var key, value;
if(equalsIndex == -1) {
key = part, value = "";
}else{
key = part.substring(0, equalsIndex);
value = part.substring(equalsIndex + 1);
}
key = decodeURIComponent(key);
value = decodeURIComponent(value);
parameters[key] = value;
});
If you really wanted to, you could then put all that data into an object:
return {
method: method,
url: url,
version: version,
parameters: parameters
};
If you're in a browser environment, that's the only way to do it. If you're using Node.JS, it can deal with the URL parsing for you.