Evernote SetSharedSessionConsumerKey Does not Work in Outlook VBA Macro - evernote

I have a VBA macro in Outlook that moves a selected message into my archive folder and gets a url for the message. I also would like to add the message to Evernote like the "Save to Evernote" add-in and automatically add the url to the message as the url of the note.
I downloaded the COM setup for the Evernote Cloud SDK:
https://github.com/evernote/evernote-cloud-sdk-windows/tree/master/COM%20Setup
I then registered for and received my Evernote API Key for this application (Consumer Key and Consumer Secret).
I have an account in the sandbox.
I added a reference to the Evernote Cloud SDK and wrote some simple code to test that it is working.
However, the following code fails when checking the SharedSession.IsAuthenticated.
The code:
Public Sub CreateNote()
Const Key = "MY KEY"
Const Secret = "MY SECRET"
Const Host = "sandbox.evernote.com"
Dim evernoteSession As New ENSessionForCOM
Call evernoteSession.SetSharedSessionConsumerKey(Key, Secret, Host)
If evernoteSession.SharedSession.IsAuthenticated = False Then
evernoteSession.SharedSession.AuthenticateToEvernote
End If
End Sub
The error:
Run-time error '-2147024809 (80070057)'
Cannot create shared Evernote session without either a valid
consumer key/secret pair, or a developer token set.
I thought maybe I was trying too soon, but it has been almost 24 hours. What am I doing wrong?

After a lot of trial and error, I finally found a solution. Instead of an ENSessionForCOM, I needed to create an ENSessionAdvancedForCOM object. So now the code looks like this:
Public Sub CreateNote()
Const Key = "MY KEY"
Const Secret = "MY SECRET"
Const Host = "sandbox.evernote.com"
Dim evernoteSession As New ENSessionAdvancedForCOM
Call evernoteSession.SetSharedSessionConsumerKey(Key, Secret, Host)
If evernoteSession.SharedSession.IsAuthenticated = False Then
evernoteSession.SharedSession.AuthenticateToEvernote
End If
End Sub
And it now authenticated.

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

Signalr send message from browser to .net client on the same machine

We need to communicate a native application with a web application.
We think to use signalr to send the message/command.
The pipeline would be:
User clicks to make an action.
Javascript (with signalr) send a message to a server in azure.
The server re-send the message a specific client. It must be the client installed on the same machine.
Once the result is completed, NET sends the resulting reverse.
The matter is, How I can find client from the same machine in the signalr Server?
The organization in our system is:
There is center/gym.
Every center has staff who can login.
We could identify client at the same center with some file configuration. Saving our key center, for example. But, in a center, could there are more than one.NET client installed on the different computer.
We think to use the private IP of the computer to make a key on the signalr server.
var ips = [];
var RTCPeerConnection = window.RTCPeerConnection ||
window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
var pc = new RTCPeerConnection({
// Don't specify any stun/turn servers, otherwise you will
// also find your public IP addresses.
iceServers: []
});
// Add a media line, this is needed to activate candidate gathering.
pc.createDataChannel('');
// onicecandidate is triggered whenever a candidate has been found.
pc.onicecandidate = function (e) {
if (!e.candidate) { // Candidate gathering completed.
pc.close();
console.log(ips);
return;
}
var ip = /^candidate:.+ (\S+) \d+ typ/.exec(e.candidate.candidate)[1];
ips.push(ip);
};
pc.createOffer(function (sdp) {
pc.setLocalDescription(sdp);
}, function onerror() { });
This data can be obtained in .NET client without a problem. But in javascript, the previous code works regularly. In some PC, it only returns ipv4. And in Mozilla it doesn't work.
How can we identify both clients? Do You know another way to reach the goal?
Thanks,
Finally, we didn't find a good solution filtering ip adress.
We did the as follow:
We used URI schema to launch our app. URI Schema windows
Public Class RegistrarURI
Const URI_SCHEME As String = "xxx"
Const URI_KEY As String = "URL:xxx"
Private Shared APP_PATH As String = Location.AssemblyDirectory() ' "C:\Program Files (x86)\xxx.exe"
Public Shared Sub RegisterUriScheme()
Using hkcrClass As RegistryKey = Registry.ClassesRoot.CreateSubKey(URI_SCHEME)
hkcrClass.SetValue(Nothing, URI_KEY)
hkcrClass.SetValue("URL Protocol", [String].Empty, RegistryValueKind.[String])
Using defaultIcon As RegistryKey = hkcrClass.CreateSubKey("DefaultIcon")
Dim iconValue As String = [String].Format("""{0}"",0", APP_PATH)
defaultIcon.SetValue(Nothing, iconValue)
End Using
Using shell As RegistryKey = hkcrClass.CreateSubKey("shell")
Using open As RegistryKey = shell.CreateSubKey("open")
Using command As RegistryKey = open.CreateSubKey("command")
Dim cmdValue As String = [String].Format("""{0}"" ""%1""", APP_PATH)
command.SetValue(Nothing, cmdValue)
End Using
End Using
End Using
End Using
End Sub
End Class
In an Azure WebApp we launch a SignalR Server. This server will send data from our .NET app to Chrome.
To achive that, when the web is loaded, we connect to the signalR server. To build de uri, We send the connectionId from Javascript client to the .NET Client.
Then, when the native process is completed. .NET client send the information to signalR server, and this server mirrored the data to javacript client using the connectionId.
To avoid launch some instance of our native app, we use IPC channel to send data to one instance to the previous and closind the new one.
Link to source Blog source

Evernote Windows SDK Csharp SampleAppAdvanced - can't authenticate

I am trying to run the Csharp sampleAppAdvanced from this code https://github.com/evernote/evernote-cloud-sdk-windows
I substituted the consumer key and secret with those that I got in the email when I requested the API key.
ENSessionAdvanced.SetSharedSessionConsumerKey("xyz","123","sandbox.evernote.com");
if (ENSession.SharedSession.IsAuthenticated == false)
{
ENSession.SharedSession.AuthenticateToEvernote();
}
But I always end up hitting an error at this point
ENNoteRef myRef = ENSession.SharedSession.UploadNote(myNoteAdv, null);
With exception reading "Exception of type 'EvernoteSDK.ENAuthExpiredException' was thrown."
On the console the error reads "EvernoteSDK: ENSession is unauthenticating."
Am I missing something? I know the Application is authorized for access.
The other sample code called sampleApp, doesn't throw an error but doesn't display notes either.
When you register the api, did you choose Basic Access or Full Access?

ADAL Token Not Refreshing

I have a ASP.NET webforms application in which I'm using Azure Key Vault in association with Azure Active directory. I've used the guide found here https://azure.microsoft.com/en-us/documentation/articles/storage-encrypt-decrypt-blobs-key-vault/
for getting a token from Azure Active Directory for my application and using it to access my key vault, which I'm ultimately using for storage encryption. Everything works well the first time the application requests a token, but after the token expires (an hour later). The application will not retrieve a new token as it should. I'm using the latest stable release Microsoft.IdentityModel.Clients.ActiveDirectory 2.19.208020213, and did try the latest pre-release (3.5.208051316-alpha) as well.
The GetToken method looks like this
Public Async Function GetToken(authority As String, resource As String, scope As String) As Task(Of String)
Dim authContext = New AuthenticationContext(authority)
Dim clientCred As New ClientCredential(CloudConfigurationManager.GetSetting("ClientID"), CloudConfigurationManager.GetSetting("ClientSecret"))
System.Diagnostics.Trace.TraceInformation("Attempting to acquire auth token")
Dim result As AuthenticationResult = await authContext.AcquireTokenAsync(resource, clientCred)
System.Diagnostics.Trace.TraceInformation("Auth returned")
If result Is Nothing Then
System.Diagnostics.Trace.TraceInformation("Auth was null")
Throw New InvalidOperationException("Failed to obtain the JWT token")
End If
System.Diagnostics.Trace.TraceInformation("Returning auth access token")
Return result.AccessToken
End Function
Which is used here to get a connection to the key vault
Dim cloudResolver As New KeyVaultKeyResolver(AddressOf GetToken)
The GetToken method just hangs at AcquireTokenAsync. I've turned on verbose logging in ADAL and this is what the log shows and it stops and GetToken never returns.
-Application: 2015-09-21T17:12:13 PID[8884] Information 9/21/2015 5:12:13 PM: 19ce5dc3-d618-48e9-8bbd-c5b3ad31bfc2 - TokenCache: Looking up cache for a token...
-Application: 2015-09-21T17:12:13 PID[8884] Information 9/21/2015 5:12:13 PM: 19ce5dc3-d618-48e9-8bbd-c5b3ad31bfc2 - TokenCache: An item matching the requested resource was found in the cache
-Application: 2015-09-21T17:12:13 PID[8884] Information 9/21/2015 5:12:13 PM: 19ce5dc3-d618-48e9-8bbd-c5b3ad31bfc2 - TokenCache: An expired or near expiry token was found in the cache
-Application: 2015-09-21T17:12:13 PID[8884] Information 9/21/2015 5:12:13 PM: 19ce5dc3-d618-48e9-8bbd-c5b3ad31bfc2 - TokenCache: An old item was removed from the cache
Further, I tried turning off token caching by setting the token cache to Nothing and then ADAL wouldn't even retrieve the access token the first time.
I found the answer in this similar question Azure KeyVault Active Directory AcquireTokenAsync timeout when called asynchronously
The key was to remove any of these and replace the them with await
.GetAwaiter().GetResult()
For example this was the original
Dim theKey = cloudResolver.ResolveKeyAsync($"{CloudConfigurationManager.GetSetting("KeyVaultUrl")}Secret/", CancellationToken.None).GetAwaiter().GetResult()
Which has been replaced with
Dim theKey = await cloudResolver.ResolveKeyAsync($"{CloudConfigurationManager.GetSetting("KeyVaultUrl")}Secret/", CancellationToken.None)

Get token from ADFS

I'm trying to obtain a token from ADFS to that I can use it with an on-premise Windows Service Bus installation. I may not have ADFS properly configured because I get the following message:
MSIS3127: The specified request failed.
The code to access the token is as follows:
string adrecaSTS = "trust/13/usernamemixed";
WS2007HttpBinding binding = new WS2007HttpBinding();
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Mode = SecurityMode.TransportWithMessageCredential; //https
string baseSSLUri = #"https://<myadfs>/adfs/services/";
WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(binding, new EndpointAddress(baseSSLUri + adrecaSTS));
trustChannelFactory.TrustVersion = TrustVersion.WSTrust13;
trustChannelFactory.Credentials.UserName.UserName = "username";
trustChannelFactory.Credentials.UserName.Password = "password";
WSTrustChannel tokenClient = (WSTrustChannel)trustChannelFactory.CreateChannel();
//create a token issuance issuance
RequestSecurityToken rst = new RequestSecurityToken(RequestTypes.Issue);
//call ADFS STS
SecurityToken token = tokenClient.Issue(rst);
The endpoint is enabled on ADFS and my client (laptop on separate domain) trusts the certificate from ADFS.
Do I need to set up some kind of trust or something further? This error message is not particularly helpful.
See here:
https://github.com/thinktecture/Thinktecture.IdentityServer.v2/blob/master/src/Libraries/Thinktecture.IdentityServer.Protocols/WSFederation/HrdController.cs
The ValidateToken method has most of the code - but you first need to extract the InnerXml from the generic token and turn that into a SAML security token (again using a token handler).
Found the issue. I was trying to log on as an administrator account. When I used a regular user it worked.
I also had to modify the RequestSecurityToken to have a KeyType of KeyType.Symmetric
I see that you solved your issue, but here is some additional inforamation to potentially help others that might have the same error message but a different cause.
The AD FS error, "MSIS3127...", can have multiple causes. For us, it was caused by one of our relying party claim rules specifying an AD FS attribute store that didn't exist.
In order to debug the error, we checked the Event Viewer on all of the servers running AD FS, and that's where we found the detailed message that called out the attribute store problem. So, if anyone else gets the same error message, then I suggest checking the Event Viewer on AD FS to see if there are additional logs.
Note that AD FS logs to the Event Viewer under the folder/node of Applications and Services Logs => AD FS => Admin

Resources