ASP.NET MVC Stripe Error No such token - asp.net

I cant seem to solve this error
Credit.cshtml
<form action="#Url.Action("Charge", "Home")" method="POST">
<article>
<label>Amount: $5.00</label>
</article>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="pk_test_6pRNASCoBOKtIshFeQd4XMUh"
data-amount="1000"
data-name="My Project Name"
data-description="Premium Account (€10)"
data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
data-locale="auto"
data-zip-code="true"
data-currency="eur">
</script>
</form>
HomeController
[HttpPost]
//Parameters can contain stripeToken, stripeEmail, stripeName, stripeAddress submitted from Credit.cshtml form
public ActionResult Charge(string stripeToken, string stripeEmail)
{
Debug.WriteLine("stripe token is " + stripeToken);
Debug.WriteLine("stripe email is " + stripeEmail);
StripeConfiguration.SetApiKey("<!-- my secret key -->");
//Take the token submitted by the form
var token = stripeToken;
//Charge to the user card
var charges = new StripeChargeService();
var charge = charges.Create(new StripeChargeCreateOptions
{
Amount = 1000,
Currency = "sgd",
Description = "Example charge",
SourceTokenOrExistingSourceId = token
});
return View();
}
An exception of type 'Stripe.StripeException' occurred in Stripe.net.dll but was not handled in user code
No such token: tok_1BYf3F2eZvKYlo2C0MJgUKKD
What is happening? Some help pleasee thankss

A "no such token" error generally happens when the token you are trying to charge does not match the account you are making the API call on.
I'd recommend double checking the API keys that you're using, make sure the publishable key on your front-end and secret key in your back-end belong to the same account.
If switching up API Keys doesn't resolve it, you'd want to get in touch with Stripe, their support can look up the token id and tell you why it's not working!

Related

ASP.Net Identity reset password with website and web api

We have 2 separate ways for people to perform a forgot password:
1. Via the website - mywebsite.com/account/forgotpassword
2. Via our App - Clicking the "Forgot Password" passes the users email address to our asp.net web api which in turn creates the code and sends the email.
Clicking the link in the email brings up the correct page where we can enter the email and new password. When resetting the password using option 1, it works fine. Using option 2 gives an invalid token error. Both the website and web api are on the same server.
Here's the Web api code:
var user = await UserManager.FindByEmailAsync(email);
var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = $"/Account/ResetPassword?userId={user.Id}&code={code}";
var path = System.Web.Hosting.HostingEnvironment.MapPath("~/Content/emails/ResetPassword.html");
var body = GenerateEmailBody(user);
await UserManager.SendEmailAsync(user.Id, "Reset Password", body);
Here's the website code
var user = await UserManager.FindByEmailAsync(model.Email);
if (user == null)// || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
{
// Don't reveal that the user does not exist or is not confirmed
return View("ForgotPasswordConfirmation");
}
// Send an email with this link
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
var body = GenerateEmailBody(user);
await UserManager.SendEmailAsync(user.Id, "Reset Password", body);
I verified that the UserTokenProvider is the same in both as well.
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("IdentityStuff"));
I read that MachineKey can cause this issue except we're only using a single server.
An additional piece of info that is worth mentioning is when the website was created, it didn't have identity added to it. This was an after thought. The web api started off with identity.
For clarity purposes I thought I would answer my question.
Instead of have the reset logic in both the website and api, I have both the website and our app call the api to reset the password.
I did, however run into an additional problem when using a load balancer. Since one server may create the code for the reset and another may respond to the link, we run into the same issue.
To fix this problem, I have a DNS entry that always points to a single server which is used to create the code as well as actually reset the password. This eliminates the issue of getting an invalid token.
HTH.

Messenger bot with checkbox plugin how to keep track of the conversation with user ref and user id

We'd like to add the facebook messenger checkbox plugin at the end of a request form so users can opt-in for notifications via messenger.
When the user opts in, our webhook receives a callback with the user_ref that we set in the form.
We send a confirmation of opt-in to this user_ref
But other messages we receive like delivery, read receipt or actual messages from the user do contain the user ref anymore but the user id.
This is the official documentation of facebook:
After you receive the callback event, you can call the Send API to start messaging the user using the user_ref identifier in recipient as shown below. Note that this field is the same as the unique user_ref param used before when the plugin was rendered and in confirming the opt-in.
If the call to the Send API is successful, the response will contain a recipient_id parameter, which is a stable user ID that you can now use in future API calls.
Therefore it's impossible to keep track between the initial message and new ones. Does anyone found a solution for this?
Thank you very much in advance.
You can, for example, send additional information when the user opts in using the optional ref parameter. You can send the username of the user logged on my website:
function confirmOptIn() {
FB.AppEvents.logEvent('MessengerCheckboxUserConfirmation', null, {
'app_id':'APP_ID',
'page_id':'PAGE_ID',
'ref': 'myuser#mywebsite.com',
'user_ref':'UNIQUE_REF_PARAM'
});
You will receive the username within optin in your webhook event:
{
"recipient":{
"id":"PAGE_ID"
},
"timestamp":1234567890,
"optin":{
"ref":"myuser#mywebsite.com",
"user_ref":"UNIQUE_REF_PARAM"
}
}
Then, you can call the Send API to start messaging the user using the user_ref.
If the call to the Send API is successful, the response will contain a recipient_id parameter, which is a stable user ID that you can now use in future API calls.
...so you will received the Messenger ID which you can map to the username of your website you already have. Here, I modified a little the example from the official developers site to call the send API with user_ref and map the user ID I get in the response to the username of my website:
function callSendAPICheckbox(messageData, userApplicationId) {
((userApplicationId) => {
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: {
access_token: PAGE_ACCESS_TOKEN
},
method: 'POST',
json: messageData
},
function(error, response, body) {
if (!error && response.statusCode == 200) {
var recipientId = body.recipient_id;
var messageId = body.message_id;
if (messageId) {
console.log("Map messenger user ID %s with the username of my website %s", recipientId, userApplicationId);
} else {
console.log("Successfully called Send API for recipient %s",
recipientId);
}
} else {
console.error("Failed calling Send API for userId " +
recipientId, response.statusCode, response.statusMessage, body.error);
}
});
})(userApplicationId)
}
Why don't you make use of metadata field of sendTextMessage. Each and every message you send to your user, you send the metadata too, and when you receive response of the message being delivered, you find the metadata field in it.
Here is what I do:
When user select the checkbox plugin and event is triggered I receive the call on my server, check if it contains user_ref. If it does, then I send a text message to user with a custom metadata using user_ref. When user receives the message, the webhook send me a json data as mentioned in the documentation. To identify for which user_ref I have received this response, I set custom metadata which is combination of some string + user_ref before sending the message to user using user_ref. Using this custom metadata I identify the sender.id of the user for which I previously sent message using user_ref. The sender.id is my pageid and recipient.id the the user id which you are trying to get and using which we generally send message to the user and is also know as psid.
Above if just the logical part mentioned which I usually do.
For detail solution along with code, I have already posted it here:

Getting an "Unauthorized" error in Dropnet

I'm using Asp.net MVC 4 and Dropnet to download a file from my DropBox account. I'm not sure what is wrong with my code but I get a error whenever I run my project,
Received Response [Unauthorized] : Expected to see [OK]. The HTTP response was [{"error": "Request token has not been properly authorized by a user."}].
Here are my codes,
public ActionResult DropDls()
{
var _client = new DropNetClient("API KEY", "API SECRET");
DropNet.Models.UserLogin login = _client.GetToken();
_client.UserLogin = login;
var url = _client.BuildAuthorizeUrl();
var accessToken = _client.GetAccessToken();
var fileBytes = _client.GetFile("/Getting Started.pdf");
return View();
}
I want only my Dropbox account to be accessed so I need to know how can I give my own USER TOKEN and USER SECRET. I've searched on the web for a solution but couldn't find anything that'll help me.
The problem is you are not getting the user to login before trying to access their dropbox account.
This line should not be there _client.UserLogin = login;
and after this line var url = _client.BuildAuthorizeUrl(); you will need to redirect the user to that url so they can login, then the dropbox site will redirect them back to your site which is when you make the call _client.GetAccessToken(); then you will have access to the users dropbox account.

Google OpenId Connect migration: getting the openid_id in ASP.NET app

I've gone through plenty of Google documentation and SO Q/A's but with no luck. I wonder if anyone has yet succesfully used the OpenId to OpenId Connect migration as advised by Google.
This is what we used to do:
IAuthenticationResponse response = _openid.GetResponse();
if (response != null) {
//omitted for brevity
} else {
IAuthenticationRequest req = _openid.CreateRequest("https://www.google.com/accounts/o8/id");
req.AddExtension(new ClaimsRequest
{
Country = DemandLevel.Request,
Email = DemandLevel.Request,
Gender = DemandLevel.Require,
PostalCode = DemandLevel.Require,
TimeZone = DemandLevel.Require
});
req.RedirectToProvider();
}
That was done using a version of DotNetOpenAuth that dates back a few years. Because Google has deprecated OpenId authentication we are trying to move over to OpenID Connect. The key question here is: can I somehow get my hands on the OpenId identifier (in the form of https://www.google.com/accounts/o8/id?id=xyz) using the latest version of DotNetOpenAuth library or by any other means?
I have tried the latest DotNetOpenAuth and I can get it to work but it gives me a new Id (this was expected). I have also tried the Javascript way by using this URL (line breaks for readibility):
https://accounts.google.com/o/oauth2/auth?
scope=openid%20profile%20email
&openid.realm=http://localhost/palkkac/
&client_id=//here is the client id I created in google developer console
&redirect_uri=http://localhost/palkkac/someaspxpagehere
&response_type=id_token%20token
I checked (using Fiddler) the realm value that we currently send using the old DotNetOpenAuth code and it is http://localhost/palkkac/. I've put the same realm in the url above. The redirect url starts with the realm value but it is not entirely the same.
When I redirect to a simple page that parses the id_token and decrypts it (using the https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=zyx endpoint) I get this:
audience "client id is here"
email "mikkark#gmail.com"
expires_in 3597
issued_at //some numbers here
issued_to "client id is here"
issuer "accounts.google.com"
user_id "here is a sequence of numbers, my id in the OpenID Connect format that is"
verified_email true
So there is no sign of the openid_id field that you would expect to find here, though the whole structure of the message seems different from the Google docs, there is no field titled sub, for example. I wonder if I'm actually using the wrong endpoint, parameters or something?
What I have been reading is the migration guide: https://developers.google.com/accounts/docs/OpenID. I skipped step 2 because it seemed like an optional step. In step 3 the field openid_id is discussed and I would like to get that to work as a proof-of-concept first.
We registered the app on Google in order to create the client id etc. There are now also numerous allowed redirect url's as well as javascript origins listed in the Google dev console. Let me know if those might mess up the system and I'll post them here for review.
Side note: we are supposed to be moving our app behind a strictly firewalled environment where we would need to open ports in order to do this on the server side. Therefore, a client-side Javascript solution to access Google combined with HTTPS and redirecting the result to the server would be prefered (unless there are other issues that speak against this).
There are other resources on SO regarding this same issue, although all of these seem to use different libraries on the server side to do the job and nobody seems to have made any attempts at using Javascript:
Here (https://stackoverflow.com/questions/22842475/migrating-google-openid-to-openid-connect-openid-id-does-not-match) I think the problem was resolved by setting the realm to be the same as in the old OpenId2.0 flow. This does not seem to work in my case.
over here the openid_id field is also missing, but the problem here is more about how to request the id_token from Google using libraries other than DotNetOpenAuth.
and in here there seem to be similar problems getting Google to return the openid_id field.
You can use the GoogleAuthentication owin middleware.
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
{
SignInAsAuthenticationType = signAs,
AuthenticationType = "Google",
ClientId = "xxx.apps.googleusercontent.com",
ClientSecret = "xx",
CallbackPath = PathString.FromUriComponent("/oauth2callback"),
Provider = new GoogleOAuth2AuthenticationProvider
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&openid.realm=https://mydomain.com/"); // DotNetOpenAuth by default add a trailing slash, it must be exactly the same as before
}
},
BackchannelHttpHandler = new MyWebRequestHandler()
}
Then, add a new class called MyWebRequestHandler:
public class MyWebRequestHandler : WebRequestHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var httpResponse = await base.SendAsync(request, cancellationToken);
if (request.RequestUri == new Uri("https://www.googleapis.com/plus/v1/people/me")) return httpResponse;
var configuration = await OpenIdConnectConfigurationRetriever.GetAsync("https://accounts.google.com/.well-known/openid-configuration", cancellationToken); // read the configuration to get the signing tokens (todo should be cached or hard coded)
// google is unclear as the openid_id is not in the access_token but in the id_token
// as the middleware dot not expose the id_token we need to parse it again
var jwt = httpResponse.Content.ReadAsStringAsync().Result;
JObject response = JObject.Parse(jwt);
string idToken = response.Value<string>((object)"id_token");
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
try
{
SecurityToken token;
var claims = tokenHandler.ValidateToken(idToken, new TokenValidationParameters()
{
ValidAudience = "xxx.apps.googleusercontent.com",
ValidIssuer = "accounts.google.com",
IssuerSigningTokens = configuration.SigningTokens
}, out token);
var claim = claims.FindFirst("openid_id");
// claim.Value will contain the old openid identifier
if (claim != null) Debug.WriteLine(claim.Value);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
return httpResponse;
}
}
If like me you found this not really straightforward, please help by upvoting this issue https://katanaproject.codeplex.com/workitem/359

Can I integrate with firebase in a secure way without having user authentication without having server side code?

My site is just one page with a form. I don't have any user auth functionality . Can I still use client side firebase integration without passing through a server side code in a secure way? If yes how can I secure the details for my firebase connection ?
You can use the new anonymous auth functionality provided by Firebase Simple Login: https://www.firebase.com/docs/security/simple-login-anonymous.html
With this mechanism, you can have users of your website authenticate to Firebase anonymously (they don't need to enter any login credentials), but you can still protect reads and writes to your Firebase using regular security rules.
Yes.
Just add these tags to you page:
<script type="text/javascript" src="https://cdn.firebase.com/v0/firebase.js"></script>
<script type="text/javascript" src="https://cdn.firebase.com/v0/firebase-simple-login.js"></script>
Then write this code:
var chatRef = new Firebase('https://YOUR-APP.firebaseIO.com');
var auth = new FirebaseSimpleLogin(chatRef, function(error, user) {
if (error) {
// an error occurred while attempting login
console.log(error);
} else if (user) {
// user authenticated with Firebase
console.log('User ID: ' + user.id + ', Provider: ' + user.provider);
} else {
// user is logged out
}
});
And when your user clicks the login button, call
// attempt to log the user in with your preferred authentication provider
auth.login('github (or twitter, or what you want)');
As explained here and demonstrated here.

Resources