I'm doing a PayPal Express Checkout on my ASP.Net MVC site.
The site uses token authentication so I'm trying to put the token on the PayPal return URL as a query parameter.
I have a handler that intercepts all requests to my site and extracts the token from the URL or the request header.
Works fine getting it from the header but I get the following exception when its a query parameter. I get the token from my claims principal and don't do any encoding/decoding. I've tried this method but had no luck (same exception occurs).
System.ArgumentException was caught
HResult=-2147024809
Message=Jwt10204: 'System.IdentityModel.Tokens.JwtSecurityTokenHandler' cannot read this string: '{really long token}'.
The string needs to be in compact JSON format, which is of the form: '<Base64UrlEncodedHeader>.<Base64UrlEndcodedPayload>.<OPTIONAL, Base64UrlEncodedSignature>'.
Source=System.IdentityModel.Tokens.Jwt
StackTrace:
at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ReadToken(String jwtEncodedString)
at {our namespace}.Providers.JwtTokenServiceProvider.GetToken(String value)
at {our namespace}.TokenAuthorisationController.Post(TokenRequest request)
Turns out the problem was that PayPal appending another string (that look like a PayPal Express Checkout token) on then end of the URL with a comma as a delimiter instead of the "&" symbol.
So I solved the issue by removing the comma character and the extra characters after the comma to extra my JWT token.
Related
I'm integrating PayU API service in my web (.NET MVC Core 2.1) application.
After client pays order, PayU sends notification confirmation as POST request to my api method.
Example of PayU confirmation notification.
In heareds notification placed MD5 signature.
OpenPayu-Signature:
sender=checkout;
signature=c33a38d89fb60f873c039fcec3a14743;
algorithm=MD5;
content=DOCUMENT
string incoming_signature = c33a38d89fb60f873c039fcec3a14743;
What I supposed to do to verify that notification:
Here is instruction to verify notification signature.
1.Combine the body of the incoming notification with the value of second_key(second key is avaliable in my account page in payu ):
string concatenated = JSONnotification + second_key;
2.Select an expected signature value by applying the hashing function (e.g. md5) in the received chain of characters:
string expected_signature = md5(concatenated)
3.Compare the strings: expected_signature and incoming_signature:
bool signature_is_correct = (expected_signature == incoming_signature);
Problem is checksums is not matching.
I Handle this notification in my controller method:
[HttpPost]
[AllowAnonymous]
[Route("notify")]
public IActionResult TransactionConfirm([FromBody] dynamic content)
content variable parsed as a object
and I accessing JsonBody string as content.ToString()
method.
Is it possible to hashes isn't matched because method content.ToString() can return not the same string like in request body?
Is there any ways to handle json as argument in .Net Core method? (I've already tried to placed JObject, but method ToString() also returned string that generated to hash isn't matching)
To compute a matching hash, you need to read the incoming request as is, without deserializing it. So yes, your generated JSON probably differs from the sent one (whitespace characters).
I'm not really familiar with ASP.NET Core, but in the old ASP.NET, you could read the request content using:
var json = new System.IO.StreamReader(Request.InputStream).ReadToEnd();
Let's say we have a controller like this:
public class HomeController : Controller
{
[HttpGet]
public IActionResult Foo(string token)
{
return RedirectToAction(nameof(Index));
}
}
When I type the following URL address in the webbrowser:
https://localhost:44348/home/foo#dsfdsf
I would like to be able to read the dsfdsf after the hash symbol and bind it to the token variable.
Now I'm receiving null value. I'm getting such URL from the 3rd party app and I need to consume the response somehow and read the data from the query string.
I played with [FromQuery] attribute but I haven't managed it to work so far.
Any ideas?
Cheers
I have a work around for you, but first of all lets get more into the problem.
The strings after the hash symbol which are called Fragment values are not query parameters but they are strings to be read by the client-side (living in the browser) and the server cannot read them because they are not sent to the server by the browser.
Some authentication providers like Google and Azure send the access token as Fragment value for security reasons so that they are not transferred over the internet after they get sent as direct response from the authentication provider.
The only way you can come around that is to use javascript to convert the fragment values to query parameters by replacing the '#' with '?' and redirecting to the endpoint in your server controller.
I suppose the easiest way is to handle all that from server, meaning you get get the request in server, send a javascript code to the browser on the fly, that replaces the '#' into '?' and redirects to your second endpoint which reads the token as strong parameter.
Here how you can do it in ASP.NET Core 3.1:
[AllowAnonymous]
[HttpGet("authredirect")]
[Produces("text/html")]
public virtual ContentResult ConvertUrlFragmentToQueryParamThenRedirect()
{
return Content("<html><script>window.location.href=window.location.href.replace('#', '?').replace('authredirect', 'authparams')</script></html>", "text/html");
}
[AllowAnonymous]
[HttpGet("authparams")]
public virtual void GetAccessToken([FromQuery] string access_token)
{
// now you have your access token server side here
}
Please remember to set your redirectUrl to the correct one, in this case 'YOUR REDIRECT URL/authredirect'.
I have the code that returns the Cloud Front Signed Cookie Values.
CookiesForCustomPolicy signedCookiesUrl = AmazonCloudFrontCookieSigner.GetCookiesForCustomPolicy("https://example.cloudfront.net/movies/nature.mp4", new StreamReader(File.OpenRead(Path.Combine(AppContext.BaseDirectory, "pk-2.pem"))),"APKEXAMPLEKEYID", DateTime.Now.AddDays(10), DateTime.Now, null);
I use the returned values to request the object, however returns the
<Error>
<Code>MissingKey</Code>
<Message>
Missing Key-Pair-Id query parameter or cookie value
</Message>
</Error>.
I test this through the PostMan tool putting the headers and direct request through Chrome browser and still getting the same error.
I have use the correct Cloudfront Key Pair and correct resource URL. My objects are private and cloudfront have access to it. Is there any thing else that i need to work on to get this working?
Add Header Key Pair
These aren't raw headers, they're cookies. Although I don't use postman, it sounds like this is your issue:
Based on what you've said, you wouldn't add them like this:
[CloudFront-Key-Pair-Id, APKEXAMPLEQQ]
Instead it should look more like this:
[Cookie, CloudFront-Key-Pair-Id=APKEXAMPLEQQ]
Here is the example for Signed URL in C#.
http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CreateSignatureInCSharp.html
When you return the signed keys, you can return with query string parameter or Cookies.
You can return cookies to API Gateway in two ways, Do with ANY Integration and return the headers as it is.
If you do any other method, you need to return json data and map json data to headers in API Gateway.
http://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html#mapping-response-parameters
Hope it helps.
When we use PUBLIC_KEY and PRIVATE_KEY then we get Key-Pair-Id missing. We should use Access Key Id instead of PUBLIC_KEY then it will work perfectly.
I am trying the construct a HTTP GET web request that satisfies the following criteria
GET /v1/session
Host: developer.messenger.yahooapis.com
Authorization: < Standard OAuth credentials >
From what I know about get requests is that they are something like this :
https://someaddress.com/¶meterA=valA¶meterB=valB
where parameterA and parameterB are the parameters that are required.
Now I want to construct a similar address for the above mentioned criteria. How can I do that. I believe the address would be https://developer.messenger.yahooapis.com however I am not sure what the other requirements are for such a get request. I would appreciate it if someone could disect and specify the requirements of the above(Topmost) Get Request so that I may be able to construct a valid GET request URI.
https://developer.messenger.yahooapis.com
so your request url should be like
https://developer.messenger.yahooapis.com?parameterA=valA¶meterB=valB
you get your data in your $_GET array, just add print_r($_GET)
For a request, you need a URL like
https://developer.messenger.yahooapis.com
BUT that is only the hostname.
you need to specify a resource that you want to GET like /v1/session, so your URL is
https://developer.messenger.yahooapis.com/v1/session
If you want to pass some parameters you have to signal that the pointing part of the URL is finished. You do this with an ?. Now to add the parameters, you basically add name-value pairs, like var1=value. For multiple params use a & to seperate them. Slapping all together you get a
https://developer.messenger.yahooapis.com/v1/session?var1=value&var2=value
as URL. Now hand it to your HttpGet-method.
HttpGet will now build a request and later send it to https://developer.messenger.yahooapis.com the host/server who will return the resource to your client. To tell the host that you have the rights to access that resource, the request must contain the neccessary login informations, thats what oAuth is for. Those credentials have to be added in the request header before executing the get-request.
I need to parse url that has something after # (hash) sign in my asp.net application. How to do it easily?
Thank you,
You're looking for the Uri class:
new Uri(someString).Fragment
Note that the hash is not sent to the server in an HTTP request.
url.Substring(url.IndexOf('#') + 1)
...where "url" is a string containing the url in question
This is called "hash sign" URI.
After client gets PAGE responsed including js,
the contents after '#' would be handled by client using responsed js to get "real" URL for redirection.
SEE: https://www.w3.org/2001/tag/2011/01/HashInURI-20110115#References
Omg, I meant fragment (after #) part on the server... Though I've looked thrugh and found that it seems to be impossible......