I'm developing a Word Add-in and using auth.getAccessTokenAsync for authentication as defined here: https://dev.office.com/reference/add-ins/shared/office.context.auth.getAccessTokenAsync.
I obtain the access token successfully but then I'm encountering an error in the "on behalf of" flow described here: https://learn.microsoft.com/en-us/office/dev/add-ins/develop/authorize-to-microsoft-graph.
While using MSAL (Microsoft.Identity.Client) to validate the bootstrap access token and get a token for Microsoft Graph I get an error. Code and error details below.
Code:
var cl = new ConfidentialClientApplication(<client ID>,
"https://login.microsoftonline.com/" + <tenant ID>,
<redirect uri>,
new Microsoft.Identity.Client.ClientCredential(<client secret>),
new Microsoft.Identity.Client.TokenCache(),
new Microsoft.Identity.Client.TokenCache());
var authResult = await cl.AcquireTokenOnBehalfOfAsync(new[] {
"Sites.Read.All"
},
new Microsoft.Identity.Client.UserAssertion(accessToken));
Error:
AADSTS50013: Assertion contains an invalid signature. [Reason - The provided signature value did not match the expected signature value., Found key 'Start=02/18/2018, End=02/19/2020, Thumbprint=oZkMJ7Omv9GN7JVM', Configured keys: [Key0:Start=02/18/2018, End=02/19/2020, Thumbprint=oZkMJ7Omv9GN7JVM;Key1:Start=03/31/2018, End=03/31/2020, Thumbprint=xq4mEGikJ5Bkblfw;Key2:Start=11/16/2016, End=11/16/2018, Thumbprint=i1DVz66b9dfpPV3Z;]]\r\nTrace ID: 6ec996c8-517c-4baa-815b-54cee7913f00\r\nCorrelation ID: 4cc9d7dd-3879-4be4-a067-ed80eaaaad1d\r\nTimestamp: 2018-04-24 07:10:23Z
If I make a regular web app (not an Office add-in) and use MSAL.js to get an access token, that token validates fine.
As far as I can tell, there's a difference in the signature of the MSAL.js token versus the Word Add-in token. I'm using the same scopes, client ID and tenant ID.
The solution was to make sure that I'm getting the token correctly from the Word Add-in. IE11 F12 Developer Tools truncates strings when outputting a variable in the console window, so I just printed it on the UI instead and it works fine now.
Thanks Wayne Yang for helping me get to this point. :)
Related
I'm trying to use the Quip admin and automation APIs to add members to a document from a Salesforce trigger.
I've successfully used the GET methods for verify token and get user from the automation API, but I'm getting an error when I call add members from the Admin API. The error I'm getting is 'Missing argument thread_id', despite passing in a valid thread id. If I copy the body from the request into Postman it works fine. The Salesforce org is a developer sandbox.
These are the debug lines from Salesforce:
USER_DEBUG [332]|DEBUG|System.HttpRequest[Endpoint=https://platform.quip.com/1/admin/threads/add-members?company_id=JKNAcB0VIMy, Method=POST]
USER_DEBUG [336]|DEBUG|Body req = {"thread_id":"eNiVAcaDICco","member_ids":"KPDAFRZtNRW"}
USER_DEBUG [337]|DEBUG|Body response = {"error":"application_error","error_code":400,"error_description":"Missing argument 'thread_id'"}
USER_DEBUG [339]|DEBUG|Method = POST
USER_DEBUG [340]|DEBUG|Scope = USER_READ ADMIN_MANAGE
USER_DEBUG [341]|DEBUG|Authorisation = Bearer UkRQQU1AcXymZ1M=|1692717157|N4CCVoKA8MY4sNF/+mBeWzX5lXAeI/q/YKxSMhC9PJc=
Any help would be much appreciated
I found the issue, it was the content-type in the header, it needed to be set to set to application/json
I am using the python3.7.2 module simple-salesforce==0.74.2 and I am having trouble trying to establish a connection to my salesforce sandbox. I can login to the salesforce production with the same credentials just fine like so:
from simple_salesforce import Salesforce
sf = Salesforce(username='user#domain.com', password='pswd', security_token='mytoken')
Okay cool. Now I attempt to login to my sandbox with the following:
sf = Salesforce(username='user#domain.com.sandbox_name', password='pswd', security_token='mytoken', sandbox=True)
And I get the error:
simple_salesforce.exceptions.SalesforceAuthenticationFailed:
INVALID_LOGIN: Invalid username, password, security token; or user
locked out.
So I tried logging in with a different method:
sf = Salesforce(username='user#domain.com.sandbox_name', password='pswd', security_token='mytoken', domain='sandbox_name')
And this gave a different error:
requests.exceptions.ConnectionError:
HTTPSConnectionPool(host='sandbox_name.salesforce.com', port=443): Max
retries exceeded with url: /services/Soap/u/38.0 (Caused by
NewConnectionError(': Failed to establish a new connection: [Errno 8]
nodename nor servname provided, or not known'))
I am using a Developer sandbox, named sandbox_name, following salesforce's instructions. Can someone give some advice on what I am doing incorrectly?
Solved. Set domain='test' and generate a new token under your sandbox account
this didn't work for me, but what did was:
`sf = Salesforce(
username='my.email#test.com',
password='sadfd8d8d8',
security_token='d8d8asd8f8d8',
instance_url='https://my-dev-org-instance-dev-ed.my.salesforce.com')`
The advice here may be a bit deprecated. After a bit of tinkering, I was able to get the simple_salesforce library working with the Salesforce sandbox on a custom domain with the following code. Note the domain that I am passing to the api as well the sand_box name that needs to be appended to the username.
from simple_salesforce import Salesforce
USER = "user#domain.com.sandbox_name"
PASS = "pass"
SEC_TOKEN = "token"
DOMAIN = "<domain>--<sandbox_name>.<instance>.my"
sf = Salesforce(username=USER, password=PASS, security_token=SEC_TOKEN, domain=DOMAIN)
i have got Access token from "https://oauth.intuit.com/oauth/v1/get_request_token" using rest api in apex. when i pass the response to the authorizaiton url as shown below
https://appcenter.intuit.com/Connect/Begin?oauth_token_secret=xEtlEPu7ljKAeWRYM6pZwY02e8ewZcZ2txR1xpix&oauth_callback_confirmed=true&oauth_token=qyprdc5t2G9j8TcR8AW1123BCD3iy4M0PSBwsk84Rl8WhmCa
i get this error
Oops! An error has occurred.
Please close this window and try again.
Error Code: no_such_database
Message: Application not found by appToken
Any kind of help will be much appriciable
I am not sure if you figured it out but the URL for authorization actually seems different from documentation :
https://appcenter.intuit.com/Account/DataSharing/Authorize?oauth_token=YYYY
I used this url for authorization and it worked.
Instead of old user authorization link (https://appcenter.intuit.com/Connect/Begin ) use the new link (https://appcenter.intuit.com/Account/DataSharing/Authorize)
After generating the request token and secret , redirect to the new link. This will lead to the user authorization pages. Once authorized it will redirect back to our callback url.
Code Example :
$userAuthUrl = "https://appcenter.intuit.com/Account/DataSharing/Authorize";
$signedUrl = "{$userAuthUrl}?oauth_callback={$callBackUrl}&oauth_consumer_key={$consumerKey}&oauth_nonce={$nonce_random}&oauth_signature_method=HMAC-SHA1&oauth_timestamp={$timestamp}&oauth_token={$reqToken}&oauth_version=1.0&oauth_signature={$signature}";
header("Location:$signedUrl");
Authorized URL is not correct.
It should be like -
https://appcenter.intuit.com/connect/begin?oauth_token=qyprdsGhfVztCxWPDIXbPYjVybkwxNAvUdNNaiaTabcde
Here oauth_token is actually request_token (not request_secret) which you get as part of the first call OAuth1.0a flow.
ie. https://oauth.intuit.com/oauth/v1/get_request_token
Please refer this sample Java code which shows all the 3 steps required to generate accessToken and accessSecret (OAuth1.0a).
https://gist.github.com/manas-mukh/b6450bb28506e1302463
I used DREdit app's Oauth code to get accessToken and refreshToken for my app and i am getting the accessToken but refreshToken is coming null always.
I tried to print the values in the code which comes like below
authorization URL:https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force&client_id=651991573332.apps.googleusercontent.com&redirect_uri=http://www.sakshum.org/GoogleOauth&response_type=code&scope=https://www.googleapis.com/auth/drive.file%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile
This code already has access_type=offline which I found not having in the url was the cause in some cases. Please advise what else could be wrong here.
The log prints as follows on appEngine
[s~sakshumweb-hrd/3.368699522239285323].<stdout>: Code:4/XQ1sR1Pu5VHDqGbG9iJO10bXVCCE.Qn-L1XwrBVYaEnp6UAPFm0EmSoCXfwI
W 2013-07-10 20:20:16.294
com.google.api.client.googleapis.services.AbstractGoogleClient <init>: Application name is not set. Call Builder#setApplicationName.
I 2013-07-10 20:20:16.536
[s~sakshumweb-hrd/3.368699522239285323].<stdout>: id:113470899999229420779
I 2013-07-10 20:20:17.936
[s~sakshumweb-hrd/3.368699522239285323].<stdout>: access token:ya29.AHES6ZSP7MXaaUhMz4RO7Jm3Zkh_s1zUxJyzW_6IvfADaQ
I 2013-07-10 20:20:17.936
[s~sakshumweb-hrd/3.368699522239285323].<stdout>: refresh token:null
Refresh tokens are only issued on the initial authorization (whenever the consent screen is shown.) If you find you're in a state where you don't have a saved refresh token for a user, you can ask for reauthorization with the added query parameter prompt=consent. The user will be asked to re-authorize and a new refresh token will be generated.
After your link you get authorization code. For instance:
https://accounts.google.com/o/oauth2/auth?access_type=offline
&approval_prompt=auto
&client_id=[your id]
&redirect_uri=[url]
&response_type=code
&scope=[access scopes]
&state=/profile
then if in future you are going to have access to drive you need refresh token (you can every time request auth token - redirecting to google and etc... but it's not good way. after first usage, you should save Credentials in Database with User UID (for instance, it may be mail). So if you need to have access to the drive in the feature you do this:
static Credential exchangeCode(String authorizationCode)
throws CodeExchangeException {
try {
GoogleAuthorizationCodeFlow flow = getFlow();
GoogleTokenResponse response =
flow.newTokenRequest(authorizationCode).setRedirectUri(REDIRECT_URI).execute();
return flow.createAndStoreCredential(response, null);
} catch (IOException e) {
System.err.println("An error occurred: " + e);
throw new CodeExchangeException(null);
}
}
As I guess you also want to get url of the file which is in the Google Drive. when you get files - thee the documentation, then you will find download methids in com.google.api.services.drive.model.File object. read documentations
I am using iOS 6 Social framework for accessing user's Facebook data. I am trying to get likes of the current user within my app using ACAccount and SLRequest. I have a valid Facebook account reference of type ACAccount named facebook, and I'm trying to get user's likes this way:
SLRequest *req = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodGET URL:url parameters:nil];
req.account = facebook;
[req performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
//my handler code.
}
where url is #"https://graph.facebook.com/me/likes?fields=name"; In my handler, I'm getting this response:
{
error = {
code = 2500;
message = "An active access token must be used to query information about the current user.";
type = OAuthException;
};
}
Shouldn't access tokens be handled by the framework? I've found a similar post Querying Facebook user data through new iOS6 social framework but it doesn't make sense to hard-code an access token parameter into the URL, as logically the access token/login checking should be handled automatically by the framework. In all examples that I've seen around no one plays with an access token manually:
http://damir.me/posts/facebook-authentication-in-ios-6
iOS 6 Facebook posting procedure ends up with "remote_app_id does not match stored id" error
etc.
I am using the iOS6-only approach with the built in Social framework, and I'm not using the Facebook SDK. Am I missing something?
Thanks,
Can.
You need to keep a strong reference to the ACAccountStore that the account comes from. If the store gets deallocated, it looks like it causes this problem.
Try running on an actual device instead of a simulator. This worked for me.
Ensure that your bundle id is input into your Facebook app's configuration. You might have a different bundle id for your dev/debug build.