Dropbox Error Opens Another App on device, not on simulator - ios

I have three apps that upload files to Dropbox. Same code for all three. They all share the same folder so I've used same secret key etc
Heres where it gets weird
1. All was fine for few months
2. Now on apps 2 and 3 when the user tries to log in it opens the first app?
3. Logging out and in, no help, just says Theres a an error connecting to Dropbox and to try later
What ive tried
Creating seprate secret keys etc for all three apps rathe rthan sharing the same, still get the same behaviour?
Some research on this suggested that Dropbox has changed the way it links to users accounts through applications and remins linked even if you delete the app? Has anyone else got any experience with this?
Appdelegate
NSString* appKey = #"00000000000";
NSString* appSecret = #"0000000000";
NSString *root = kDBRootAppFolder;
DBSession* session =
[[DBSession alloc] initWithAppKey:appKey appSecret:appSecret root:root];
session.delegate = self; // DBSessionDelegate methods allow you to handle re-authenticating
[DBSession setSharedSession:session];
[DBRequest setNetworkRequestDelegate:self];
Button Handler in viewController
LogCmd();
self.publishButtonPressed = YES;
if (![[DBSession sharedSession] isLinked]) {
[self loginLogoutButtonPressed:nil];
} else {
DBRestClient *restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
NSError *error = nil;
NSString *filePath = [ICUtils pathForDocument:self.fileName];
[self.pdfData writeToFile:filePath options:0 error:&error];
if (nil == error) {
[restClient uploadFile:self.fileName
toPath:#"/"
withParentRev:nil
fromPath:filePath];
} else {
[ICUtils raiseAlertWithTitle:#"An error occurred" message:[error localizedDescription]];
}
}
}
Note works ok on the simulator, problem is only present on device

That is because you are using the same key for multiple applications. The Dropbox app is communicating with your app through a custom URL scheme - to launch your app (because there is no other way to launch apps programmatically on iOS).
In other words, the Dropbox app tells the system to open "db-yoursecretkey://somemessage" which opens the registered app for that custom URL scheme. Unfortunately, all of your apps use the same custom scheme as they are all using the same key, so the system just picks one: most likely the first one.
However, you can grant your apps access to all folders in dropbox, thus effectively sharing folders. So it's not really necessary to have all three apps using the same key.

Related

Access control for iOS App with Azure AD users

I have an iOS app which is already in the app store, and i am authenticating users of my app through my web api. The app accessed by the users and this access given manually. In the next release i just want to control the access to my app with Azure AD i.e, the app get accessed by only users who are configured in the Azure AD.
I am new to Azure AD. I have gone through with multiple documents from Microsoft Azure started from https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-ios-get-started and all the docs/stuff confused me and i just came to know ADAL is the library which need to be used to get authenticated from Azure AD.
Please suggest me from where to start and what need to be followed/done. I have checked https://github.com/Azure-Samples/active-directory-ios and other related Azure native app libraries for objective-c.
Thanks in advance.
If you just want to authenticate against Azure AD, you don't need any mobile backend - just the ADAL library and an appropriate configuration for a Native App in Azure AD.
Firstly, configure Azure AD for a Native Mobile App:
Log in to the Azure Classic Portal (https://manage.windowsazure.com)
Select the appropriate directory from your list of all items
Click on the APPLICATIONS tab
Click on the ADD button at the bottom of the page
Click on Add an application my organization is developing
Give it a name, then select NATIVE CLIENT APPLICATION as the Type
Enter a valid URI for the redirect URI (it can be anything, but it has to be valid)
Click on the tick to create the application.
At this point, you've created the app. Click on the CONFIGURE tab and note the Client ID and Redirect URI.
You can now use any of the samples by replacing the Client ID and the Redirect URI for the ADAL library. Here is the relevant code from one of the samples:
- (void)acquireTokenInteractive:(id)sender
{
ADTestAppSettings* settings = [ADTestAppSettings settings];
NSString* authority = [settings authority];
NSString* resource = [settings resource];
NSString* clientId = [settings clientId];
NSURL* redirectUri = [settings redirectUri];
ADUserIdentifier* identifier = [self identifier];
ADCredentialsType credType = [self credType];
BOOL validateAuthority = _validateAuthority.selectedSegmentIndex == 0;
ADAuthenticationError* error = nil;
ADAuthenticationContext* context = [[ADAuthenticationContext alloc
initWithAuthority:authority
validateAuthority:validateAuthority
error:&error];
if (!context)
{
NSString* resultText = [NSString stringWithFormat:#"Failed to create AuthenticationContext:\n%#", error];
[_resultView setText:resultText];
return;
}
[context setCredentialsType:credType];
if ([self embeddedWebView])
{
[context setWebView:_webView];
//[_authView setFrame:self.view.frame];
[UIView animateWithDuration:0.5 animations:^{
[_acquireSettingsView setHidden:YES];
[_authView setHidden:NO];
}];
}
__block BOOL fBlockHit = NO;
[context acquireTokenWithResource:resource
clientId:clientId
redirectUri:redirectUri
promptBehavior:[self promptBehavior]
userIdentifier:identifier
extraQueryParameters:nil
completionBlock:^(ADAuthenticationResult *result)
{
if (fBlockHit)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController* alert = [UIAlertController
alertControllerWithTitle:#"Error!"
message:#"Completion block was hit multiple times!"
preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
});
return;
}
fBlockHit = YES;
dispatch_async(dispatch_get_main_queue(), ^{
[self updateResultView:result];
[_webView loadHTMLString:#"<html><head></head><body>done!</body></html>" baseURL:nil];
[_authView setHidden:YES];
[self.view setNeedsDisplay];
[[NSNotificationCenter defaultCenter] postNotificationName:ADTestAppCacheChangeNotification object:self];
});
}];
}

Using RoutingHTTPServer to redirect iOS mdm configuration profile?

Using my Native iOS app to setup an MDM device takes the user out of the App to load Safari to initiate the MDM Configuration Profile Installation and then returns to Safari.
What I would like to do, is return back to the Application.
I know this can be done with RoutingHTTPServer as documented here but I can't seem to get a MDM Configuration Profile Post request to work with it.
Any help, much appreciated.
Using the code in the other post from #xaphod, I got it working as below but it's still not very good.
Basically I need Safari to load the profile, the user installs it the profile then clicks Done and when Safari re-opens it will direct the user back to the app.
I don't think it can be done, maybe the best workaround is hosting a webpage to do the redirection back to the app.
start server and setup routes
self.firstTime = true;
self.httpServer = [[RoutingHTTPServer alloc] init];
[self.httpServer setPort:8000];
[self.httpServer handleMethod:#"GET" withPath:#"/start" target:self selector:#selector(handleMobileconfigRootRequest:withResponse:)];
[self.httpServer handleMethod:#"GET" withPath:#"/load" target:self selector:#selector(handleMobileconfigLoadRequest:withResponse:)];
[self.httpServer start:NULL];
then to begin,
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"http://localhost:8000/start/"]];[/code]
which will load Safari with a JS timer
- (void)handleMobileconfigRootRequest:(RouteRequest *)request withResponse:(RouteResponse *)response
{
[response respondWithString:#"<HTML><HEAD><title>Profile Install</title>\
</HEAD><script> \
function load() { window.location.href='http://localhost:8000/load/';} \
var int=self.setTimeout(function(){load()},600); \
</script><BODY></BODY></HTML>"];
}
first timer loads the profile in Safari, then second re-direct to the app
- (void)handleMobileconfigLoadRequest:(RouteRequest *)request withResponse:(RouteResponse *)response
{
if (self.firstTime)
{
self.firstTime = FALSE;
NSData *mobileConfigFile = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://mobileconfigfileUrl"]];
[response setHeader:#"Content-Type" value:#"application/x-apple-aspen-config"];
[response respondWithData:mobileConfigFile];
}
else
{
[response setStatusCode:302];
[response setHeader:#"Location" value:#"CustomAppUrl://"];
}
}

Is it possible to get the value of USE TOUCHID FOR iPhone unlock in default settings

Is it possible to Access Default settings > TouchID & Passcode > iPhone Unlock toggle value.
As far as I know, it's not possible.
NO. there is no way to know if user has opted for using TouchID for Unlocking phone.
There is method canEvaluatePolicy: error:
But this tells you if TouchId is configured / Enabled or Not Configured/Not Enabled. If you want to check for Availability of touch Id for your app, you can use canEvaluatePolicy: error:
-(void)canEvaluatePolicy {
LAContext *context = [[LAContext alloc] init];
__block NSString *message;
NSError *error;
BOOL success;
// test if we can evaluate the policy, this test will tell us if Touch ID is available and enrolled
success = [context canEvaluatePolicy: <BR>LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
if (success) {
message = [NSString stringWithFormat:#"Touch ID is available"];
}
else {
message = [NSString stringWithFormat:#"Touch ID is not available"];
}
[super printMessage:message inTextView:self.textView];
}
you can find fully working code from developer.apple.com website:
https://developer.apple.com/library/content/samplecode/KeychainTouchID/Listings/KeychainTouchID_AAPLLocalAuthenticationTestsViewController_m.html
I don't know why you would want to know that however, you can always check if the device supports TouchID and if it has been setup by the user. You do this by creating an LAContext (Local Authentication Context) and calling the function canEvaluatePolicy:error:. That is all I think you can find out about the TouchID settings on a given iPhone through an app. I hope this helps a little :)

Office 365 iOS: Not able to fetch List Items from Office 365 SDK

I have added the announcement app and added few items to it, now i want to fetch the items from my announcement list so I have used the below code
token_Obtained_During_first_time_Login: This is the token that i get when i login for the first time using the acquireTokenWithResource method of ADAuthenticationContext class
- (void)getClientList {
NSString *appToken = [[NSUserDefaults standardUserDefaults]
valueForKey:#"token_Obtained_During_first_time_Login"];
NSString* hostName = #"https://myTenant.sharepoint.com/sites/myApp";
OAuthentication *credentials = [[OAuthentication alloc] initWith:appToken];
ListClient *client = [[ListClient alloc]
initWithUrl:hostName
credentials:credentials];
NSURLSessionTask* task = [client getListItems:#"MyAnnouncements"
callback:^(NSMutableArray *listItems, NSError *error) {
if (error==nil) {
NSLog(#"%#",listItems);
}
}];
[task resume];
}
I have even debugged the 365 code and it provides me the below URL for getListItems: callback method
https://myTenant.sharepoint.com/sites/myApp/_api/lists/GetByTitle('MyAnnouncements')/Items
I have even tried the same using getTokenWith method which comes with the sample code
- (void)getAnnouncementList:(void (^)(ListClient *))callback{
NSString* hostName = #"https://myTenant.sharepoint.com";
[self getTokenWith:hostName :true completionHandler:^(NSString *token) {
OAuthentication *credentials = [[OAuthentication alloc] initWith:token];
callback([[ListClient alloc]initWithUrl:hostName credentials:credentials]);
}];
}
But still no luck i get the list as nil
Please guide on how this can be resolved, I have even verified the rights in the Azure Directory everything seems fine am able to fetch data of one drive, mails and calendar but list is a place where i am stuck.
Every time i call the above code i get the response nil not sure what am passing wrong, my guess is the token.
I resolved this issue by making a change in the apiUrl present in the ListClient.m file of Office 365.
All i did was changed it to
const NSString *apiUrl = #"/sites/mobileApp/_api/web/Lists";
Making the above change did the trick and now i can access all the list data.

Opening a Datastore in iOS Dropbox Sync API 3.0

One of the new features of the 3.0 Datastore API is the ability to use local datastores that will later sync up with Dropbox when the user decides to link your app to Dropbox. I'm wondering how the process of opening datastores differs now.
For example, this is how I currently open a datastore:
DBAccount *account = [[DBAccountManager sharedManager] linkedAccount];
self.store = [DBDatastore openDefaultStoreForAccount:account error:nil];
How do I get a DBAccount without a linked account? Maybe I don't. :)
On that same note, what is the process for opening a datastore with openDefaultStoreForAccount if there is no account present?
I just noticed openDefaultLocalStoreForAccountManager:
Is this how it's used? And does this still work later when there is a linked account?
self.store = [DBDatastore openDefaultLocalStoreForAccountManager:[DBAccountManager sharedManager] error:nil];
I'd appreciate any help. Thanks!
From https://www.dropbox.com/developers/blog/99/using-the-new-local-datastores-feature:
// If the user has linked a Dropbox account for the first time...
if (_justLinked) {
if (_localDatastoreManager && self.account) {
// Perform a one-time migration to move from the local datastore to a remote one.
[_localDatastoreManager migrateToAccount:self.account error:nil];
_localDatastoreManager = nil;
}
}
if (!_store) {
// If there's a linked account, use that.
if ([[DBAccountManager sharedManager] linkedAccount]) {
_store = [DBDatastore openDefaultStoreForAccount:self.account error:nil];
// Otherwise, use a local datastore.
} else {
_store = [DBDatastore openDefaultLocalStoreForAccountManager:[DBAccountManager sharedManager]
error:nil];
}
}

Resources