XSRF token expired after website publish to IIS - asp.net

I am using ASP.NET Boilerplate framework, I put the below code in everypage.
#inject IAbpAntiForgeryManager AbpAntiForgeryManager
#{
AbpAntiForgeryManager.SetCookie(Context);
}
I call the app service as below:
var xhr = abp.services.app.order.add(data);
xhr.done(function (data) {
alert(data);
});
Everything works fine when I run in localhost, XSRF token will not expired even if I rebuild the project. Every time when I click [Publish website to IIS], all the ajax request will return 400 Bad Request, I guess it is because the XSRF token has expired, everything back to normal after I click F5 in browser. It was so annoying for the user, any thing I can do to prevent this error? Or auto refresh token?
Thank you!
update
error message in LOG file:
ERROR 2019-02-12 13:40:09,773 [71 ] .Antiforgery.Internal.DefaultAntiforgery - An exception was thrown while deserializing the token.
Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery token could not be decrypted. ---> System.Security.Cryptography.CryptographicException: The key {996d31d2-0fa3-4ffe-8e82-e155c1486d33} was not found in the key ring.

Based on the error it sounds like your Data Protection keys have rotated on publish.
Check out the docs on Data Protection here: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/introduction?view=aspnetcore-2.2.
There's a bunch of options how to configure it, where to store keys etc.
You'll want to change how it is storing them.
More on configuring Data Protection: https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?view=aspnetcore-2.2.

Related

Missing initial state in WebAuthenticator login attempt

working on a .NET MAUI app and am trying to implement Firebase Authentication with the help of WebAuthenticator in MAUI. I get to the login form in a browser, but after logging in get the error
Unable to process request due to missing initial state. This may happen if browser sessionStorage is inaccessible or accidentally cleared.
This is the code that calls the authenticator
await client.SignInWithRedirectAsync(FirebaseProviderType.Google, async uri =>
{
var options = new WebAuthenticatorOptions
{
Url = new Uri(uri),
CallbackUrl = new Uri("com.companyname.myappname://callback/"),
PrefersEphemeralWebBrowserSession= true
};
var res = await WebAuthenticator.Default.AuthenticateAsync(options);
});
I think the problem could be the callback URL, but I'm not sure how to write it differently since I'm not using a backend API. Does anyone have any suggestions?
Thanks!
P.S. This happens with bost Firebase Google auth and Facebook login
You can try to clear the chrome browser data and reload the page to see if it works. This is a known problem of firebase. You can continue to follow up this github iissue: Unableto process request due to missing initial state.

Newly generated access token in not working instantly in the linkedin-ads API

I'm getting this response (with 401 error code) after using the new refreshed access token:
{'serviceErrorCode': 65601, 'code': 'REVOKED_ACCESS_TOKEN', 'message': 'The token used in the request has been revoked by the user'}
I followed this guide to refresh the access token:
https://learn.microsoft.com/en-us/linkedin/shared/authentication/programmatic-refresh-tokens?view=li-lms-2022-07#step-2-exchanging-a-refresh-token-for-a-new-access-token
Although it works after several seconds. It seems like the issue is from the LinkedIn-Ads API side. Is there an exact time to wait after generating the access token?

REST API Getting 401 UnAuthorized

I am using .NET Core Web API to make call and getting back
401, unauthorized ? I am using a REST API key.
var ApiKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var _Http = new HttpClient();
var response = await _Http.GetAsync($"https://geocode.search.hereapi.com/v1/geocode?q={address},{city},{state},{postalCode},{country}&apikey={ApiKey}");
What am I missing ?
I am getting the key from the following section
UPDATE: this problem has vanished today. It appears to have been a bug on the Here side.
Yesterday: My JS API code, which has been working fine, is throwing 401s today as well, with no changes. I could kill the project and create a new one with a new API key, but I'm not sure that would fix it. I did find that it was "disabled" (due to a billing issue, I think), and I "enabled" it and it still throws 404s.
Did you confirm your email address (by clicking the link in the email they send)?
If you have not confirmed your email address, then the API Key is only valid for 30 minutes.

App Service Refresh Tokens

Has anything changed with regard to refreshing Google tokens using the MobileServiceClient against App Service. I used to be able to refresh Google tokens in my Xamarin Forms app using the MobileServiceClient. Now, after logging in, any attempt to refresh returns forbidden.
My login code is as follows:
public class Authentication : IAuthentication
{
public async Task<MobileServiceUser> LoginAsync(MobileServiceClient mobileClient, MobileServiceAuthenticationProvider provider)
{
return await mobileClient.LoginAsync(
Forms.Context,
provider,
new Dictionary<string, string>()
{
{ "access_type", "offline" }
});
}
}
My refresh code is:
var user = await MobileService.RefreshUserAsync();
The refresh fails even if I try refreshing immediately after my successful login. The Token Store is configured "On". The refresh works fine against the Microsoft provider. It was working a few months ago.
Microsoft.Azure.Mobile.Client v3.1.0
Microsoft.Azure.Mobile.Server v2.0.0
Browsing directly to https://[my-website].azurewebsites.net/.auth/login/google returns "You have successfully signed in"
Browsing directly to https://[my-website].azurewebsites.net/.auth/me returns [{"access_token":"ya29.Gl3ZAw6B1H0cT_e6vRlHgwQd0U-bcDSKo_CGQ9wKwPH8H-EbtNojP61JSzDaiIgSzU14PrT3QRb14NsFPhFYrU8ikCPGkhwKkZMAtHCNSdzDhTPm5cl89VrAlNc3vRU","expires_on":"2017-01-20T15:00:21.3928445Z","id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjZlYzMwOTBlZjgyM2YxMWFhN2VhNDE0N2FlZWM1Zjk0YmViNWZkMDMifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJpYXQiOjE0ODQ5MjA4MjEsImV4cCI6MTQ4NDkyNDQyMSwiYXRfaGFzaCI6IlhHa3dqOFpiZU9GX2N3SmpqeEpMRnciLCJhdWQiOiI3NDgwNzM0Njg2NDktanRtNTl0N21sY3NjaTg5bG9rYnV2c2VvYW5uMjhiZ3EuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMDE4MTI5MTIzODE5MTgwNDA4NDciLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNzQ4MDczNDY4NjQ5LWp0bTU5dDdtbGNzY2k4OWxva2J1dnNlb2FubjI4YmdxLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiZW1haWwiOiJnY3JvY2tlbmJlcmdAZ21haWwuY29tIiwibmFtZSI6ImdlcmFyZCBjcm9ja2VuYmVyZyIsInBpY3R1cmUiOiJodHRwczovL2xoNS5nb29nbGV1c2VyY29udGVudC5jb20vLVpINUxBQ1RhQTRJL0FBQUFBQUFBQUFJL0FBQUFBQUFBQUFBL0FLQl9VOHRpamZ5ZUN3Qk9tWUxzTmM4QUZJcTNDVGJhVHcvczk2LWMvcGhvdG8uanBnIiwiZ2l2ZW5fbmFtZSI6ImdlcmFyZCIsImZhbWlseV9uYW1lIjoiY3JvY2tlbmJlcmcifQ.Qie3hRwKP-mbzMp3gzWatmQdLLVw3Ae7PXw1Ly8Se7-EQWBPgky0TsQ-fvZIasiHaq1tQu9lXyNu9qYqaaAvKxKCGxRE5yYhC76Yar_rQig14lf42bMRYQ3ADzwsPZ0yUbEpk-h4_HU5Ld1lNqYG-hgzEdUsJm_uspJk7FggwcfuPw-YQJr-GXbqd2Om9fmgGPrPrsFy7EzPGL27q_BIY3cOLEVX0e3tbAAVhxFCri835nBKdkYOP9X2g6wSuMWCq6iPOjFzErhVYR_WUwi5H-UW6mJHswcAfs_3Hwwt9RzCqfcyS1ZaehQVJE5B3uvK9WmAOrbD7uyEQmSli_zRWw","provider_name":"google","user_claims":[{"typ":"iss","val":"https://accounts.google.com"},{"typ":"iat","val":"1484920821"},{"typ":"exp","val":"1484924421"},{"typ":"at_hash","val":"XGkwj8ZbeOF_cwJjjxJLFw"},{"typ":"aud","val":"748073468649-jtm59t7mlcsci89lokbuvseoann28bgq.apps.googleusercontent.com"},{"typ":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier","val":"101812912381918040847"},{"typ":"email_verified","val":"true"},{"typ":"azp","val":"748073468649-jtm59t7mlcsci89lokbuvseoann28bgq.apps.googleusercontent.com"},{"typ":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress","val":"[my-googleemail]"},{"typ":"name","val":"[my - name]"},{"typ":"picture","val":"https://lh5.googleusercontent.com/-ZH5LACTaA4I/AAAAAAAAAAI/AAAAAAAAAAA/AKB_U8tijfyeCwBOmYLsNc8AFIq3CTbaTw/s96-c/photo.jpg"},{"typ":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname","val":"[my-givenname]"},{"typ":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname","val":"[my-surname]"}],"user_id":"[my-googleemail]"}]
Browsing directly to https://[my-website].azurewebsites/.auth/refresh returns "You do not have permission to view this directory or page"
If I repeat those steps with "microsoftaccount" the last refresh step works.
From Azure request tracking:
107. -GENERAL_FLUSH_RESPONSE_START
0 ms
Informational
108. -GENERAL_RESPONSE_HEADERS
Headers
Content-Type: text/html
Server: Microsoft-IIS/8.0
X-FE-DATA: AppId:Unknown-StatusCode
X-Powered-By: ASP.NET
DWAS-Handler-Name: BEGIN|403|80|0x0|CONFIG_SUCCESS|ExtensionlessUrlHandler-Integrated-4.0|###.##.##.###|\###.##.##.##\volume-4-default\&ApiApp=0
0 ms
Verbose
109. -GENERAL_RESPONSE_ENTITY_BUFFER
Buffer
You do not have permission to view this directory or page.
0 ms
Informational
110. -GENERAL_FLUSH_RESPONSE_END
BytesSent 400
ErrorCode The operation completed successfully.
(0x0)
Turns out that, with Google logins, refresh tokens are only issued upon the first login. I moved my Azure website and repointed the OAuth client settings so I was able to login but the Token Store no longer had a copy of the refresh_token sent with my initial Google login. Found the rest of the answer here.
Not receiving Google OAuth refresh token
According to your detailed information, I noticed that when you browsing directly to https://[my-website].azurewebsites.net/.auth/me, the response did not contain refresh_token. To isolate this issue, you could refer the following steps:
1.Browser https://brucechen-mobile.azurewebsites.net/.auth/login/google?access_type=offline and login with google account;
2.Access /.auth/me to retrieve my logged information as follows:
3.Browser /.auth/refresh to see whether you could get the response with 200 http status code.
Also, you could follow this official tutorial about refreshing user logins in App Service Mobile Apps to troubleshoot this issue. Additionally, you could leverage Fiddler to capture the detailed response when you invoke MobileService.RefreshUserAsync().

Get refresh token google api

I can't get my refresh token with my code. I can only get my access token, token type etc.,
I have followed some tutorials like putting access_type=offline on my login URL:
echo "<a href='https://accounts.google.com/o/oauth2/auth?"
. "access_type=offline&client_id=123345555.apps.googleusercontent.com& "
. "scope=https://www.googleapis.com/auth/calendar+https://www.googleapis.com/auth/plus.me&response_type=code& "
. "redirect_uri=http://www.sample.com/sample.php&state=/profile'>Google</a>";
and my fields in getting the access token:
$fields=array(
'code'=> urlencode($authcode),
'client_id'=> urlencode($clientid),
'client_secret'=> urlencode($clientsecret),
'redirect_uri'=> urlencode($redirecturi),
'grant_type'=> 'authorization_code',
);
but I can't get refresh_token, just the access_token, token_type, id_token and expires_in.
Found out by adding this to your url parameters
approval_prompt=force
Update:
Use access_type=offline&prompt=consent instead.
approval_prompt=force no longer works
https://github.com/googleapis/oauth2client/issues/453
If I may expand on user987361's answer:
From the offline access portion of the OAuth2.0 docs:
When your application receives a refresh token, it is
important to store that refresh token for future use. If your
application loses the refresh token, it will have to re-prompt the
user for consent before obtaining another refresh token. If you need
to re-prompt the user for consent, include the approval_prompt
parameter in the authorization code request, and set the value to
force.
So, when you have already granted access, subsequent requests for a grant_type of authorization_code will not return the refresh_token, even if access_type was set to offline in the query string of the consent page.
As stated in the quote above, in order to obtain a new refresh_token after already receiving one, you will need to send your user back through the prompt, which you can do by setting approval_prompt to force.
Cheers,
PS This change was announced in a blog post as well.
It is access_type=offline that you want.
This will return the refresh token the first time the user authorises the app. Subsequent calls do not force you to re-approve the app (approval_prompt=force).
See further detail:
https://developers.google.com/accounts/docs/OAuth2WebServer#offline
This is complete code in PHP using google official SDK
$client = new Google_Client();
## some need parameter
$client->setApplicationName('your application name');
$client->setClientId('****************');
$client->setClientSecret('************');
$client->setRedirectUri('http://your.website.tld/complete/url2redirect');
$client->setScopes('https://www.googleapis.com/auth/userinfo.email');
## these two lines is important to get refresh token from google api
$client->setAccessType('offline');
$client->setApprovalPrompt('force'); # this line is important when you revoke permission from your app, it will prompt google approval dialogue box forcefully to user to grant offline access
For our app we had to use both these parameters access_type=offline&prompt=consent.
approval_prompt=force did not work for us
Hi I followed following steps and I had been able to get the refresh token.
Authorization flow has two steps.
Is to obtain the authorization code using https://accounts.google.com/o/oauth2/auth? URL.
For that a post request is sent providing following parameters. 'scope=' + SCOPE + '&client_id=' + CLIENTID + '&redirect_uri=' + REDIRECT + '&response_type=' + TYPE + '&access_type=offline' Providing above will receive a authorization code.
Retrieving AcessToken and RefreshToken using https://accounts.google.com/o/oauth2/token? URL.
For that a post request is sent providing following parameters.
"code" : code,
"client_id" : CID,
"client_secret" : CSECRET,
"redirect_uri" : REDIRECT,
"grant_type" : "authorization_code",
So in your first attempt once you authorize the permissions you will be able to get the Refresh token. Subsequent attempts will not provide the refresh token. If you want the token again the revoke the access in you application.
Hope this will help someone cheers :)
OAuth has two scenarios in real mode.
The normal and default style of access is called online.
In some cases, your application may need to access a Google API when the user is not present,It's offline scenarios .
a refresh token is obtained in offline scenarios during the first authorization code exchange.
So you can get refersh_token is some scenarios ,not all.
you can have the content in https://developers.google.com/identity/protocols/OAuth2WebServer#offline
.
Since March 2016, use prompt=consent to regenerate Google API refresh token.
As mentioned in https://github.com/googleapis/oauth2client/issues/453,
approval_prompt=force has been replaced with prompt=none|consent|select_account
For those using the Google API Client Library for PHP and seeking offline access and refresh tokens beware as of the time of this writing the docs are showing incorrect examples.
currently it's showing:
$client = new Google_Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt("consent");
$client->setIncludeGrantedScopes(true); // incremental auth
source: https://developers.google.com/identity/protocols/OAuth2WebServer#offline
All of this works great - except ONE piece
$client->setApprovalPrompt("consent");
After a bit of reasoning I changed this line to the following and EVERYTHING WORKED
$client->setPrompt("consent");
It makes sense since using the HTTP requests it was changed from approval_prompt=force to prompt=consent. So changing the setter method from setApprovalPrompt to setPrompt follows natural convention - BUT IT'S NOT IN THE DOCS!!! That I found at least.

Resources