I am using Evernote SDK for iOS and I am saving the authentication token when the user has authorized access.
Once the user installs my application on a different device, I want to use that token to reauthenticate automatically, but it looks like SDK doesn't support that. Is there a way to do that?
I had the same issue last week, and their SDK indeed doesn't support it out-of-the-box, but after some research I found a solution that works perfectly. This solution mimics a valid authentication flow.
A little background:
When the ENSession
class initializes, it retrieves the credentials that are saved on the keychain (unless [[ENSession sharedSession] unauthenticate]
was called earlier). The problem is that the keychain is empty when using a different device, so our goal is to add a valid ENCredentials
instance to the ENCredentialStore
.
Solution:
Add the following imports to your code: ENCredentials.h
and ENCredentialStore.h
. We will need them later.
Initialize the ENSession
like you already do, using setSharedSessionConsumerKey:(NSString *)key consumerSecret:(NSString *)secret optionalHost:(NSString *)host
.
In order to create a valid ENCredentials
object, we need to provide the following objects:
NSString *
host
NSString *
edamUserId
NSString *
noteStoreUrl
NSString *
webApiUrlPrefix
NSString *
authenticationToken
NSDate *
expirationDate
The host
is always www.evernote.com
(as defined in ENSession
under ENSessionBootstrapServerBaseURLStringUS
).
edamUserId
is the user id you received when you got the original token. Same for the expirationDate
. If you are not sure how to get them then you should use [[ENSession sharedSession].userStore getUserWithSuccess:^(EDAMUser *user)
once authenticated.
So the only objects that are actually missing are noteStoreUrl
and webApiUrlPrefix
. Their format is always:
- noteStoreUrl:
https://www.evernote.com/shard/edam_shard/notestore
- webApiUrlPrefix:
https://www.evernote.com/shard/edam_shard/
Luckily, your token already contains edam_shared
(value of S=
, see this):
@"S=s161:U=5ce3f20:E=1561182201b:C=24eb9d000f8:P=285:A=app:V=2:H=e8ebf56eac26aaacdef2f3caed0bc309"
If you extract s161
and put it in the URLs above it will work (I am sure you know how to extract that, but let me know if you're having problems).
Now we are ready to authenticate using the token. First, expose the necessary functions from ENSession using a category:
@interface ENSession(Authentication)
- (void)startup;
- (void)addCredentials:(ENCredentials *)credentials;
@end
And authenticate using the token:
ENCredentials *credentials = [[ENCredentials alloc] initWithHost:ENSessionBootstrapServerBaseURLStringUS edamUserId:userId noteStoreUrl:noteStoreUrl webApiUrlPrefix:webApiUrlPrefix authenticationToken:token expirationDate:expirationDate];
[[ENSession sharedSession] addCredentials:credentials];
[[ENSession sharedSession] startup];
The last line is important in order to refresh the ENSession
and retrieve the new stored credentials.
Now you are authenticated and ready to query the SDK. Good luck.