Handle the revoked or expired Evernote app - evernote

One year ago I activated the Evernote API key for an app (for my client). One week ago the key expired. My client mistakenly revoked the app instead of authorizing it for one year more.
I restored the app authorization with the oAuth method:
var oAuth = new EvernoteOAuthNet.EvernoteOAuth(EvernoteOAuthNet.EvernoteOAuth.HostService.Production, "palmaross", "42dd922cb547c0b7", true);
var errorResponse = oAuth.Authorize();
if (!String.IsNullOrEmpty(errorResponse))
{
ENSessionAdvanced.SetSharedSessionDeveloperToken(oAuth.Token, oAuth.NoteStoreUrl);
}
Client successfully authorized the app for one year more:
Now the ENSessionAdvanced.SharedSession.IsAuthenticated = true. OK.
ENNoteStoreClient SC = ENSessionAdvanced.SharedSession.PrimaryNoteStore is OK.
But the SC.GetSyncState() now raises an exception of type EDAMUserException with AUTH_EXPIRED parameter. (Despite the fact the app was successfully authorized for one year more - see above).
For this reason few days ago i requested a new API key for this app,
With this key I have successfully connected my app with Evernote for one year.
But...
With the new API key (= new app?) the SC.GetSyncState() also raises the same exception - AUTH_EXPIRED!!
What can I do to solve the problem?

Related

ADFS 2016 On behalf of flow : cannot get any user informations

I'm trying to implement the "on behalf of" flow in an application using ADFS 2016 as STS. As a reference, I look at this Microsoft tutorial (https://learn.microsoft.com/en-ca/windows-server/identity/ad-fs/development/ad-fs-on-behalf-of-authentication-in-windows-server). It's working as it should, I can login into my web application and then use my original access token in UserAssertion to generate a new access token with the proper audience to call my API BUT I found absolutely no way to include any user informations (sub, name, email, upn etc.) into the access token for my API, even if I set claim rules into my ADFS configurations for the API.
I checked the communication between my app and adfs using Fiddler and everything looks like the informations in the tutorial. See the screen shot of the "on behalf of" request below :
Here's the resulting access token :
Finally, here's the code I use to generate my new access token :
private async Task<string> GetAccessToken(ClaimsPrincipal user, string originalAccessToken)
{
var authority = "[authority]";
var context = new AuthenticationContext(authority, false);
string userName = user.FindFirstValue("upn");
var userAssertion = new UserAssertion(originalAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer",userName);
var cc = new ClientCredential("https://localhost:44387/", "[client_secret]");
var result = await context.AcquireTokenAsync("https://localhost:44339/", cc, userAssertion);
return result.AccessToken;
}
Have you struggle with that scenario and if yes, did you find a way to fix this ?
Thanks
I've only used the Microsoft On Behalf Of flow with Azure AD and not ADFS, but it looks like you need to send a more detailed scope in your User Info request.
Maybe try sending 'openid profile email', to indicate that you want that type of detail, as in Section 17 of my blog post. Of course this assumes that this type of data has been registered for all users.
TROUBLESHOOTING
Looks like one of these will be the cause:
A suboptimal Microsoft library that does not allow you to send the required scope
Or ADFS 2016 perhaps lacks the scope features that work correctly in Azure AD
I would concentrate on making extra sure you are sending the correct form URL encoded request message, using a tool such as curl, Postman or a plain C# HttpClient. Here is the code I used to send the correct scope - using an open source library rather than a Microsoft one:
Sample NodeJS Code
If you can get the scope sent correctly then you should have a resolution either way:
Either you get the correct data and can update your code
Or the behaviour you want is not supported by ADFS
Good luck ...

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.

How to Extend Firebase Session Cookies Beyond 2 Weeks

I'm using Firebase Auth to have users authenticate using their Google Account. I found the token returned by firebase.auth().currentUser.getIdToken is only valid for 1 hour. To allow the session to last longer I tried creating a session cookie as outlined in Manage Session Cookies:
const expiresIn = 60 * 60 * 24 * 5 * 1000;
admin.auth().createSessionCookie(idToken, {expiresIn}).then((sessionCookie) => {
const options = {maxAge: expiresIn, httpOnly: true, secure: true};
res.cookie('session', sessionCookie, options);
res.end(JSON.stringify({status: 'success'});
}
This code successfully created a session cookie and subsequent requests could be verified using admin.auth().verifySessionCookie. All was well until I tried increasing the expiresIn duration. It turns out that Firebase session cookies have a maximum expiration time of 2 weeks. From the docs:
Ability to create session cookies with custom expiration times ranging from 5 minutes to 2 weeks.
For this project I would prefer to have a user log in once and stay logged in. I tried extending the session on every interaction with the server but I didn't find any official documentation on how to do that. It seemed to make sense to call admin.auth().createSessionCookie on the server using the token returned by admin.auth().verifySessionCookie, but that failed with this error:
Failed to extend session: { Error: An internal error has occurred. Raw server response: "{"error":{"code":400,"message":"Invalid value at 'valid_duration' (TYPE_INT64), 604.8","errors":[{"message":"Invalid value at 'valid_duration' (TYPE_INT64), 604.8","domain":"global","reason":"badRequest"}],"status":"INVALID_ARGUMENT"}}"`enter code here`
at FirebaseAuthError.Error (native)
at FirebaseAuthError.FirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:39:28)
at FirebaseAuthError.PrefixedFirebaseError [as constructor] (/user_code/node_modules/firebase-admin/lib/utils/error.js:85:28)
at new FirebaseAuthError (/user_code/node_modules/firebase-admin/lib/utils/error.js:143:16)
at Function.FirebaseAuthError.fromServerError (/user_code/node_modules/firebase-admin/lib/utils/error.js:173:16)
at /user_code/node_modules/firebase-admin/lib/auth/auth-api-request.js:726:49
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
errorInfo:
{ code: 'auth/internal-error',
message: 'An internal error has occurred. Raw server response: "{"error":{"code":400,"message":"Invalid value at \'valid_duration\' (TYPE_INT64), 604.8","errors":[{"message":"Invalid value at \'valid_duration\' (TYPE_INT64), 604.8","domain":"global","reason":"badRequest"}],"status":"INVALID_ARGUMENT"}}"' },
codePrefix: 'auth' }
Is it possible to extend Firebase sessions on the server side without requiring the client to do any work? Is it possible to use Firebase auth with tokens with a longer lifespan than 2 weeks? If not, in there a standard approach on how to achieve incredibly long lived sessions?
Extending it too long can be risky, as if the cookie is leaked, the window of attack will be quite wide. I don't recommend extending the session longer but if this is a requirement, you could try to do the following:
after verifying the session cookie on your server for the user and noticing it is about to expire.
mint a custom token for that user ID with Admin SDK
signInWithCustomToken with that custom token.
user.getIdToken() to get new ID token.
Exchange that ID token for a new session cookie.
The downside is that the claims in the session cookie will correspond to a custom token user.
Notice for client side sessions, the ID token passed around has one hour duration, even though the session is indefinite. This is because a refresh token lives on the device and is used to exchange new ID tokens. At any time, only the ID token is transmitted limiting the window of attack to one hour if that token is leaked.
I think it would be useful for Firebase Auth to offer an active duration functionality. That would be better for extending sessions continuously in short increments. This would be better than minting an indefinite or very long cookie. An active user would constantly have their session extended. This is not offered by Firebase Auth but you can file a feature request for it.

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().

The Access Token is Valid but We get OAuthException: An active access token error

We've been working on an application for about 2 months, and everything was going perfectly.
we were using PHP SDK and offline mode in permissions for login
But since some days ago after recent changes in Facebook api and removing offline mode we started facing the problem of "Uncaught OAuthException: An active access token must be used to query information about the current user."
The main problem is that it does happen after a while working in our app (about 10 mins) but at the same time when we check the validity of the token via this link
we see that the token is still valid on the other hand the cookie does still exist and it doesn't expire but we get this error :
"Uncaught OAuthException: An active access token must be used to query information about the current user"
I've already visited this link
and I downloaded the latest version but it didn't help could anyone help us please where might be making mistake?
Thanks for responses, I think same as yacon
it seems there's a bug when accessing facebook->api(/me) at the moment we are handling
some parts of the app with javascript which is a real headache to use javascript sdk
and PhP sdk alongside with each other
You can solve this simply store accesstoken to session variable after getLoginUrl
$facebook->getLoginUrl(...)
then whenever you initialize facebook
$facebook = new Facebook(array(
'appId' => Yii::app()->params['facebook_appId'],
'secret' => Yii::app()->params['facebook_appSecret'],
));
get the accesstoken from session and set it using setAccessToken
$facebook->setAccessToken(Yii::app()->session['access_token']);
I handle this situation in this way
1.i get the access token for 1 hour validity
2.extend the token to 60 days validity
3.save that token to session and use it for all project queries.
try{
$facebook_uid = $facebook->getUser();
$facebook->setExtendedAccessToken();
$accessToken = $facebook->getAccessToken();
$fbuser = $facebook->api('/me');
$session['api_me'] = $fbuser;
$session['tokenValue'] = $accessToken;
}catch (Exception $e) {
facebook_uid =null;
}
I think there is a bug in the api. When I use $facebook->api('/'.$facebook_uid) instead of ->api('/me') it works.

Resources