I am implementing an api key for a basic web service I have. I am using an implementation found here: https://blogs.msdn.microsoft.com/rjacobs/2010/06/14/how-to-do-api-key-verification-for-rest-services-in-net-4/
I know I have it all implemented and setup correctly on the service side but I am not sure how to pass the API key from my client. When I debug the web service upon request I don't get anything returned for my HttpRequestMessage query string. Here is code:
Web service auth manager:
public string GetAPIKey(OperationContext oc)
{
// get the request
var request = oc.RequestContext.RequestMessage;
// get HTTP request message
var requestProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
// get the actual query string
NameValueCollection queryParams = HttpUtility.ParseQueryString(requestProp.QueryString);
// return APIKey if there, NameValueCollection returns null if not present
return queryParams[APIKEY];
}
Client consumption (the part that matters):
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/json");
client.Headers.Add("APIKey","my_generated_key");
client.Encoding = Encoding.UTF8;
Console.WriteLine(client.UploadString("http://my_local_host/my.svc/myCall", "POST", data));
}
During debug, the web service is always getting empty queryParams in the NameValueCollection because the query string is empty. How do I add to that query string during the request made from the client?
Solved. The solution was to not try to pull from the HttpRequestMessageProprty.QueryString but to just pull from the headers.
Code:
public string GetAPIKey(OperationContext oc)
{
// get the request
var request = oc.RequestContext.RequestMessage;
// get HTTP request message
var requestProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
// get the actual query string
NameValueCollection queryParams = requestProp.Headers;
// return APIKey if there, NameValueCollection returns null if not present
return queryParams["APIKey"];
}
Related
I've written multiple REST Endpoints in my Controller [GET, POST and PUT].
GET and POST calls are working fine. But when I try to hit PUT request from Postman, my java controller is not able to receive that request. There is no error message. Response body is empty. Response code in Postman is 200, OK.
Here is my PUT Endpoint which is not able to get request from Postman:
#PutMapping(value = "/devRegistration")
public Object deviceRegistration(HttpServletRequest httpRequest,
#RequestBody(required = false) Map<String, Object> jsonBody ){
ResponseEntity<Object> response = null;
System.out.println("jsonBody = "+jsonBody);
devService.deviceRegistration(httpRequest, jsonBody);
return response;
}
Here is my GET Endpoint which is working fine:
#GetMapping(value = "/checkRegistration")
public void checkRegistration(HttpServletRequest httpRequest,
#RequestParam("appId") String appId, #RequestParam("offset") String offset ){
Map<String, Object> jsonBody = new HashMap<String, Object>();
jsonBody.put("appId", appId);
jsonBody.put("offset", offset);
service.checkRegistration(httpRequest, jsonBody);
}
Postman URL with Headers and Body for PUT request is :
https://localhost:8443/api/device/devRegistration
In Body:
app_Id : some value
offset : some value
Headers are:
RequestHeader
Content-Type
Authorization
MobileHeader
SessionToken
But, System.out.println() is not being executed in PUT Endpoint.
Let me know, if any other info. is required.
I found the answer.
Actually, I need to pass the params in the Body as raw form instead of form-data in Postman.
It worked now.
I am writing a REST client in C#.Net using RestSharp. There are two API calls - one is "Auth" call and second is "getKey" call. The "Auth" call throws back a "Auth token"in the response, and I'd like to parse that token from the response, and pass it as an header to the second "getkey" call. Please advise with examples
I have given some sample to achieve your scenario. Please use the below example and do the modification as per your requirement.
RestUtils Class:
Add the Request Header, If your application is expected some additional headers.
class RestUtils
{
private static readonly RestClient _restClient = new RestClient();
public static void SetBaseURL(String host)
{
_restClient.BaseUrl = new Uri(host);
}
public static string GetResponse(String endpoint, String token)
{
var request = new RestRequest(endpoint, Method.GET);
request.AddHeader("Accept", "application/json");
request.AddHeader("Authorization", token);
IRestResponse response = _restClient.Execute(request);
return response.Content;
}
public static string GetToken(String endpoint)
{
var request = new RestRequest(endpoint, Method.GET);
request.AddHeader("Accept", "application/json");
IRestResponse response = _restClient.Execute(request);
return response.Content;
}
}
TestClass:
In your test class you can add the below steps and you can get the result as expected. First two lines will be executed and give the authentication token as output. So, you can use the retrieved token in the subsequent lines for other API. In another way, you can create one property class and set the retrieved token value .So, that you can access the token from various class.
//Specify the Base URI of your Token Specific API
RestUtils.SetBaseURL("https://login.microsoftonline.com/");
//Specify the End Point of your Token Specific API
String token = RestUtils.GetToken("/oauth2/token");
//Specify the Base URI of your actual Test API
RestUtils.SetBaseURL("XXXXXXX");
String response = RestUtils.GetResponse(token);
I try to use Windows Azure like a Storage fom Salesforce.com.
I cheked the documentation and I only can see call the calls to azure rest api from SDK (Java, .Net, JS, etc) examples.
I need integrate Salesforce with Windows Azure Storage but, Azure don't have a SDK for Salesforce.com
From Salesforce.com is allow the calls to rest services but the process to call Azure Rest Services require one o more librarys.
Exameple:
Authentication for the Azure Storage Services require of:
Headers: Date Header and Authorization Header
The Authorization Header require two elments
SharedKey
Account Name
Authorization="[SharedKey|SharedKeyLite] :"
SharedKey and Account Name give a conversion:
HMAC-SHA256 conversion
over UTF-8 encoded
For this convertion the documentation referes to SDK Librarys in others words Java Class or .Net Class type helper that in Salesforce.com not exist.
Please, I need a example to call the authentification service without sdk
Sorry for my bad English.
Visit: https://learn.microsoft.com/en-us/rest/api/storageservices/fileservices/authentication-for-the-azure-storage-services
I need a example to call the authentification service without sdk
We could generate signature string and specify Authorization header for the request of performing Azure storage services without installing SDK. Here is a simple working sample to list the containers, you could refer to my generateAuthorizationHeader function and Authentication for the Azure Storage Services to construct the signature string.
string StorageAccount = "mystorageaccount";
string StorageKey = "my storage key";
string requestMethod = "GET";
string mxdate = "";
string storageServiceVersion = "2014-02-14";
protected void btnlist_Click(object sender, EventArgs e)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(string.Format(CultureInfo.InvariantCulture,
"https://{0}.blob.core.windows.net/?comp=list",
StorageAccount
));
req.Method = requestMethod;
//specify request header
string AuthorizationHeader = generateAuthorizationHeader();
req.Headers.Add("Authorization", AuthorizationHeader);
req.Headers.Add("x-ms-date", mxdate);
req.Headers.Add("x-ms-version", storageServiceVersion);
using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
{
var stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string content = reader.ReadToEnd();
StringReader theReader = new StringReader(content);
DataSet theDataSet = new DataSet();
theDataSet.ReadXml(theReader);
DataTable dt = theDataSet.Tables[2];
}
}
public string generateAuthorizationHeader()
{
mxdate = DateTime.UtcNow.ToString("R");
string canonicalizedHeaders = string.Format(
"x-ms-date:{0}\nx-ms-version:{1}",
mxdate,
storageServiceVersion);
string canonicalizedResource = string.Format("/{0}/\ncomp:list", StorageAccount);
string stringToSign = string.Format(
"{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}",
requestMethod,
canonicalizedHeaders,
canonicalizedResource);
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(StorageKey));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
String authorization = String.Format("{0} {1}:{2}",
"SharedKey",
StorageAccount,
signature
);
return authorization;
}
Besides, please refer to Azure Storage Services REST API Reference to know more about programmatic access to Azure Storage Services via REST APIs.
I find a way to solve this.
You should use Shared Sing, here explain me:
Enter to Portal Azure
Open the Account Storage
In the General Information click on "Share sing access"
Enable all permissions that you need (In my case only Enable "File")
Enable all resources permission that you need (In my case onl Enable "Service, Container and Object")
Define and Start Date and End Date (This is the space of time that Shared Key will be valid)
Define protocol type (In my case use HTTPS)
Clic on "Generate SAS" button
After this process you will get a token like this:
?sv=2016-05-31&ss=f&srt=sco&sp=rwdlc&se=2017-11-28T04:29:49Z&st=2017-02-18T20:29:49Z&spr=https&sig=rt7Loxo1MHGJqp0F6ryLhYAmOdRreyiYT418ybDN2OI%3D
You have to use this Token like Autentication
Example Call Code List a Content:
public with sharing class CallAzureRestDemo {
public string token = '&sv=2016-05-31&ss=f&srt=sco&sp=rwdlc&se=2017-02-19T04:00:44Z&st=2017-02-18T20:00:44Z&spr=https&sig=GTWGQc5GOAvQ0BIMxMbwUpgag5AmUVjrfZc56nHkhjI%3D';
//public Integer batchSize;
public CallAzureRestDemo(){}
public void getlistcontent(String endpoint)
{
// Create HTTP GET request
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint(endpoint+token);
Http http = new Http();
HTTPResponse res;
System.debug(LoggingLevel.INFO, '##RESPONSE: '+res);
// only do this if not running in a test method
if(!Test.isRunningTest())
{
System.debug(LoggingLevel.INFO, 'Sending the message to Azure');
res = http.send(req);
System.debug(LoggingLevel.INFO, 'http.send result status: ' + res.getStatus());
}
else
{
System.debug(LoggingLevel.INFO, 'Running in a test so not sending the message to Azure');
}
}
}
Example TestMethod:
#isTest
private class Test_CallAzureRestDemo {
static testMethod void myUnitTest() {
CallAzureRestDemo oRest = new CallAzureRestDemo();
try{
//Call the method and set endpoint
oRest.getlistcontent('https://accountstoragecomex.file.core.windows.net/?comp=list');
}catch(Exception e){
System.debug('##'+e);
}
}
}
Example to Response:
20:15:47.64 (79388244)|CALLOUT_REQUEST|[100]|System.HttpRequest[Endpoint=https://accountstoragecomex.file.core.windows.net/?comp=list&sv=2016-05-31&ss=f&srt=sco&sp=rwdlc&se=2017-02-19T04:00:44Z&st=2017-02-18T20:00:44Z&spr=https&sig=GTWGQc5GOAvQ0BIMxMbwUpgag5AmUVjrfZc56nHkhjI%3D, Method=GET]
20:15:47.64 (395755012)|CALLOUT_RESPONSE|[100]|System.HttpResponse[Status=OK, StatusCode=200]
Example Call Service "FILE - Get List Share"
Call To List Content
One more time, Sorry for my bad english.
I am attempting to get eBay product IDs using the GetOffers request by sending it a product SKU.
My code is below, the problem I am currently having is that when I try to test this code is returns a 401 unauthorized. It's not returning any specific error code or anything descriptive.
I know my access token is valid I can't find any good examples on how to use this request.
public string getEbayOffers(string sku)
{
HttpResponseMessage response;
string accessToken = "tokenhere";
string param = Convert.ToBase64String(Encoding.ASCII.GetBytes(accessToken));
string url = $"sell/inventory/v1/offer?sku={sku}";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://api.ebay.com/");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", param);
response = client.GetAsync(url).Result;
}
if (response.IsSuccessStatusCode)
{
return response.Content.ReadAsStringAsync().Result;
}
return null;
}
No need to convert your token to base64. The correct format should be "Bearer YOUR_USER_TOKEN". Replace YOUR_USER_TOKEN with your own token string.
Access token should be enough for getting offers but maybe you can try to use user token if above doesn't work.
The Sharepoint Rest API uses a simple URL of the type http://mysite/_api/search/query?querytext='search_key' to return search results as an XML. When I run this directly in a browser, I see a valid XML response:
(1) Am I right in assuming the above response is generated using the current user's authorization?
(2) Can this URL be invoked from server side? I tried it in a web method (WCF web service), but received a 401 - Unauthorized:
public string GetSearchResults(string searchKey)
{
string webURL = SPContext.Current.Web.Url;
string searchURL = webURL + "/_api/search/query?querytext='" + searchKey + "'";
WebClient client = new WebClient();
string xmlResponse = client.DownloadString(searchURL); // throws 401
// parse xmlResponse and return appropriately
}
(3) What I really need is to be able to get the search results irrespective of the current user's access rights (the requirement is that users will see all search results, with an option to "request access" when needed).
I tried this in the above web method, but it still throws the same 401:
public string GetSearchResults(string searchKey)
{
string webURL = SPContext.Current.Web.Url;
string searchURL = webURL + "/_api/search/query?querytext='" + searchKey + "'";
string xmlResponse;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
WebClient client = new WebClient();
xmlResponse = client.DownloadString(searchURL); // still 401
});
// parse xmlResponse and return appropriately
}
What is the right way to invoke the Rest URL from server side? Specifically, from a web method? And how can it be run as super user?
In order to perform REST request, authenticate the request via WebClient.Credentials Property
On Premise (your scenario)
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(userName,password,domain);
SharePoint Online
WebClient client = new WebClient();
client.Credentials = new SharePointOnlineCredentials(username,securedPassword);
client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
Search results are always security trimmed by SharePoint so to make this work, you'd need to run your query after specifying new credentials as mentioned by Vadim. This is almost certainly not a good idea. If you're running code server side already, don't use the REST interface, just query directly using the search API.