I'm in the process of updating our app from from oauth 1 to 2. Entire flow works well - I can migrate and save the tokens and access the APIs. However, there is a problem once the original token expires and it gets refreshed. After refreshing, the call to updateTenants does not return any active connections.
My pseudocode is below:
const tokenSet = await getTokenSet(); // Returns saved token set from DB. Assume token is expired!!
const client = new XeroClient(...);
client.setTokenSet(tokenSet);
const newToken = await client.refreshToken();
await saveTokenSet(newToken); // Save to DB
const token = client.readTokenSet();
console.log(token); // Does return my NEW active token set
const tenants = await client.updateTenants(false);
console.log(tenants.body); // This returns an array of length 0
Not clear why the results from updateTenants is empty. I was able to verify this by calling the GET https://api.xero.com/connections endpoint manually with one of the refreshed tokens and also see an empty array in the body.
Any ideas?
I played around with our xero-node-oauth2-app to see if I could recreate this. Here's what I found:
If I connected to my Xero org to obtain valid tokens and then disconnected via the Xero connected apps dashboard and then refreshed my tokens triggering updateTenants the connections endpoint returns an empty array and status code 200. In other words, it's a successful call but Xero doesn't see that the user has authorized your integration to interact with any of their orgs/tenants.
Are you able to verify if your integration is still listed in the connected apps list under settings?
https://community.xero.com/developer/discussion/127403806
Related
When trying to do a password reset or email confirmation, on the flow to run the method
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
It never returns true. Fails with invalid token, even though I checked the token generated and the one passed via email myself. I am not sure if there is something else I am doing wrong. Below is how I generate the code to send via email
var newUser = await _userManager.FindByEmailAsync(requestData.Email);
var code = await _userManager.GeneratePasswordResetTokenAsync(newUser);
This is the same for sending a confirmation email token. I create the user via api call then try to confirm the email token on the IS server not sure if that adds a wrench in my process or not. I am looking for some help to figure out if my workflow to generate then email the token is incorrect and maybe I should be doing some additional work before.
Refresh token returned from Cognito is not a JWT token , hence cannot be decoded. Is there a way to get the refresh token expiry or it needs to be maintained at application level.
There is no way to decode a refresh token. If you know the expiration time set in cognito for refresh tokens you can store the time it was generated and calculate based on that.
just to elaborate on the accepted answer, as I had the same question.
jwt.org cannot decode the refresh token from aws, as it is encrypted
My way around it, is as follows:
the id token carries "auth_time" (see https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-id-token.html)
on login (you could technically do it on refresh as well), I look at that value and add expiration duration to that for a rough estimate
how to get the expiration duration programmatically? There are probably easier ways to do it, but the sdk-v3 command that worked for me was the 'DescribeUserPoolClientCommand' (https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-cognito-identity-provider/classes/describeuserpoolclientcommand.html)
pseudo code in typescript (used in nodejs backend code) looks something like this:
import { CognitoIdentityProviderClient, DescribeUserPoolClientCommand, DescribeUserPoolClientCommandInput} from "#aws-sdk/client-cognito-identity-provider"
import get from 'lodash/get'
const client = new CognitoIdentityProviderClient({ region: [yourRegion] })
const input = {
UserPoolId: [yourUserPoolId],
ClientId: [yourWebClientId],
} as DescribeUserPoolClientCommandInput
const command = new DescribeUserPoolClientCommand(input)
const response = await client.send(command)
const refreshTokenValidityUnits = get(
response,
"UserPoolClient.TokenValidityUnits.RefreshToken"
)
const refreshTokenValidity = get(
response,
"UserPoolClient.RefreshTokenValidity"
)
// result: "days" and "30" for example
This is obviously not complete enough to get the exact values, but enough to get anyone started who, like me, might not be as familiar with the aws-sdk yet.
I'm using Sage Pay token system, evrithyng is working fine I store the tokens on my side. The question is if I want to remove a token is it fine to remove it only from my side, and then if some one wants to add tha card again to create another token or I have to send a request to sagepay with StoreToken = 0 param?
You can remove the token from your side only, but I would recommend sending a REMOVETOKEN request to Sage Pay to remove it (or setting StoreToken=0 on usage) - token storage is charged above a certain threshold. No point paying for something you can't use.....
Your end user can create another token if required.
Here goes the code:
# REMOVE TOKEN REQUEST
if(YourCondition=='OK')
{
$strRemoveTokenURL = "https://test.sagepay.com/gateway/service/removetoken.vsp";
$sToken = 'Token Stored your side';
$strPost = "VPSProtocol=3.00&TxType=REMOVETOKEN&Vendor=yourvendorid&Token=".$sToken;
$arrRemoveResponse = requestPost($strRemoveTokenURL, $strPost);
}
# REMOVE TOKEN RESPONSE
echo '<hr>';
print"<pre>";print_r($arrRemoveResponse);print"<pre>";
exit;
Here's my current operations:
1./ User accepts app and the app callback stores the oauth_token and oauth_token_secret into the database (as access_token and access_token_secret).
2./ We use a cli script to handle autoposting to twitter. We load the twitter oauth object as follows:
public function post()
{
$consumerKey = $this->getConsumerKey();
$consumerSecret = $this->getConsumerSecret();
$accessToken = $this->getAccessToken();
$accessSecret = $this->getAccessSecret();
$twitteroauth = new TwitterOAuth($consumerKey,$consumerSecret,$accessToken,$accessSecret);
$message = $this->getPostMessage();
$result = $twitteroauth->post('statuses/update', array('status' =>$message));
$this->log($result);
}
Now this assumes we are using the API consumer key and secret assigned to the app and the user's stored access tokens.
The result we are getting is:
Invalid or expired token
I don't quite understand why we are receiving this. We are using the access token and access token secret provided to us by twitter.
I did notice that there is a GET parameter oauth_verifier. This isn't something we need to be using somewhere?
In any case, I'm not quite sure whats wrong here.
Do I need to log in or something before doing posting?
your code is correct.
The problem is that the library's Util.urlParameterParse() method is broken.
My problem is I have existing user in database which store the key and secret from the first authentication. I wish to reuse it again when I come back. For the first time authentication, everything working fine. I can use every method call from Dropbox API and the Token(key and secret) was stored in database.
I come back to app and get the Token from database, set it to the session, link current session with API.
session = new WebAuthSession(appKeys, ACCESS_TYPE);
api = new DropboxAPI<WebAuthSession>(session);
String userKey = dropboxUserObj.getUserKey(); //Key from database
String userSecret = dropboxUserObj.getUserSecret();//Secret from database
AccessTokenPair userAccessTokenPair = new AccessTokenPair(userKey, userSecret);
session.setAccessTokenPair(userAccessTokenPair);
It return DropboxUnlinkedException to me when I want to get user data from api using
String userDisplayName = api.accountInfo().displayname;
I have checked on debug mode. Api was linked with the current session. The current session stored Appkey and user's token and correct access type. The point that I doubt is I saw "client = null". I maybe forgot something but I check them all, try every possibilities I can think of but it still return me "DropboxUnlinkedException" which mean I haven't set an access token pair on the session and I didn't revoke access for sure.
Please help me figure out...
I added a screenshot maybe it can illustrate my problem