Play Framework: getting foursquare access token - web-services

I am trying to grasp how Play framework handles its web service calls.
This is Foursquare's directions (after 1 and 2):
Your server will make a request for
https://foursquare.com/oauth2/access_token
?client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&grant_type=authorization_code
&redirect_uri=YOUR_REGISTERED_REDIRECT_URI
&code=CODE
The response will be JSON
{ access_token: ACCESS_TOKEN }
And this is my code:
public static Result index() {
String base = "http://foursquare.com/oauth2/authenticate";
String clientId = "?client_id=***";
String responseType = "&response_type=code";
String redirectUri = "&redirect_uri=http://localhost:9000/code";
return redirect(base + clientId + responseType + redirectUri);
}
public static Result code() {
String base = "http://foursquare.com/oauth2/access_token";
String clientId = "?client_id=***";
String clientsecret = "&client_secret=***";
String grantType = "&grant_type=authorization_code";
String redirectUri = "&redirect_uri=http://localhost:9000/json";
String code = "&code=" + request().getQueryString("code");
return redirect(base + clientId + clientsecret + grantType
+ redirectUri + code);
}
There are two things I am curios about:
1) I am redirected to a page with the access token displayed on screen:
URL: https://foursquare.com/oauth2/access_token?client_id=***&client_secret=***&grant_type=authorization_code&redirect_uri=http://localhost:9000/json&code=***
With this displayed:
{"access_token":"***"}
I would have expected to be redirected to http://localhost:9000/json as that was the redirect uri...
2) How do I grab the access token? I have tried using the asynchronous web service calls vis http://www.playframework.com/documentation/2.2.x/JavaWS but I cannot make them work.
My attempt:
String feedUrl = base + clientId + clientsecret + grantType
+ redirectUri + code;
final Promise<Result> resultPromise = WS.url(feedUrl).get().map(
new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok("Feed title:" + response.asJson().findPath("access_token").asText());
}
}
);
return resultPromise;
This gives me an exception: [ConnectException: Connection refused: no further information: foursquare.com/107.23.103.139:80 to http://foursquare.com/oauth2/access_token]
All help is appreciated greatly!

This is the class that I made to get the foursquare access_token and submit a new search to foursquare:
public class Application extends Controller {
static final String HOST_AUTHENTICATE = "foursquare.com/oauth2/authenticate";
static final String HOST_ACCESS_TOKEN = "https://www.foursquare.com/oauth2/access_token";
static final String CLIENT_ID = "***";
static final String REDIRECT_URI = "http://localhost:9000/code";
static final String CLIENT_SECRET = "***";
static final String GRANT_TYPE = "authorization_code";
static final String RESPONSE_TYPE = "code";
static final String FOURSQUARE_API_FRIENDS = "https://api.foursquare.com/v2/users/self/friends";
public static Result index() {
String uri = new URIBuilder().setScheme("https").setHost(HOST_AUTHENTICATE)
.setParameter("client_id", CLIENT_ID).setParameter("response_type", RESPONSE_TYPE)
.setParameter("redirect_uri", REDIRECT_URI).toString();
return redirect(uri);
}
public static Promise<Result> code() {
WSRequestHolder authenticate = WS.url(HOST_ACCESS_TOKEN).setQueryParameter("client_id", CLIENT_ID)
.setQueryParameter("client_secret", CLIENT_SECRET).setQueryParameter("grant_type", GRANT_TYPE)
.setQueryParameter("redirect_uri", REDIRECT_URI)
.setQueryParameter("code", request().getQueryString("code").toString());
final Promise<Result> resultPromise = authenticate.get().flatMap(new Function<WS.Response, Promise<Result>>() {
public Promise<Result> apply(WS.Response response) {
JsonNode json = response.asJson();
return WS.url(FOURSQUARE_API_FRIENDS).setQueryParameter("oauth_token", json.findPath("access_token").asText())
.setQueryParameter("v", "20131108").get().map(new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
return ok(response.asJson());
}
});
}
});
return resultPromise;
}
}

Related

Get token from google cloud platform in salesforce

I am a salesforce developer, our company are planning to extend the service for global users, so we decided to use google translate to improve our customers' experience.
I have read the google api document, however, we met an issue when requesting GCP access token, the tutorial google provided in document which supports different languages, like java, c#, python etc. Since we are suing apex (a type of salesforce platform script), we weren't able to use your library to get GCP token.
Instead, we also checked "OAuth 2.0 for Server Accounts", unfortunately, neither worked from me.
Is there any suggestions?
I got token by below code, and the error I met was caused by special characters encode.
public with sharing class SwitchLanguageByGoogleAPIController {
private static final String ENDPOINT = '**';
private static final String TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token';
private static final String SCOPE = 'https://www.googleapis.com/auth/cloud-platform';
private static final String PROJECT_ID = '**';
private static final String GLOSSARY_ID = '88';
private static final String LOCATION_ID = 'us-central1';
private static final String CLIENT_SECRET = '**';
private static final String PRIVATE_KEY = '**';
private static final String CLIENT_EMAIL = '**';
public static void translateByGlossary() {
Token token = getToken();
HttpRequest request = new HttpRequest();
request.setHeader('Content-Type', 'text/plain');
request.setEndpoint(ENDPOINT + PROJECT_ID + '/locations/' + LOCATION_ID + ':translateText?access_token=' + token.access_token);
request.setMethod('POST');
String contents = 'Personal Information, Middle Name e, first First Name';
String sourceLanguageCode = 'en';
String targetLanguageCode = 'zh';
request.setBody('{"sourceLanguageCode":"' + sourceLanguageCode + '","targetLanguageCode":"' + targetLanguageCode + '","contents":"'+ contents +'","glossaryConfig":{"glossary":"projects/' + PROJECT_ID +'/locations/' + LOCATION_ID + '/glossaries/' + GLOSSARY_ID + '"}}');
HTTP http = new HTTP();
HttpResponse reponse = http.send(request);
System.debug(reponse.getBody());
}
private static Token getToken() {
Http http = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
//Making the call out
req.setEndpoint(TOKEN_ENDPOINT);
req.setMethod('POST');
req.setHeader('Content-Type','application/x-www-form-urlencoded');
string URLEncodedGrantType = encodingUtil.urlEncode('urn:ietf:params:oauth:grant-type:jwt-bearer','UTF-8');
string jwtSigned = generateJWT();
req.setBody('grant_type='+URLEncodedGrantType+'&assertion='+jwtSigned);
res = http.send(req);
system.debug('Response : '+res.getBody());
return (Token)JSON.deserialize(res.getBody(), Token.Class);
}
private static String generateJWT() {
Http http = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
String JWTHeader = '{"typ":"JWT","alg":"RS256"}';
String Base64EncodedJWTHeader = EncodingUtil.base64Encode(Blob.valueOf(JWTHeader));
long issued_at = datetime.now().getTime()/1000;
long expires_at = datetime.now().addHours(1).getTime()/1000;
JWTClaimSet claimSet = new JWTClaimSet();
claimSet.iss = CLIENT_EMAIL;
claimSet.scope = SCOPE;
claimSet.aud = TOKEN_ENDPOINT;
claimSet.iat = issued_at;
claimSet.exp = expires_at;
String strClaimSetJSON = JSON.Serialize(claimSet);
String Base64EncodedClaimset = EncodingUtil.base64Encode(Blob.valueOf(strClaimSetJSON));
system.debug('Base64 Encoded Claimset::'+Base64EncodedClaimset);
Base64EncodedClaimset = PerformPostBase64Encode(Base64EncodedClaimset);
system.debug('persorm post Claimset::'+Base64EncodedClaimset);
string Base64EncodedString = Base64EncodedJWTHeader + '.' + Base64EncodedClaimset;
String algorithmName = 'RSA-SHA256';
Blob privateKey = EncodingUtil.base64Decode(PRIVATE_KEY);
Blob input = Blob.valueOf(Base64EncodedString);
Blob Blobsign = Crypto.sign(algorithmName, input , privateKey);
String base64EncodedSignature = EncodingUtil.base64Encode(Blobsign);
base64EncodedSignature = PerformPostBase64Encode(base64EncodedSignature);
system.debug('Base 64 encoded signature ::'+base64EncodedSignature );
system.debug('Encoded assertion : ' + Base64EncodedString+'.'+base64EncodedSignature);
string URLEncodedUTF8Assertion = encodingUtil.urlEncode(Base64EncodedString+'.'+base64EncodedSignature,'UTF-8');
return URLEncodedUTF8Assertion;
}
public static String PerformPostBase64Encode(String s)
{
s = s.Replace('+', '-');
s = s.Replace('/', '_');
s = s.Split('=')[0];
return s;
}
public class JWTClaimSet
{
public string iss {get;set;}
public string scope {get;set;}
public string aud {get;set;}
public Long exp {get;set;}
public Long iat {get;set;}
}
private class Token{
private String access_token;
private String token_type;
private String expires_in;
}
}

Invoke AWS API Gateway URL in C#

We are trying to call AWS API Gateway from C# Windows Service, for a background job. Which was supposed to trigger API Gateway periodically initialize request?
We used RestSharp to invoke API Endpoint, the class called AwsAuthenticator , which is inherited from RestSharp.Authenticators.IAuthenticator.
But when we invoke API Gateway we received with error as
"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
namespace ConsoleApp3
{
public class AwsAuthenticator : RestSharp.Authenticators.IAuthenticator
{
public string AccessKeyId { get; }
public string AccessKeySecret { get; }
public string Region { get; }
public AwsAuthenticator(string accessKeyId, string accessKeySecret, string region)
{
AccessKeyId = accessKeyId;
AccessKeySecret = accessKeySecret;
Region = region;
}
private static HashSet<string> ignoredHeaders = new HashSet<string>() {
"authorization",
"content-length",
"content-type",
"user-agent"
};
public void Authenticate(RestSharp.IRestClient client, RestSharp.IRestRequest request)
{
DateTime signingDate = DateTime.UtcNow;
SetContentMd5(request);
SetContentSha256(request);
SetHostHeader(request, client);
SetDateHeader(request, signingDate);
SortedDictionary<string, string> headersToSign = GetHeadersToSign(request);
string signedHeaders = GetSignedHeaders(headersToSign);
string canonicalRequest = GetCanonicalRequest(client, request, headersToSign);
byte[] canonicalRequestBytes = System.Text.Encoding.UTF8.GetBytes(canonicalRequest);
string canonicalRequestHash = BytesToHex(ComputeSha256(canonicalRequestBytes));
string stringToSign = GetStringToSign(Region, signingDate, canonicalRequestHash);
byte[] signingKey = GenerateSigningKey(Region, signingDate);
byte[] stringToSignBytes = System.Text.Encoding.UTF8.GetBytes(stringToSign);
byte[] signatureBytes = SignHmac(signingKey, stringToSignBytes);
string signature = BytesToHex(signatureBytes);
string authorization = GetAuthorizationHeader(signedHeaders, signature, signingDate, Region);
request.AddHeader("Authorization", authorization);
}
public string GetCredentialString(DateTime signingDate, string region)
{
return AccessKeyId + "/" + GetScope(region, signingDate);
}
private string GetAuthorizationHeader(string signedHeaders, string signature, DateTime signingDate, string region)
{
return "AWS4-HMAC-SHA256 Credential=" + this.AccessKeyId + "/" + GetScope(region, signingDate) +
", SignedHeaders=" + signedHeaders + ", Signature=" + signature;
}
private string GetSignedHeaders(SortedDictionary<string, string> headersToSign)
{
return string.Join(";", headersToSign.Keys);
}
private byte[] GenerateSigningKey(string region, DateTime signingDate)
{
byte[] formattedDateBytes = System.Text.Encoding.UTF8.GetBytes(signingDate.ToString("yyyMMdd"));
byte[] formattedKeyBytes = System.Text.Encoding.UTF8.GetBytes("AWS4" + this.AccessKeySecret);
byte[] dateKey = SignHmac(formattedKeyBytes, formattedDateBytes);
byte[] regionBytes = System.Text.Encoding.UTF8.GetBytes(region);
byte[] dateRegionKey = SignHmac(dateKey, regionBytes);
byte[] serviceBytes = System.Text.Encoding.UTF8.GetBytes("execute-api");
byte[] dateRegionServiceKey = SignHmac(dateRegionKey, serviceBytes);
byte[] requestBytes = System.Text.Encoding.UTF8.GetBytes("aws4_request");
return SignHmac(dateRegionServiceKey, requestBytes);
}
private byte[] SignHmac(byte[] key, byte[] content)
{
HMACSHA256 hmac = new HMACSHA256(key);
hmac.Initialize();
return hmac.ComputeHash(content);
}
private string GetStringToSign(string region, DateTime signingDate, string canonicalRequestHash)
{
return "AWS4-HMAC-SHA256\n" +
signingDate.ToString("yyyyMMddTHHmmssZ") + "\n" +
GetScope(region, signingDate) + "\n" +
canonicalRequestHash;
}
private string GetScope(string region, DateTime signingDate)
{
string formattedDate = signingDate.ToString("yyyyMMdd");
return formattedDate + "/" + region + "/execute-api/aws4_request";
}
private byte[] ComputeSha256(byte[] body)
{
SHA256 sha256 = SHA256.Create();
return sha256.ComputeHash(body);
}
private string BytesToHex(byte[] checkSum)
{
return BitConverter.ToString(checkSum).Replace("-", string.Empty).ToLower();
}
public string PresignPostSignature(string region, DateTime signingDate, string policyBase64)
{
byte[] signingKey = this.GenerateSigningKey(region, signingDate);
byte[] stringToSignBytes = System.Text.Encoding.UTF8.GetBytes(policyBase64);
byte[] signatureBytes = SignHmac(signingKey, stringToSignBytes);
string signature = BytesToHex(signatureBytes);
return signature;
}
public string PresignURL(RestSharp.IRestClient client, RestSharp.IRestRequest request, int expires)
{
DateTime signingDate = DateTime.UtcNow;
string requestQuery = "";
string path = request.Resource;
requestQuery = "X-Amz-Algorithm=AWS4-HMAC-SHA256&";
requestQuery += "X-Amz-Credential="
+ this.AccessKeyId
+ Uri.EscapeDataString("/" + GetScope(Region, signingDate))
+ "&";
requestQuery += "X-Amz-Date="
+ signingDate.ToString("yyyyMMddTHHmmssZ")
+ "&";
requestQuery += "X-Amz-Expires="
+ expires
+ "&";
requestQuery += "X-Amz-SignedHeaders=host";
string canonicalRequest = GetPresignCanonicalRequest(client, request, requestQuery);
byte[] canonicalRequestBytes = System.Text.Encoding.UTF8.GetBytes(canonicalRequest);
string canonicalRequestHash = BytesToHex(ComputeSha256(canonicalRequestBytes));
string stringToSign = GetStringToSign(Region, signingDate, canonicalRequestHash);
byte[] signingKey = GenerateSigningKey(Region, signingDate);
byte[] stringToSignBytes = System.Text.Encoding.UTF8.GetBytes(stringToSign);
byte[] signatureBytes = SignHmac(signingKey, stringToSignBytes);
string signature = BytesToHex(signatureBytes);
// Return presigned url.
return client.BaseUrl + path + "?" + requestQuery + "&X-Amz-Signature=" + signature;
}
private string GetPresignCanonicalRequest(RestSharp.IRestClient client, RestSharp.IRestRequest request, string requestQuery)
{
LinkedList<string> canonicalStringList = new LinkedList<string>();
canonicalStringList.AddLast(request.Method.ToString());
string path = request.Resource;
if (!path.StartsWith("/"))
{
path = "/" + path;
}
canonicalStringList.AddLast(path);
canonicalStringList.AddLast(requestQuery);
canonicalStringList.AddLast("host:" + client.BaseUrl.Host);
canonicalStringList.AddLast("");
canonicalStringList.AddLast("host");
canonicalStringList.AddLast("UNSIGNED-PAYLOAD");
return string.Join("\n", canonicalStringList);
}
private string GetCanonicalRequest(RestSharp.IRestClient client, RestSharp.IRestRequest request,
SortedDictionary<string, string> headersToSign)
{
LinkedList<string> canonicalStringList = new LinkedList<string>();
canonicalStringList.AddLast(request.Method.ToString());
string[] path = request.Resource.Split(new char[] { '?' }, 2);
if (!path[0].StartsWith("/"))
{
path[0] = "/" + path[0];
}
canonicalStringList.AddLast(path[0]);
string query = "";
if (path.Length == 2)
{
var parameterString = path[1];
var parameterList = parameterString.Split('&');
SortedSet<string> sortedQueries = new SortedSet<string>();
foreach (string individualParameterString in parameterList)
{
if (individualParameterString.Contains('='))
{
string[] splitQuery = individualParameterString.Split(new char[] { '=' }, 2);
sortedQueries.Add(splitQuery[0] + "=" + splitQuery[1]);
}
else
{
sortedQueries.Add(individualParameterString + "=");
}
}
query = string.Join("&", sortedQueries);
}
canonicalStringList.AddLast(query);
foreach (string header in headersToSign.Keys)
{
canonicalStringList.AddLast(header + ":" + headersToSign[header]);
}
canonicalStringList.AddLast("");
canonicalStringList.AddLast(string.Join(";", headersToSign.Keys));
if (headersToSign.Keys.Contains("x-amz-content-sha256"))
{
canonicalStringList.AddLast(headersToSign["x-amz-content-sha256"]);
}
else
{
canonicalStringList.AddLast("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
}
return string.Join("\n", canonicalStringList);
}
private SortedDictionary<string, string> GetHeadersToSign(RestSharp.IRestRequest request)
{
var headers = request.Parameters.Where(p => p.Type.Equals(RestSharp.ParameterType.HttpHeader)).ToList();
SortedDictionary<string, string> sortedHeaders = new SortedDictionary<string, string>();
foreach (var header in headers)
{
string headerName = header.Name.ToLower();
string headerValue = header.Value.ToString();
if (!ignoredHeaders.Contains(headerName))
{
sortedHeaders.Add(headerName, headerValue);
}
}
return sortedHeaders;
}
private void SetDateHeader(RestSharp.IRestRequest request, DateTime signingDate)
{
request.AddHeader("x-amz-date", signingDate.ToString("yyyyMMddTHHmmssZ"));
}
private void SetHostHeader(RestSharp.IRestRequest request, RestSharp.IRestClient client)
{
request.AddHeader("Host", client.BaseUrl.Host + (client.BaseUrl.Port != 80 ? ":" + client.BaseUrl.Port : string.Empty));
}
private void SetContentSha256(RestSharp.IRestRequest request)
{
if (request.Method == RestSharp.Method.PUT || request.Method.Equals(RestSharp.Method.POST))
{
var bodyParameter = request.Parameters.Where(p => p.Type.Equals(RestSharp.ParameterType.RequestBody)).FirstOrDefault();
if (bodyParameter == null)
{
request.AddHeader("x-amz-content-sha256", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
return;
}
byte[] body = null;
if (bodyParameter.Value is string)
{
body = System.Text.Encoding.UTF8.GetBytes(bodyParameter.Value as string);
}
if (bodyParameter.Value is byte[])
{
body = bodyParameter.Value as byte[];
}
if (body == null)
{
body = new byte[0];
}
SHA256 sha256 = System.Security.Cryptography.SHA256.Create();
byte[] hash = sha256.ComputeHash(body);
string hex = BitConverter.ToString(hash).Replace("-", string.Empty).ToLower();
request.AddHeader("x-amz-content-sha256", hex);
}
else
{
request.AddHeader("x-amz-content-sha256", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
}
}
private void SetContentMd5(RestSharp.IRestRequest request)
{
if (request.Method == RestSharp.Method.PUT || request.Method.Equals(RestSharp.Method.POST))
{
var bodyParameter = request.Parameters.Where(p => p.Type.Equals(RestSharp.ParameterType.RequestBody)).FirstOrDefault();
if (bodyParameter == null)
{
return;
}
byte[] body = null;
if (bodyParameter.Value is string)
{
body = System.Text.Encoding.UTF8.GetBytes(bodyParameter.Value as string);
}
if (bodyParameter.Value is byte[])
{
body = bodyParameter.Value as byte[];
}
if (body == null)
{
body = new byte[0];
}
MD5 md5 = MD5.Create();
byte[] hash = md5.ComputeHash(body);
string base64 = Convert.ToBase64String(hash);
request.AddHeader("Content-MD5", base64);
}
}
}
////////////////////////
public class MainClass
{
public void Execute()
{
var client = new RestClient("https://nm47849kod.execute-api.ap-southeast1.amazonaws.com/samplegateway/");
var request = new RestRequest("/", Method.POST);
var postData = new { Mode = 4 };
request.AddParameter("application/json",JsonConvert.SerializeObject(postData),ParameterType.RequestBody); AwsAuthenticator awsAuthenticator = new AwsAuthenticator("AccessKeyXXXXX", "SECKEYxxxx12313123123123123", "apsoutheast-1");
awsAuthenticator.Authenticate(client,request);
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
Console.WriteLine(content);
Console.ReadLine();
}
}
Error Details:
{"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been\n'POST\n/samplegateway/\n\ncontent-md5:rkT7BbUvFInBgrPCuA0UZw==\nhost:nm47849kod.execute-api.ap-southeast-1.amazonaws.com\nx-amz-content-sha256:0318f62547c9078687e73f987ec26fa557047b67f54bb99b8047c950990ae42c\nx-amz-date:20190601T102835Z\n\ncontent-md5;host;x-amz-content-sha256;x-amz-date\n0318f62547c9078687e73f987ec26fa557047b67f54bb99b8047c950990ae42c'\n\nThe String-to-Sign should have been\n'AWS4-HMAC-SHA256\n20190601T102835Z\n20190601/ap-southeast-1/execute-api/aws4_request\n8f89bd5010655fb26a8de5e29d48d6129ac7875e5eb6bc2faeb8e41864b4d49e'\n"}.
We identified the problem.
Below is the working code and this resolves my issue. I am sharing this so that the group can get benefitted. The above class is entirely rewritten and when invoked it worked.
public class ApiRequest
{
private const string ServiceName = "execute-api";
private const string Algorithm = "AWS4-HMAC-SHA256";
private const string ContentType = "application/json";
private const string SignedHeaders = "content-type;host;x-amz-date;x-api-key";
private const string DateTimeFormat = "yyyyMMddTHHmmssZ";
private const string DateFormat = "yyyyMMdd";
public AwsApiGatewayRequest AwsApiGatewayRequest;
public ApiRequest(AwsApiGatewayRequest request)
{
AwsApiGatewayRequest = request;
if (string.IsNullOrEmpty(AwsApiGatewayRequest.RequestMethod))
AwsApiGatewayRequest.RequestMethod = "POST";
if (string.IsNullOrEmpty(AwsApiGatewayRequest.xApiKey))
AwsApiGatewayRequest.xApiKey = "";
}
public WebResponse GetPostResponse()
{
var request = GetPostRequest();
return request.GetResponse();
}
public WebRequest GetPostRequest()
{
string hashedRequestPayload = CreateRequestPayload(AwsApiGatewayRequest.JsonData);
string authorization = Sign(hashedRequestPayload, AwsApiGatewayRequest.RequestMethod, AwsApiGatewayRequest.AbsolutePath, AwsApiGatewayRequest.QueryString);
string requestDate = DateTime.UtcNow.ToString(DateTimeFormat);
var webRequest = WebRequest.Create($"https://{AwsApiGatewayRequest.Host}{AwsApiGatewayRequest.AbsolutePath}");
webRequest.Timeout = AwsApiGatewayRequest.RequestTimeout.HasValue ? AwsApiGatewayRequest.RequestTimeout.Value : 50000;
webRequest.Method = AwsApiGatewayRequest.RequestMethod;
webRequest.ContentType = ContentType;
webRequest.Headers.Add("X-Amz-date", requestDate);
webRequest.Headers.Add("Authorization", authorization);
webRequest.Headers.Add("x-amz-content-sha256", hashedRequestPayload);
if (!string.IsNullOrEmpty(AwsApiGatewayRequest.AdditionalHeaders))
{
// parse apart and apply the additional headers
string[] headers = AwsApiGatewayRequest.AdditionalHeaders.Split(';');
foreach (string header in headers)
{
var headervalue = header.Split('=');
if (headervalue.Count() == 2)
webRequest.Headers.Add(headervalue[0], headervalue[1]);
}
}
if (!string.IsNullOrEmpty(AwsApiGatewayRequest.SessionToken))
webRequest.Headers.Add("X-Amz-Security-Token", AwsApiGatewayRequest.SessionToken);
webRequest.ContentLength = AwsApiGatewayRequest.JsonData.Length;
var encoding = new ASCIIEncoding();
var data = encoding.GetBytes(AwsApiGatewayRequest.JsonData);
using (var newStream = webRequest.GetRequestStream())
{
newStream.Write(data, 0, data.Length);
newStream.Close();
}
return webRequest;
}
private string CreateRequestPayload(string jsonString)
{
return HexEncode(Hash(ToBytes(jsonString)));
}
private string Sign(string hashedRequestPayload, string requestMethod, string canonicalUri, string canonicalQueryString)
{
var currentDateTime = DateTime.UtcNow;
var dateStamp = currentDateTime.ToString(DateFormat);
var requestDate = currentDateTime.ToString(DateTimeFormat);
var credentialScope = $"{dateStamp}/{AwsApiGatewayRequest.RegionName}/{ServiceName}/aws4_request";
var headers = new SortedDictionary<string, string> {
{ "content-type", ContentType },
{ "host", AwsApiGatewayRequest.Host },
{ "x-amz-date", requestDate },
{ "x-api-key", AwsApiGatewayRequest.xApiKey }
};
var canonicalHeaders = string.Join("\n", headers.Select(x => x.Key.ToLowerInvariant() + ":" + x.Value.Trim())) + "\n";
// Task 1: Create a Canonical Request For Signature Version 4
var canonicalRequest = $"{requestMethod}\n{canonicalUri}\n{canonicalQueryString}\n{canonicalHeaders}\n{SignedHeaders}\n{hashedRequestPayload}";
var hashedCanonicalRequest = HexEncode(Hash(ToBytes(canonicalRequest)));
// Task 2: Create a String to Sign for Signature Version 4
var stringToSign = $"{Algorithm}\n{requestDate}\n{credentialScope}\n{hashedCanonicalRequest}";
// Task 3: Calculate the AWS Signature Version 4
var signingKey = GetSignatureKey(AwsApiGatewayRequest.SecretKey, dateStamp, AwsApiGatewayRequest.RegionName, ServiceName);
var signature = HexEncode(HmacSha256(stringToSign, signingKey));
// Task 4: Prepare a signed request
// Authorization: algorithm Credential=access key ID/credential scope, SignedHeadaers=SignedHeaders, Signature=signature
var authorization = $"{Algorithm} Credential={AwsApiGatewayRequest.AccessKey}/{dateStamp}/{AwsApiGatewayRequest.RegionName}/{ServiceName}/aws4_request, SignedHeaders={SignedHeaders}, Signature={signature}";
return authorization;
}
private byte[] GetSignatureKey(string key, string dateStamp, string regionName, string serviceName)
{
var kDate = HmacSha256(dateStamp, ToBytes("AWS4" + key));
var kRegion = HmacSha256(regionName, kDate);
var kService = HmacSha256(serviceName, kRegion);
return HmacSha256("aws4_request", kService);
}
private byte[] ToBytes(string str)
{
return Encoding.UTF8.GetBytes(str.ToCharArray());
}
private string HexEncode(byte[] bytes)
{
return BitConverter.ToString(bytes).Replace("-", string.Empty).ToLowerInvariant();
}
private byte[] Hash(byte[] bytes)
{
return SHA256.Create().ComputeHash(bytes);
}
private byte[] HmacSha256(string data, byte[] key)
{
return new HMACSHA256(key).ComputeHash(ToBytes(data));
}
}
Execution Parameter:
var request = new AwsApiGatewayRequest()
{
RegionName = "",
Host = ,
AccessKey = "",
SecretKey = "",
RequestMethod = "POST",
AbsolutePath = ,
JsonData = "{\"Mode\":\"4\"}",
SessionToken = ""
};//Invoke this using RestClient...
The problem here is we failed to add an additional header which was required by AWS. In this version, we have added hence it rectified.
Thanks for your support.

How to do http request for POST methord (rest api url created by aws apigateway) from android using volly

How to send a proper http request from android using volly for a post REST URL created with using aws api gateway?
How to make a proper http request from android so that these values accept by api gateway.
Api gateway internal testing works properly.
This is the parameter need to pass through the request.
{
"id": "22",
"res": "10",
"rate": "75",
"index": "1"
}
//this method is used call http request
public static void newPost2(Context context){
String awsAccessKey = "awsAccessKey";
final String awsSecretKey = "awsSecretKey";
String dateStr = ClientSSLSocketFactory.getServerTime();
String scope = dateStr + "/us-east-1/execute-api/aws4_request,";
String headerNames = "host;x-amz-date";
final String credentialsAuthorizationHeader = "Credential=" + awsAccessKey + "/" + scope;
String signedHeadersAuthorizationHeader = "SignedHeaders=" + headerNames;
String signatureAuthorizationHeader = "Signature=" + "hex encoded signature";
final String authorization = "AWS4-HMAC-SHA256 "
+ credentialsAuthorizationHeader + ", "
+ signedHeadersAuthorizationHeader + ", "
+ signatureAuthorizationHeader;
final String url="https://xxxxxxx2.execute-api.us-east-1.amazoxxxxxxxxxxxxxxxx";
RequestQueue queue = Volley.newRequestQueue(context);
StringRequest sr = new StringRequest(Request.Method.POST,url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// mPostCommentResponse.requestCompleted();
System.out.print("\n\n\n......post ok."+response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// mPostCommentResponse.requestEndedWithError(error);
System.out.print("\n\n\n.......post error."+error);
error.printStackTrace();
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
// params.put("Content-Type", "application/json; charset=utf-8");
params.put("id","22");
params.put("rate","10");
params.put("res", "75");
params.put("index","1");
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
// params.put("Content-Type","application/x-www-form-urlencoded");
params.put("Host", "apigateway.us-east-1.amazonaws.com");
params.put("x-amz-date", ClientSSLSocketFactory.getawsnettime());
params.put("Authorization", authorization);
params.put("Content-Type", "application/x-amz-json-1.0");
return params;
}
};
queue.add(sr);
}
but shows error in log
...stringr..header......post error.com.android.volley.AuthFailureError
11-30 14:52:14.140 4663-4663/com.example.acernrc.noveleven W/System.err: com.android.volley.ServerError
11-30 14:52:14.140 4663-4663/com.example.acernrc.noveleven W/System.err: at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:163)

Pass field from Droid project to PCL, Xamarin.Forms

I have an app that allows users to log in via facebook, once user enters their credentials - My api request saves the user onto the database and auto-generates a user token(This is unique to each user). In order to display user specific details once user logs in - the token needs to be referenced. I am trying to get this token to the PCL project but it returns null just for the token. When I tried passing another string like name, it passes the correct value. Any help will be much appreciated.Thanks
FacebookRender in droid:
public class FacebookRender : PageRenderer
{
public FacebookRender()
{
CustomerService customerService = new CustomerService();
String error;
var activity = this.Context as Activity;
var auth = new OAuth2Authenticator(
clientId: "",
scope: "",
authorizeUrl: new Uri("https://www.facebook.com/dialog/oauth/"),
redirectUrl: new Uri("https://www.facebook.com/connect/login_success.html")
);
auth.Completed += async (sender, eventArgs) =>
{
try
{
if (eventArgs.IsAuthenticated)
{
await AccountStore.Create().SaveAsync(eventArgs.Account, "FacebookProviderKey");
var accessToken = eventArgs.Account.Properties["access_token"].ToString();
var expiresIn = Convert.ToDouble(eventArgs.Account.Properties["expires_in"]);
var expiryDate = DateTime.Now + TimeSpan.FromSeconds(expiresIn);
var request = new OAuth2Request("GET", new Uri("https://graph.facebook.com/me?fields=email,first_name,last_name,gender,picture"), null, eventArgs.Account);
var response = await request.GetResponseAsync();
var obj = JObject.Parse(response.GetResponseText());
var id = obj["id"].ToString().Replace("\"", "");
var name = obj["first_name"].ToString().Replace("\"", "");
var surname = obj["last_name"].ToString().Replace("\"", "");
var gender = obj["gender"].ToString().Replace("\"", "");
//var email = obj["email"].ToString().Replace("\"", "");
Customer.Customers cust = new Customer.Customers();
cust.Credentials = new Customer.Credentials();
cust.Name = name;
cust.Surname = surname;
cust.Email = "";
cust.MobilePhone = "";
cust.DOB = DateTime.Now;
cust.Number = "";
cust.City = "";
cust.Region = "";
cust.Country = "";
cust.DeviceToken = "sample";
cust.Credentials.SecretKey = "";
await customerService.AddCustomer(cust);
App.SaveToken(cust.Credentials.Token); - **//This is where I am passing the token**
App.NavigateToProfile(string.Format(name + surname));
}
else
{
App.NavigateToProfile("Invalid Login");
}
}
catch(Exception ex)
{
error = ex.Message;
}
};
activity.StartActivity(auth.GetUI(activity));
}
App.cs
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
public static void NavigateToProfile(string message)
{
App.Current.MainPage = (new Profile(message));
}
static string _Token;
public static string Token
{
get { return _Token; }
}
public static void SaveToken(string token)
{
_Token = token;
}
AboutPage.cs - I am passing the token in a label just to see if it's passing
public partial class About : ContentPage
{
private Label _lbltoken;
public About()
{
//InitializeComponent();
Appearing += (object s, EventArgs a) => {
_lbltoken.Text = App.Token;
};
string tk = App.Token;
_lbltoken = new Label()
{
FontSize = 20,
HorizontalOptions = LayoutOptions.CenterAndExpand,
Text = tk,
};
var stack = new StackLayout
{
VerticalOptions = LayoutOptions.StartAndExpand,
Children = { _lbltoken },
};
Content = stack;
}
}
You can use the MessagingCenter.
Messages may be sent as a result like a button click, a system event or some other incident. Subscribers might be listening in order to change the appearance of the user interface, save data or trigger some other operation.
More Info
I don't really now if its good idea use static fields in App class. Xamarin access all fields with service locator, App.Current.[property] I will suggest you try to change these fields to public
string _Token;
public string Token
{
get { return _Token; }
}
public void SaveToken(string token)
{
_Token = token;
}
and use it with App.Current.SaveToken(token) or App.Current.Token

Get the AccessToken of Facebook without login using HttpWebRequest for WP8

I am trying to get the accesstoken like this,
string uri = "https://graph.facebook.com/oauth/access_token?client_id=" +
APP_ID +
"&redirect_uri=&client_secret=" + APP_SECRET + "&grant_type=client_credentials";
var access_token = GetMyData(uri);
public async Task<string> GetMyData(string urlToCall)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToCall);
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
using (var sr = new StreamReader(response.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
{
var taskComplete = new TaskCompletionSource<HttpWebResponse>();
request.BeginGetResponse(asyncResponse =>
{
try
{
HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
taskComplete.TrySetResult(someResponse);
}
catch (WebException webExc)
{
HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
taskComplete.TrySetResult(failedResponse);
}
}, request);
return taskComplete.Task;
}
It gets stuck in the var taskComplete = new TaskCompletionSource(); and takes a lot of time and does not get the accesstoken also.what is wrong?
You can probably achieve this with the following code
public void GetMyData(string urlToCall)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(urlToCall);
request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallback), request);
}
private static void ReadWebRequestCallback(IAsyncResult callbackResult)
{
HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
HttpWebResponse myResponse = (HttpWebResponse)myRequest.EndGetResponse(callbackResult);
using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
{
// Here you get the result
string results = httpwebStreamReader.ReadToEnd();
}
myResponse.Close();
}