Handle facebook expiration token - c#

I am having some trouble while integrating facebook API with my desktop application.
Now, I`m trying to use Facebook SDK for .NET: http://facebooksdk.net/
Here is the problem:
When I use my tokens, Facebook returns the following message:
"Error validating access token: Session has expired at unix time 1365165488. The current unix time is 1378218499."
I saw in some posts that I can do something like this to renew my access token:
Dictionary<string, object> fbParams = new Dictionary<string, object> ();
fbParams["client_id"] = token.appId;
fbParams["grant_type"] = "fb_exchange_token";
fbParams["client_secret"] = token.appSecret;
fbParams["fb_exchange_token"] = token.accessToken;
JsonObject publishedResponse = fbClient.Get ("/oauth/access_token", fbParams) as JsonObject;
return publishedResponse["access_token"].ToString ();
But it doesn't work; it throws another exception with the same message ("Session has expired...")
Is there an easy way to do this?
I don't know if this can impact my application but this access token is like 1 year old (and I'm using in a desktop application).
Thank you very much! =)

The message is clear, you are using a token that has already expired (It's actually over four months old). You need to go back through the login flow with a user arriving at an authorization screen.
You cannot extend a token that has already expired, you can only extend tokens that are valid. e.g. a short lived (two hours) token to a long lived token (two months)

Related

IdentityServer4 Refresh Token: How to determine expiration time?

I am working with the Identity Server 4 sample code. In particular, for the client I am using the sample MVC Client with the Hybrid flow: https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Clients/src/MvcHybrid
And for the server I am using Identity Server with in-memory clients (no Entity Framework, and no ASP.Net Identity): https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts
Both client and server have pretty much vanilla, out-of-the-box configuration.
I am trying to understand how refresh tokens expire and how a native app can pro-actively determine the expiration time (before it gets rejected by an API). My understanding is that the default expiration for refresh tokens is long:
http://docs.identityserver.io/en/latest/topics/refresh_tokens.html:
Maximum lifetime of a refresh token in seconds. Defaults to 2592000 seconds / 30 days
However, when the sample code requests a refresh token, I do not get the expected expiration time. Here is the sample code:
var disco = await _discoveryCache.GetAsync();
if (disco.IsError) throw new Exception(disco.Error);
var rt = await HttpContext.GetTokenAsync("refresh_token");
var tokenClient = _httpClientFactory.CreateClient();
var tokenResult = await tokenClient.RequestRefreshTokenAsync(new RefreshTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "mvc.hybrid",
ClientSecret = "secret",
RefreshToken = rt
});
tokenResult.ExpiresIn is 3600 seconds, which is actually the expiration of an access token. I was expecting that to be 2592000 seconds. So question #1 is: Why is this the case?
But more importantly, I know that the expiration for the refresh token is in fact the default 30 days when I use SQL Server as the data store. There is a table PersistedGrants that contains the refresh tokens, and the expiration is clearly 30 days from the issue date. So question #2 is: How can an app programmatically determine the expiration date of the refresh token it received?
I've tried to parse the RefreshToken itself, but it is not really a full JWT, so this throws an error:
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessTokenResponse.RefreshToken);
var diff = jwt.ValidTo - jwt.ValidFrom;
I've also searched through the IdentityServer4 unit / integration tests and cannot find an example of introspecting a refresh token.
Presumably that information either needs to be somewhere in the initial token response, or there needs to be an endpoint built into Identity Server. But I can't find either of these things.
Ok, so the answer is that there is no data in the access_token response that indicates the expiration time of the refresh_token. Additionally, there is no endpoint that can be used to check the expiration.
The OAuth spec does not say anything about this, so I did not want to alter the access_token response. I wound up making my own endpoint that returns the expiration time if needed. Here is my controller action, if anyone needs a starting point:
private readonly IRefreshTokenStore _refreshTokenStore; // inject this into your controller
...
[Route("[controller]/GetRefreshTokenExpiration")]
[Authorize(...YOUR SCOPE...)]
public async Task<IActionResult> GetRefreshTokenExpiration(string refreshTokenKey)
{
var refreshToken = await this._refreshTokenStore.GetRefreshTokenAsync(refreshTokenKey);
if (refreshToken == null)
{
return NotFound(new { message = "Refresh token not found" });
}
return Ok(new {
message = "Refresh token found",
lifetime_seconds = refreshToken.Lifetime
});
}
When one calls ../token
We get access_token, expires_in, refresh_expires_in, refresh_token and other stuff
Decode access_token to get ValidTo substract expires_in from ValidTo and then add refresh_expires_in to ValidTo and that should give you the expiry date of the refresh_token.

Differences between AcquireTokenAsync and LoginAsync in Xamarin Native

TL;DR
What is the difference between authenticating users with AuthenticationContext.AcquireTokenAsync() and MobileServiceClient.LoginAsync() ?
Can I use the token from the first method to authenticate a user in the second?
Long Version
I've been trying to authenticate users via a mobile device (iOS) for a mobile service in Azure with Xamarin Native (not Forms).
There are enough tutorials online to get you started but in the process, I got lost and confused...
What's working at the moment is the following; which has the user enter his credentials in another page and returns a JWT token which (if decoded here1) has the claims listed here2.
Moreover, this token is authorized in controllers with the [Authorize] attribute in requests with an Authorization header and a Bearer token.
Note: the following constants are taken from the registered applications in Active Directory (Native and Web App / API).
public const string Authority = #"https://login.windows.net/******.com";
public const string GraphResource = #"https://*******.azurewebsites.net/********";
public const string ClientId = "046b****-****-****-****-********0290";
public const string Resource = #"https://******.azurewebsites.net/.auth/login/done";
var authContext = new AuthenticationContext(Authority);
if (authContext.TokenCache.ReadItems().Any(c => c.Authority == Authority))
{
authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority);
}
var uri = new Uri(Resource);
var platformParams = new PlatformParameters(UIApplication.SharedApplication.KeyWindow.RootViewController);
AuthenticationResult authResult = await authContext.AcquireTokenAsync(GraphResource, ClientId, uri, platformParams);
Another working authentication flow I tried is the following; which does the same with the difference that it informs the user that the app requires permissions to access some resources.
If allowed, a JWT token (with less characters than the previous one) is returned with less payload data. This token though, won't pass the authorization attribute just like the previous one.
public const string AadResource = #"https://******.azurewebsites.net/.auth/aad";
var client = new MobileServiceClient(AadResource);
var rootView = UIApplication.SharedApplication.KeyWindow.RootViewController;
MobileServiceUser user = await client.LoginAsync(rootView, "aad");
Obviously, the return type is different, but, what is the main difference between these two authentication methods?
Additionally, another headache comes from trying to achieve this3 at the very end of the article. I already have the token from the first aforementioned method but when I try to follow the client flow with the token in client.LoginAsync() the following error is returned:
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Link References:
https://jwt.io/
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-token-and-claims
https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/chapter2/enterprise/
https://www.reddit.com/r/xamarindevelopers/comments/6dw928/differences_between_acquiretokenasync/
Edit (30 May 2017)
The Why are they different? has been answered on this4 reddit post by the same person (pdx mobilist / saltydogdev) and the simple answer is claims.
Yes. You can insert a token into the MobileServicesClient and then use it had been authenticated directly. That's the beauty of bearer tokens.
Just set the MobileServiceClient CurrentUser:
MobileServiceclient Client;
...
Client.CurrentUser = new MobileServiceUser(username)
{ MobileServiceAuthenticationToken = authtoken};
Edit:
The reason they are different is because each library is requesting a different set of claims. The reason they still work is that the basic information for authenticating/validating the token is there. I'm not sure what are the specific required claims. At a minimum it would be the user id AND that the signature is valid. They are doing the same basic thing, MobileServiceClient just requests less claims.
I believe that the MobileServicesClient can authenticate against Azure AD, if you set up the mobile service correctly. So you should be able to just use the MobileServiceClient.
Here is the document that describes how this works: https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-how-to-configure-active-directory-authentication

tweetsharp - app stops being able to tweet after a few hours

I have a asp.net 4.5 webforms site that allows users to link their account to twitter and tweet directly from my site.
My app is registered with twitter and I am able to successfully authorise my app for the user's account and initially can tweet fine, but after a few hours the tweets stop working. I am using tweetsharp to handle the authorisation.
my code is:
TwitterClientInfo twitterClientInfo = new TwitterClientInfo();
twitterClientInfo.ConsumerKey = ConsumerKey;
twitterClientInfo.ConsumerSecret = ConsumerSecret;
var requestToken = new OAuthRequestToken { Token = oauthtoken };
TwitterService twitterService = new TwitterService(ConsumerKey, ConsumerSecret);
OAuthAccessToken accessToken = twitterService.GetAccessToken(requestToken, oauthverifier);
twitterService.AuthenticateWith(accessToken.Token, accessToken.TokenSecret);
TwitterUser user = twitterService.VerifyCredentials(new VerifyCredentialsOptions());
SendTweetOptions options = new SendTweetOptions();
options.Status = tweetText;
twitterService.SendTweet(options);
what i have noticed is that while the app is successfully tweeting, the accessToken.Token value that is being used to authenticate the user has a proper value (a long string of numbers and upper/lowercase characters) however when it stops tweeting the accessToken.Token value is just a single question mark "?".
Twitter says it doesn't expire tokens so i am at a loss to understand what is happening or how it can be resolved? if i went in to my twitter account and deauthorised my app and went through the authorisation again it would work fine for a few hours, but obviously that's not something i can ask my users to do.
can anyone suggest a resolution to this - either to stop the accessToken value becoming ? or to handle it and get a proper value if it does (without reauthorising the app)
Well, without beginning to understand the actual issue, I managed to fix it
Instead of retrieving the access token every time via:
var requestToken = new OAuthRequestToken { Token = oauthtoken };
OAuthAccessToken accessToken = twitterService.GetAccessToken(requestToken, oauthverifier);
twitterService.AuthenticateWith(accessToken.Token, accessToken.TokenSecret);
i only do that once and store accessToken.Token and accessToken.TokenSecret in the database and retrieve them when tweeting and supply them
twitterService.AuthenticateWith(accessTokenFromDB, accessokenSecretFromDB);
I have seen somewhere that Twitter doesn't expire tokens, so this should work. Certainly it's been working for me all weekend whereas the original code would stop working after a few hours.
Thought this might help some others who have the same issue.

Get Facebook's Application Access Token

I have to use Facebook's notification for my web app.
Facebook Graph API requires the Application Access Token for this action.
Is there a way to get this token by code (C# SDK) or is this generated by Facebook a single time?
Is this token static (and secret) or with expire datetime?
For info: https://developers.facebook.com/tools/access_token/ - App Token, not User Token!
Thanks
The answer is the dynamic way by code:
var fb = new FacebookClient();
dynamic result = fb.Get( "oauth/access_token", new
{
client_id = <myAppID>,
client_secret = <mySecretID>,
grant_type = "client_credentials"
} );
var apptoken = result.access_token;
Or by the combination or appid|secretid
You can just use the concatenation of id and secret with a pipe symbol in the middle:
app_id|app_secret
This is actually how the PHP SDK creates the app access token internally, so there should be no question about the reliability of this method. (From other endpoints where you actively query for an app access token you might get another token that does not match this scheme though.)
you can investigate the getApplicationAccessToken method as in another c# sdk project from github
https://github.com/barans/FacebookCsharpSdk/blob/master/FacebookCSharpSDK/FacebookClient/FacebookClient.cs

Authentication Facebook C# SDK

I have a website where i have a event module, where the users can maintain their own events.
At the same time i have a Facebook Page(not app) and i would really like to create/update/delete the events from my website directly to Facebook.
I have the following working:
FacebookClient clientApp = new FacebookClient(token);
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("name", currentEvent.HeadLine);
DateTime startTime = DateTime.Now;
DateTime endTime = DateTime.Now.AddDays(1);
parameters.Add("start_time", currentEvent.StartDateTime);
parameters.Add("end_time", currentEvent.EndDateTime);
parameters.Add("location", currentEvent.Location);
parameters.Add("description", currentEvent.Description);
var postResult = (IDictionary<string, object>)currentClient.Post("pageid/events", parameters);
the accesstoken used is from my facebook login, so if that expires the system fails.
Any other way or can i get a newer expiring accesstoken.
Regards Keld
regards Keld
You have two options, one is to request the permission offline access from Facebook when you obtain the token. This gives you a token that never expires (unless the user explicitly removes access for your app.
The second way is to handle exceptions from the callback of the method. In the handling code you detect a token expired exception and redirect users to the appropriate login page to get a new token. You can then re-try the event update.

Categories