├── Podfile ├── Microsoft Tasks ├── en.lproj │ └── InfoPlist.strings ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── iPhone-1.png │ │ ├── iPhone-4.png │ │ ├── iPhone-5.png │ │ ├── iPhone-6.png │ │ ├── iPhone-2-1.png │ │ ├── iPhone-5-5.png │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── SamplesSelectUserViewController.h ├── samplesTaskItem.m ├── SamplesAppSettingsController.h ├── Microsoft_Tasks.xcdatamodeld │ ├── .xccurrentversion │ └── Microsoft_Tasks.xcdatamodel │ │ └── contents ├── NSDictionary+UrlEncoding.h ├── samplesLoginViewController.h ├── samplesTaskListTableViewController.h ├── main.m ├── Microsoft Tasks.entitlements ├── samplesTaskItem.h ├── Microsoft Tasks-Prefix.pch ├── sampleAddTaskItemViewController.h ├── samplesPolicyData.h ├── SamplesApplicationData.h ├── samplesShowClaimsViewController.h ├── samplesAppDelegate.h ├── settings.plist ├── samplesPolicyData.m ├── NSDictionary+UrlEncoding.m ├── SamplesApplicationData.m ├── samplesWebAPIConnector.h ├── samplesShowClaimsViewController.m ├── Microsoft Tasks-Info.plist ├── sampleAddTaskItemViewController.m ├── samplesLoginViewController.m ├── SamplesAppSettingsController.m ├── samplesAppDelegate.m ├── samplesTaskListTableViewController.m ├── SamplesSelectUserViewController.m ├── samplesWebAPIConnector.m └── Main_iPhone.storyboard ├── Microsoft TasksTests ├── en.lproj │ └── InfoPlist.strings ├── Microsoft_TasksTests.m └── Microsoft TasksTests-Info.plist ├── HockeySDK-iOS └── BuildAgent ├── Microsoft Tasks.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── project.pbxproj ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE └── README.md /Podfile: -------------------------------------------------------------------------------- 1 | target 'Microsoft Tasks' do 2 | 3 | pod 'ADALiOS' 4 | 5 | end 6 | -------------------------------------------------------------------------------- /Microsoft Tasks/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Microsoft TasksTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /HockeySDK-iOS/BuildAgent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/active-directory-ios/master/HockeySDK-iOS/BuildAgent -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/active-directory-ios/master/Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-1.png -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/active-directory-ios/master/Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-4.png -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/active-directory-ios/master/Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-5.png -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/active-directory-ios/master/Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-6.png -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/active-directory-ios/master/Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-2-1.png -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-5-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikyau/active-directory-ios/master/Microsoft Tasks/Images.xcassets/AppIcon.appiconset/iPhone-5-5.png -------------------------------------------------------------------------------- /Microsoft Tasks.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Microsoft Tasks/SamplesSelectUserViewController.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @interface SamplesSelectUserViewController : UITableViewController 5 | 6 | - (IBAction)addPressed:(id)sender; 7 | 8 | - (IBAction)cancelPressed:(id)sender; 9 | @end 10 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesTaskItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // samplesTaskItem.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/5/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import "samplesTaskItem.h" 10 | 11 | @implementation samplesTaskItem 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Microsoft Tasks/SamplesAppSettingsController.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @interface SamplesAppSettingsController : UIViewController 5 | 6 | - (IBAction)savePressed:(id)sender; 7 | 8 | - (IBAction)clearKeychainPressed:(id)sender; 9 | 10 | - (IBAction)cancelPressed:(id)sender; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | *.xccheckout 19 | 20 | #CocoaPods 21 | Pods 22 | -------------------------------------------------------------------------------- /Microsoft Tasks/Microsoft_Tasks.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | Microsoft_Tasks.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /Microsoft Tasks/NSDictionary+UrlEncoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+UrlEncoding.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSDictionary (UrlEncoding) 12 | 13 | -(NSString*) urlEncodedString; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesLoginViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // samplesLoginViewController.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface samplesLoginViewController : UIViewController 12 | - (IBAction)signInPressed:(id)sender; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesTaskListTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // samplesTaskListTableViewController.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface samplesTaskListTableViewController : UITableViewController 12 | 13 | 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Microsoft Tasks/Microsoft_Tasks.xcdatamodeld/Microsoft_Tasks.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Microsoft Tasks/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "samplesAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([samplesAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Microsoft Tasks/Microsoft Tasks.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)com.microsoft.adalcache 8 | $(AppIdentifierPrefix)com.microsoft.workplacejoin 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesTaskItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // samplesTaskItem.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/5/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface samplesTaskItem : NSObject 12 | 13 | @property NSString *itemName; 14 | @property NSString *ownerName; 15 | @property BOOL completed; 16 | @property (readonly) NSDate *creationDate; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Microsoft Tasks/Microsoft Tasks-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #import 17 | #endif 18 | -------------------------------------------------------------------------------- /Microsoft Tasks/sampleAddTaskItemViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // sampleAddTaskItemViewController.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface sampleAddTaskItemViewController : UIViewController 12 | 13 | - (IBAction)save:(id)sender; 14 | @property (weak, nonatomic) IBOutlet UITextField *textField; 15 | 16 | - (IBAction)cancelPressed:(id)sender; 17 | @end 18 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesPolicyData.h: -------------------------------------------------------------------------------- 1 | // 2 | // samplesPolicyData.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | #ifndef Microsoft_Tasks_samplesPolicyData_h 10 | #define Microsoft_Tasks_samplesPolicyData_h 11 | 12 | 13 | #endif 14 | 15 | #import 16 | 17 | @interface samplesPolicyData : NSObject 18 | 19 | @property (strong) NSString* policyName; 20 | @property (strong) NSString* policyID; 21 | 22 | +(id) getInstance; 23 | 24 | @end -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Microsoft Tasks/SamplesApplicationData.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface SamplesApplicationData : NSObject 5 | 6 | @property (strong) ADTokenCacheStoreItem *userItem; 7 | @property (strong) NSString* taskWebApiUrlString; 8 | @property (strong) NSString* authority; 9 | @property (strong) NSString* clientId; 10 | @property (strong) NSString* resourceId; 11 | @property (strong) NSString* redirectUriString; 12 | @property (strong) NSString* correlationId; 13 | @property BOOL fullScreen; 14 | @property BOOL showClaims; 15 | 16 | +(id) getInstance; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesShowClaimsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // samplesShowClaimsViewController.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface samplesShowClaimsViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *useLabel; 14 | @property (weak, nonatomic) IBOutlet UIScrollView *tokenView; 15 | @property (weak, nonatomic) IBOutlet UITextView *tokenText; 16 | @property (nonatomic, strong) NSString *claims; 17 | - (IBAction)homePressed:(id)sender; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // samplesAppDelegate.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | @interface samplesAppDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow *window; 13 | 14 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 15 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; 16 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Microsoft Tasks/settings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | authority 6 | https://login.microsoftonline.com/common 7 | clientId 8 | e6d65cc4-f9e8-444a-9ba6-c3c82ce8086b 9 | resourceString 10 | http://localhost:3000/tasks 11 | redirectUri 12 | urn:ietf:wg:oauth:2.0:oob 13 | userId 14 | 15 | taskWebAPI 16 | http://localhost:3000/tasks 17 | fullScreen 18 | 19 | showClaims 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Microsoft TasksTests/Microsoft_TasksTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // Microsoft_TasksTests.m 3 | // Microsoft TasksTests 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Microsoft_TasksTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation Microsoft_TasksTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Microsoft TasksTests/Microsoft TasksTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.microsoft.windowsazure.activedirectory.samples.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Azure samples 2 | 3 | Thank you for your interest in contributing to Azure samples! 4 | 5 | ## Ways to contribute 6 | 7 | You can contribute to [Azure samples](https://azure.microsoft.com/documentation/samples/) in a few different ways: 8 | 9 | - Submit feedback on [this sample page](https://azure.microsoft.com/documentation/samples/active-directory-ios/) whether it was helpful or not. 10 | - Submit issues through [issue tracker](https://github.com/Azure-Samples/active-directory-ios/issues) on GitHub. We are actively monitoring the issues and improving our samples. 11 | - If you wish to make code changes to samples, or contribute something new, please follow the [GitHub Forks / Pull requests model](https://help.github.com/articles/fork-a-repo/): Fork the sample repo, make the change and propose it back by submitting a pull request. -------------------------------------------------------------------------------- /Microsoft Tasks/samplesPolicyData.m: -------------------------------------------------------------------------------- 1 | // 2 | // samplesPolicyData.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "samplesPolicyData.h" 11 | 12 | @implementation samplesPolicyData 13 | 14 | +(id) getInstance 15 | { 16 | static samplesPolicyData *instance = nil; 17 | static dispatch_once_t onceToken; 18 | 19 | dispatch_once(&onceToken, ^{ 20 | instance = [[self alloc] init]; 21 | NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"settings" ofType:@"plist"]]; 22 | instance.policyName = [dictionary objectForKey:@"policyName"]; 23 | instance.policyID = [dictionary objectForKey:@"policyID"]; 24 | 25 | 26 | }); 27 | 28 | return instance; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Microsoft Tasks/NSDictionary+UrlEncoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+UrlEncoding.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+UrlEncoding.h" 10 | 11 | // helper function: get the string form of any object 12 | static NSString *toString(id object) { 13 | return [NSString stringWithFormat: @"%@", object]; 14 | } 15 | 16 | // helper function: get the url encoded string form of any object 17 | static NSString *urlEncode(id object) { 18 | NSString *string = toString(object); 19 | return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; 20 | } 21 | 22 | @implementation NSDictionary (UrlEncoding) 23 | 24 | -(NSString*) urlEncodedString { 25 | NSMutableArray *parts = [NSMutableArray array]; 26 | for (id key in self) { 27 | id value = [self objectForKey: key]; 28 | NSString *part = [NSString stringWithFormat: @"%@=%@", urlEncode(key), urlEncode(value)]; 29 | [parts addObject: part]; 30 | } 31 | return [parts componentsJoinedByString: @"&"]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Microsoft Tasks/SamplesApplicationData.m: -------------------------------------------------------------------------------- 1 | #import "SamplesApplicationData.h" 2 | 3 | @implementation SamplesApplicationData 4 | 5 | +(id) getInstance 6 | { 7 | static SamplesApplicationData *instance = nil; 8 | static dispatch_once_t onceToken; 9 | 10 | dispatch_once(&onceToken, ^{ 11 | instance = [[self alloc] init]; 12 | NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"settings" ofType:@"plist"]]; 13 | NSString* va = [dictionary objectForKey:@"fullScreen"]; 14 | NSString* sc = [dictionary objectForKey:@"showClaims"]; 15 | instance.fullScreen = [va boolValue]; 16 | instance.showClaims = [sc boolValue]; 17 | instance.clientId = [dictionary objectForKey:@"clientId"]; 18 | instance.authority = [dictionary objectForKey:@"authority"]; 19 | instance.resourceId = [dictionary objectForKey:@"resourceString"]; 20 | instance.redirectUriString = [dictionary objectForKey:@"redirectUri"]; 21 | instance.taskWebApiUrlString = [dictionary objectForKey:@"taskWebAPI"]; 22 | instance.correlationId = [dictionary objectForKey:@"correlationId"]; 23 | 24 | }); 25 | 26 | return instance; 27 | } 28 | 29 | @end -------------------------------------------------------------------------------- /Microsoft Tasks/samplesWebAPIConnector.h: -------------------------------------------------------------------------------- 1 | // 2 | // samplesWebAPIConnector.h 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/11/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "samplesTaskItem.h" 11 | #import "samplesPolicyData.h" 12 | #import "ADALiOS/ADAuthenticationContext.h" 13 | 14 | @interface samplesWebAPIConnector : NSObject 15 | 16 | +(void) getTaskList:(void (^) (NSArray*, NSError* error))completionBlock 17 | parent:(UIViewController*) parent; 18 | 19 | +(void) addTask:(samplesTaskItem*)task 20 | parent:(UIViewController*) parent 21 | completionBlock:(void (^) (bool, NSError* error)) completionBlock; 22 | 23 | +(void) deleteTask:(samplesTaskItem*)task 24 | parent:(UIViewController*) parent 25 | completionBlock:(void (^) (bool, NSError* error)) completionBlock; 26 | 27 | +(void) doPolicy:(samplesPolicyData*)policy 28 | parent:(UIViewController*) parent 29 | completionBlock:(void (^) (ADUserInformation* userInfo, NSError* error)) completionBlock; 30 | 31 | +(void) doLogin:(BOOL)prompt 32 | parent:(UIViewController*) parent 33 | completionBlock:(void (^) (ADUserInformation* userInfo, NSError* error)) completionBlock; 34 | 35 | +(void) signOut; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesShowClaimsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // samplesShowClaimsViewController.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | 10 | #import "samplesShowClaimsViewController.h" 11 | #import "samplesTaskListTableViewController.h" 12 | 13 | @interface samplesShowClaimsViewController () 14 | 15 | @end 16 | 17 | @implementation samplesShowClaimsViewController 18 | 19 | @synthesize tokenText; 20 | @synthesize claims; 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view. 25 | tokenText.text = claims; 26 | // Do any additional setup after loading the view. 27 | } 28 | 29 | - (void)didReceiveMemoryWarning { 30 | [super didReceiveMemoryWarning]; 31 | // Dispose of any resources that can be recreated. 32 | } 33 | 34 | /* 35 | #pragma mark - Navigation 36 | 37 | // In a storyboard-based application, you will often want to do a little preparation before navigation 38 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 39 | // Get the new view controller using [segue destinationViewController]. 40 | // Pass the selected object to the new view controller. 41 | } 42 | */ 43 | 44 | - (IBAction)homePressed:(id)sender { 45 | 46 | [self.navigationController popToRootViewControllerAnimated:TRUE]; 47 | 48 | } 49 | @end 50 | -------------------------------------------------------------------------------- /Microsoft Tasks/Microsoft Tasks-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Microsoft Tasks 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.microsoft.windowsazure.activedirectory.samples.microsofttasks 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | Microsoft Tasks 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.3 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.3 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | Main_iPhone 29 | UIMainStoryboardFile 30 | Main_iPhone 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | NSAppTransportSecurity 36 | 37 | NSAllowsArbitraryLoads 38 | 39 | 40 | UISupportedInterfaceOrientations 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | UIInterfaceOrientationPortraitUpsideDown 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Microsoft Tasks/sampleAddTaskItemViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // sampleAddTaskItemViewController.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import "sampleAddTaskItemViewController.h" 10 | #import "samplesWebAPIConnector.h" 11 | #import "samplesTaskItem.h" 12 | 13 | @implementation sampleAddTaskItemViewController 14 | 15 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 16 | { 17 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 18 | if (self) { 19 | // Custom initialization 20 | } 21 | return self; 22 | } 23 | 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | // Do any additional setup after loading the view. 28 | } 29 | 30 | - (void)didReceiveMemoryWarning 31 | { 32 | [super didReceiveMemoryWarning]; 33 | // Dispose of any resources that can be recreated. 34 | } 35 | 36 | - (IBAction)save:(id)sender { 37 | 38 | if (self.textField.text.length > 0) { 39 | 40 | samplesTaskItem* taskItem = [[samplesTaskItem alloc]init]; 41 | taskItem.itemName = self.textField.text; 42 | taskItem.completed = NO; 43 | 44 | [samplesWebAPIConnector addTask:taskItem parent:self completionBlock:^(bool success, NSError* error) { 45 | if (success) 46 | 47 | {dispatch_async(dispatch_get_main_queue(),^ { 48 | 49 | [self.navigationController popViewControllerAnimated:TRUE]; 50 | }); 51 | } 52 | else 53 | { 54 | UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[[NSString alloc]initWithFormat:@"Error : %@", error.localizedDescription] delegate:nil cancelButtonTitle:@"Retry" otherButtonTitles:@"Cancel", nil]; 55 | 56 | [alertView setDelegate:self]; 57 | 58 | dispatch_async(dispatch_get_main_queue(),^ { 59 | [alertView show]; 60 | }); 61 | } 62 | 63 | }]; 64 | } 65 | } 66 | 67 | 68 | - (IBAction)cancelPressed:(id)sender 69 | { 70 | [self dismissViewControllerAnimated:YES completion:nil]; 71 | } 72 | 73 | 74 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 75 | { 76 | if (buttonIndex == 0) 77 | { 78 | [alertView dismissWithClickedButtonIndex:0 animated:NO]; 79 | [self save:nil]; 80 | } 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesLoginViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // samplesLoginViewController.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 4/21/15. 6 | // Copyright (c) 2015 Microsoft. All rights reserved. 7 | // 8 | 9 | #import "samplesLoginViewController.h" 10 | #import "samplesWebAPIConnector.h" 11 | #import "samplesShowClaimsViewController.h" 12 | #import "samplesPolicyData.h" 13 | #import "samplesApplicationData.h" 14 | 15 | @interface samplesLoginViewController () 16 | 17 | @end 18 | 19 | @implementation samplesLoginViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | // Do any additional setup after loading the view. 24 | } 25 | 26 | - (void)didReceiveMemoryWarning { 27 | [super didReceiveMemoryWarning]; 28 | // Dispose of any resources that can be recreated. 29 | } 30 | 31 | /* 32 | #pragma mark - Navigation 33 | 34 | // In a storyboard-based application, you will often want to do a little preparation before navigation 35 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 36 | // Get the new view controller using [segue destinationViewController]. 37 | // Pass the selected object to the new view controller. 38 | } 39 | */ 40 | 41 | - (IBAction)signInPressed:(id)sender { 42 | 43 | SamplesApplicationData* appData = [SamplesApplicationData getInstance]; 44 | 45 | [samplesWebAPIConnector doLogin:YES parent:self completionBlock:^(ADUserInformation* userInfo, NSError* error) { 46 | if (userInfo && appData.showClaims) 47 | { 48 | dispatch_sync(dispatch_get_main_queue(), ^{ 49 | samplesShowClaimsViewController* claimsController = [self.storyboard instantiateViewControllerWithIdentifier:@"ClaimsView"]; 50 | claimsController.claims = [NSString stringWithFormat:@" Claims : %@", userInfo.allClaims]; 51 | [self.navigationController pushViewController:claimsController animated:YES]; 52 | }); 53 | } 54 | else if (userInfo) 55 | { 56 | [self dismissViewControllerAnimated:YES completion:nil]; 57 | } 58 | else 59 | { 60 | UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[[NSString alloc]initWithFormat:@"Error : %@", error.localizedDescription] delegate:nil cancelButtonTitle:@"Retry" otherButtonTitles:@"Cancel", nil]; 61 | 62 | [alertView setDelegate:self]; 63 | 64 | dispatch_async(dispatch_get_main_queue(),^ { 65 | [alertView show]; 66 | }); 67 | } 68 | 69 | }]; 70 | 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Microsoft Tasks/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "3x" 17 | }, 18 | { 19 | "size" : "40x40", 20 | "idiom" : "iphone", 21 | "filename" : "iPhone-2-1.png", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "size" : "40x40", 26 | "idiom" : "iphone", 27 | "filename" : "iPhone-5.png", 28 | "scale" : "3x" 29 | }, 30 | { 31 | "size" : "57x57", 32 | "idiom" : "iphone", 33 | "filename" : "iPhone-1.png", 34 | "scale" : "1x" 35 | }, 36 | { 37 | "size" : "57x57", 38 | "idiom" : "iphone", 39 | "filename" : "iPhone-4.png", 40 | "scale" : "2x" 41 | }, 42 | { 43 | "size" : "60x60", 44 | "idiom" : "iphone", 45 | "filename" : "iPhone-5-5.png", 46 | "scale" : "2x" 47 | }, 48 | { 49 | "size" : "60x60", 50 | "idiom" : "iphone", 51 | "filename" : "iPhone-6.png", 52 | "scale" : "3x" 53 | }, 54 | { 55 | "size" : "24x24", 56 | "idiom" : "watch", 57 | "scale" : "2x", 58 | "role" : "notificationCenter", 59 | "subtype" : "38mm" 60 | }, 61 | { 62 | "size" : "27.5x27.5", 63 | "idiom" : "watch", 64 | "scale" : "2x", 65 | "role" : "notificationCenter", 66 | "subtype" : "42mm" 67 | }, 68 | { 69 | "size" : "29x29", 70 | "idiom" : "watch", 71 | "role" : "companionSettings", 72 | "scale" : "2x" 73 | }, 74 | { 75 | "size" : "29x29", 76 | "idiom" : "watch", 77 | "role" : "companionSettings", 78 | "scale" : "3x" 79 | }, 80 | { 81 | "size" : "40x40", 82 | "idiom" : "watch", 83 | "scale" : "2x", 84 | "role" : "appLauncher", 85 | "subtype" : "38mm" 86 | }, 87 | { 88 | "size" : "44x44", 89 | "idiom" : "watch", 90 | "scale" : "2x", 91 | "role" : "longLook", 92 | "subtype" : "42mm" 93 | }, 94 | { 95 | "size" : "86x86", 96 | "idiom" : "watch", 97 | "scale" : "2x", 98 | "role" : "quickLook", 99 | "subtype" : "38mm" 100 | }, 101 | { 102 | "size" : "98x98", 103 | "idiom" : "watch", 104 | "scale" : "2x", 105 | "role" : "quickLook", 106 | "subtype" : "42mm" 107 | } 108 | ], 109 | "info" : { 110 | "version" : 1, 111 | "author" : "xcode" 112 | } 113 | } -------------------------------------------------------------------------------- /Microsoft Tasks/SamplesAppSettingsController.m: -------------------------------------------------------------------------------- 1 | #import "SamplesAppSettingsController.h" 2 | #import "SamplesApplicationData.h" 3 | #import 4 | 5 | @interface SamplesAppSettingsController () 6 | 7 | @property (weak, nonatomic) IBOutlet UITextField *authorityLabel; 8 | @property (weak, nonatomic) IBOutlet UITextField *clientIdLabel; 9 | @property (weak, nonatomic) IBOutlet UITextField *resourceLabel; 10 | @property (weak, nonatomic) IBOutlet UITextField *redirectUriLabel; 11 | @property (weak, nonatomic) IBOutlet UISegmentedControl *fullScreenSwitch; 12 | @property (weak, nonatomic) IBOutlet UITextField *correlationIdLabel; 13 | @property (weak, nonatomic) IBOutlet UISegmentedControl *showClaimsSwitch; 14 | @end 15 | 16 | @implementation SamplesAppSettingsController 17 | 18 | - (void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view. 22 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 23 | self->_authorityLabel.text = data.authority; 24 | self->_clientIdLabel.text = data.clientId; 25 | self->_resourceLabel.text = data.resourceId; 26 | self->_redirectUriLabel.text = data.redirectUriString; 27 | self->_correlationIdLabel.text = data.correlationId; 28 | [self configureControl:self->_fullScreenSwitch forValue:data.fullScreen]; 29 | [self configureControl:self->_showClaimsSwitch forValue:data.showClaims]; 30 | } 31 | 32 | 33 | - (IBAction)savePressed:(id)sender 34 | { 35 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 36 | data.authority = self->_authorityLabel.text; 37 | data.clientId = self->_clientIdLabel.text; 38 | data.resourceId = self->_resourceLabel.text; 39 | data.redirectUriString = self->_redirectUriLabel.text; 40 | data.fullScreen = [self isEnabled:self->_fullScreenSwitch]; 41 | data.correlationId = self->_correlationIdLabel.text; 42 | data.showClaims = [self isEnabled:self->_showClaimsSwitch]; 43 | [self cancelPressed:sender]; 44 | 45 | } 46 | 47 | 48 | - (void) configureControl:(UISegmentedControl *)control forValue:(BOOL) enabled 49 | { 50 | if(enabled){ 51 | [control setSelectedSegmentIndex:1]; 52 | }else 53 | { 54 | [control setSelectedSegmentIndex:0]; 55 | } 56 | } 57 | 58 | - (IBAction)cancelPressed:(id)sender 59 | { 60 | [self dismissViewControllerAnimated:YES completion:nil]; 61 | } 62 | 63 | 64 | - (IBAction)clearKeychainPressed:(id)sender 65 | { 66 | id cache = [ADAuthenticationSettings sharedInstance].defaultTokenCacheStore; 67 | [cache removeAllWithError:nil]; 68 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 69 | data.userItem = nil; 70 | 71 | // This clears cookies for new sign-in flow. We shouldn't need to do this. Server should accept PROMPT_ALWAYS 72 | 73 | NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; 74 | for (NSHTTPCookie *cookie in [storage cookies]) { 75 | [storage deleteCookie:cookie]; 76 | } 77 | 78 | [[NSUserDefaults standardUserDefaults] synchronize]; 79 | } 80 | 81 | - (BOOL) isEnabled:(UISegmentedControl *)control 82 | { 83 | return [control selectedSegmentIndex] != 0; 84 | } 85 | 86 | @end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | services: active-directory 3 | platforms: ios 4 | author: brandwe 5 | --- 6 | 7 | # Integrate Azure AD into an iOS application 8 | 9 | **NOTE regarding iOS 9:** 10 | 11 | Apple has released iOS 9 which includes support for App Transport Security (ATS). ATS restricts apps from accessing the internet unless they meet several security requirements incuding TLS 1.2 and SHA-256. While Microsoft's APIs support these standards some third party APIs and content delivery networks we use have yet to be upgraded. This means that any app that relies on Azure Active Directory or Microsoft Accounts will fail when compiled with iOS 9. For now our recommendation is to disable ATS, which reverts to iOS 8 functionality. Please refer to this [technote from Apple](https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/) for more informtaion. 12 | 13 | ---- 14 | 15 | 16 | This sample shows how to build an iOS application that calls a web API that requires a Work Account for authentication. This sample uses the Active Directory authentication library for iOS to do the interactive OAuth 2.0 authorization code flow with public client. 17 | 18 | 19 | ## Quick Start 20 | 21 | Getting started with the sample is easy. It is configured to run out of the box with minimal setup. If you'd like a more detailed walkthrough including how to setup the REST API and register an Azure AD Directory follow the walk-through here. 22 | 23 | ### Step 1: Download the iOS Native Client Sample code 24 | 25 | * `$ git clone git@github.com:Azure-Samples/active-directory-ios.git` 26 | 27 | ### Step 2: Download Cocoapods (if you don't already have it) 28 | 29 | CocoaPods is the dependency manager for Swift and Objective-C Cocoa projects. It has thousands of libraries and can help you scale your projects elegantly. To install on OS X 10.9 and greater simply run the following command in your terminal: 30 | 31 | `$ sudo gem install cocoapods` 32 | 33 | ### Step 3: Build the sample and pull down ADAL for iOS automatically 34 | 35 | Run the following command in your terminal: 36 | 37 | `$ pod install` 38 | 39 | This will download and build ADAL for iOS for you and configure your Microsoft Tasks.xcodeproj to use the correct dependencies. 40 | 41 | ### Step 4: Run the application in Xcode 42 | 43 | Launch XCode and load the `Microsoft Tasks.xcworkspace` file. The application will run in an emulator as soon as it is loaded. 44 | 45 | 46 | #### Step 5. Determine what your Redirect URI will be for iOS 47 | 48 | In order to securely launch your applications in certain SSO scenarios we require that you create a **Redirect URI** in a particular format. A Redirect URI is used to ensure that the tokens return to the correct application that asked for them. 49 | 50 | The iOS format for a Redirect URI is: 51 | 52 | ``` 53 | :// 54 | ``` 55 | 56 | - **app-scheme** - This is registered in your XCode project. It is how other applications can call you. You can find this under Info.plist -> URL types -> URL Identifier. You should create one if you don't already have one or more configured. 57 | - **bundle-id** - This is the Bundle Identifier found under "identity" un your project settings in XCode. 58 | 59 | An example would be: ***mstodo://com.microsoft.windowsazure.activedirectory.samples.microsofttasks*** 60 | 61 | ### Step 6: Configure the settings.plist file with your Web API information 62 | 63 | You will need to configure your application to work with the Azure AD tenant you've created. Under "Supporting Files"you will find a settings.plist file. It contains the following information: 64 | 65 | ```XML 66 | 67 | 68 | 69 | 70 | authority 71 | https://login.microsoftonline.com/common 72 | clientId 73 | xxxxxxx-xxxxxx-xxxxxxx-xxxxxxx 74 | resourceString 75 | https://localhost/todolistservice 76 | redirectUri 77 | mstodo://com.microsoft.windowsazure.activedirectory.samples.microsofttasks 78 | userId 79 | user@domain.com 80 | taskWebAPI 81 | https://localhost/api/todolist/ 82 | 83 | 84 | ``` 85 | 86 | Replace the information in the plist file with your Web API settings. 87 | 88 | ##### NOTE 89 | 90 | The current defaults are set up to work with our [Azure Active Directory Sample REST API Service for Node.js](https://github.com/Azure-Samples/WebAPI-Nodejs). You will need to specify the clientID of your Web API, however. If you are running your own API, you will need to update the endpoints as required. 91 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // samplesAppDelegate.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import "samplesAppDelegate.h" 10 | #import "SamplesApplicationData.h" 11 | 12 | 13 | @implementation samplesAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | // Override point for customization after application launch. 18 | 19 | 20 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; 21 | 22 | UIPageControl *pageControl = [UIPageControl appearance]; 23 | pageControl.pageIndicatorTintColor = [UIColor lightGrayColor]; 24 | pageControl.currentPageIndicatorTintColor = [UIColor whiteColor]; 25 | pageControl.backgroundColor = [UIColor colorWithRed:0.106 green:0.286 blue:0.627 alpha:1]; 26 | 27 | 28 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 29 | NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"settings" ofType:@"plist"]]; 30 | 31 | data.clientId = [dictionary objectForKey:@"clientId"]; 32 | data.authority = [dictionary objectForKey:@"authority"]; 33 | data.resourceId = [dictionary objectForKey:@"resourceString"]; 34 | data.redirectUriString = [dictionary objectForKey:@"redirectUri"]; 35 | data.taskWebApiUrlString = [dictionary objectForKey:@"taskWebAPI"]; 36 | 37 | return YES; 38 | } 39 | 40 | - (void)applicationWillResignActive:(UIApplication *)application 41 | { 42 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 43 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 44 | } 45 | 46 | - (void)applicationDidEnterBackground:(UIApplication *)application 47 | { 48 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 49 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 50 | } 51 | 52 | - (void)applicationWillEnterForeground:(UIApplication *)application 53 | { 54 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 55 | } 56 | 57 | - (void)applicationDidBecomeActive:(UIApplication *)application 58 | { 59 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 60 | } 61 | 62 | - (void)applicationWillTerminate:(UIApplication *)application 63 | { 64 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 65 | } 66 | 67 | #pragma mark - Core Data stack 68 | 69 | @synthesize managedObjectContext = _managedObjectContext; 70 | @synthesize managedObjectModel = _managedObjectModel; 71 | @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 72 | 73 | - (NSURL *)applicationDocumentsDirectory { 74 | // The directory the application uses to store the Core Data store file. This code uses a directory named "com.microsoft.windowsazure.activedirectory.samples" in the application's documents directory. 75 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 76 | } 77 | 78 | - (NSManagedObjectModel *)managedObjectModel { 79 | // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 80 | if (_managedObjectModel != nil) { 81 | return _managedObjectModel; 82 | } 83 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Policy" withExtension:@"momd"]; 84 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 85 | return _managedObjectModel; 86 | } 87 | 88 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 89 | // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. 90 | if (_persistentStoreCoordinator != nil) { 91 | return _persistentStoreCoordinator; 92 | } 93 | 94 | // Create the coordinator and store 95 | 96 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 97 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Microsoft_Tasks.sqlite"]; 98 | NSError *error = nil; 99 | NSString *failureReason = @"There was an error creating or loading the application's saved data."; 100 | if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 101 | // Report any error we got. 102 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 103 | dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 104 | dict[NSLocalizedFailureReasonErrorKey] = failureReason; 105 | dict[NSUnderlyingErrorKey] = error; 106 | error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 107 | // Replace this with code to handle the error appropriately. 108 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 109 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 110 | abort(); 111 | } 112 | 113 | return _persistentStoreCoordinator; 114 | } 115 | 116 | 117 | - (NSManagedObjectContext *)managedObjectContext { 118 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 119 | if (_managedObjectContext != nil) { 120 | return _managedObjectContext; 121 | } 122 | 123 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 124 | if (!coordinator) { 125 | return nil; 126 | } 127 | _managedObjectContext = [[NSManagedObjectContext alloc] init]; 128 | [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 129 | return _managedObjectContext; 130 | } 131 | 132 | #pragma mark - Core Data Saving support 133 | 134 | - (void)saveContext { 135 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 136 | if (managedObjectContext != nil) { 137 | NSError *error = nil; 138 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 139 | // Replace this implementation with code to handle the error appropriately. 140 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 141 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 142 | abort(); 143 | } 144 | } 145 | } 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesTaskListTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // samplesTaskListTableViewController.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/4/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | #import "samplesTaskListTableViewController.h" 10 | #import "SamplesApplicationData.h" 11 | #import "samplesTaskItem.h" 12 | #import "sampleAddTaskItemViewController.h" 13 | #import "samplesWebAPIConnector.h" 14 | #import "ADALiOS/ADAuthenticationContext.h" 15 | #import "SamplesSelectUserViewController.h" 16 | 17 | @interface samplesTaskListTableViewController () 18 | 19 | @property NSMutableArray *taskItems; 20 | @property ADAuthenticationContext *authContext; 21 | @property (weak, nonatomic) IBOutlet UILabel* userLabel; 22 | 23 | @end 24 | 25 | @implementation samplesTaskListTableViewController 26 | 27 | -(void)loadData { 28 | 29 | SamplesApplicationData* appData = [SamplesApplicationData getInstance]; 30 | 31 | if (!appData.userItem.userInformation.userId) { 32 | 33 | dispatch_async(dispatch_get_main_queue(),^ { 34 | 35 | SamplesSelectUserViewController* userSelectController = [self.storyboard instantiateViewControllerWithIdentifier:@"SelectUserView"]; 36 | [self.navigationController pushViewController:userSelectController animated:YES]; 37 | }); 38 | } 39 | 40 | 41 | // Load data from the webservice 42 | if (appData.userItem) { 43 | 44 | [samplesWebAPIConnector getTaskList:^(NSArray *tasks, NSError* error) { 45 | 46 | if (error != nil && appData.userItem) 47 | { 48 | UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[[NSString alloc]initWithFormat:@"%@", error.localizedDescription] delegate:nil cancelButtonTitle:@"Retry" otherButtonTitles:@"Cancel", nil]; 49 | 50 | [alertView setDelegate:self]; 51 | 52 | dispatch_async(dispatch_get_main_queue(),^ { 53 | [alertView show]; 54 | }); 55 | } 56 | else 57 | { 58 | self.taskItems = (NSMutableArray*)tasks; 59 | 60 | // Refresh main thread since we are async 61 | dispatch_async(dispatch_get_main_queue(), ^{ 62 | [self.tableView reloadData]; 63 | SamplesApplicationData* appData = [SamplesApplicationData getInstance]; 64 | if(appData.userItem && appData.userItem.userInformation) 65 | { 66 | [self.userLabel setText:appData.userItem.userInformation.userId]; 67 | } 68 | else 69 | { 70 | [self.userLabel setText:@"N/A" ]; 71 | } 72 | }); 73 | } 74 | } parent:self]; 75 | } } 76 | 77 | - (void)viewDidLoad 78 | { 79 | [super viewDidLoad]; 80 | self.refreshControl = [[UIRefreshControl alloc] init]; 81 | 82 | [self.refreshControl addTarget:self action:@selector(refreshInvoked:forState:) forControlEvents:UIControlEventValueChanged]; 83 | 84 | [self setRefreshControl:self.refreshControl]; 85 | self.taskItems = [[NSMutableArray alloc] init]; 86 | [self loadData]; 87 | } 88 | 89 | -(void)viewDidAppear:(BOOL)animated 90 | { 91 | 92 | SamplesApplicationData* appData = [SamplesApplicationData getInstance]; 93 | 94 | if(appData.userItem) 95 | { 96 | [self loadData]; 97 | } 98 | 99 | if(appData.userItem && appData.userItem.userInformation) 100 | { 101 | [self.userLabel setText:appData.userItem.userInformation.userId]; } 102 | else 103 | { 104 | [self.userLabel setText:@"N/A" ]; 105 | } 106 | } 107 | 108 | 109 | -(void) refreshInvoked:(id)sender forState:(UIControlState)state { 110 | // Refresh table here... 111 | [self.taskItems removeAllObjects]; 112 | [self.tableView reloadData]; 113 | [self loadData]; 114 | [self.refreshControl endRefreshing]; 115 | } 116 | 117 | - (void)didReceiveMemoryWarning 118 | { 119 | [super didReceiveMemoryWarning]; 120 | // Dispose of any resources that can be recreated. 121 | } 122 | 123 | 124 | #pragma mark - Table view data source 125 | 126 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 127 | { 128 | // Return the number of sections. 129 | return 1; 130 | } 131 | 132 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 133 | { 134 | // Return the number of rows in the section. 135 | return [self.taskItems count]; 136 | } 137 | 138 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 139 | { 140 | 141 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TaskPrototypeCell" forIndexPath:indexPath]; 142 | 143 | samplesTaskItem *taskItem = [self.taskItems objectAtIndex:indexPath.row]; 144 | cell.textLabel.text = taskItem.itemName; 145 | 146 | if (taskItem.completed) { 147 | cell.accessoryType = UITableViewCellAccessoryCheckmark; 148 | } else { 149 | cell.accessoryType = UITableViewCellAccessoryNone; 150 | } 151 | 152 | return cell; 153 | } 154 | 155 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 156 | 157 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 158 | samplesTaskItem *tappedItem = [self.taskItems objectAtIndex:indexPath.row]; 159 | tappedItem.completed = !tappedItem.completed; 160 | [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; 161 | } 162 | 163 | 164 | // Override to support conditional editing of the table view. 165 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 166 | // Return NO if you do not want the specified item to be editable. 167 | return YES; 168 | } 169 | 170 | 171 | 172 | // Override to support editing the table view. 173 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 174 | if (editingStyle == UITableViewCellEditingStyleDelete) { 175 | 176 | 177 | samplesTaskItem *selectedItem = [self.taskItems objectAtIndex:indexPath.row]; 178 | [samplesWebAPIConnector deleteTask:selectedItem parent:self completionBlock:^(bool success, NSError* error) { 179 | 180 | if (error != nil) { 181 | 182 | UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[[NSString alloc]initWithFormat:@"Error : %@", error.localizedDescription] delegate:nil cancelButtonTitle:@"Retry" otherButtonTitles:@"Cancel", nil]; 183 | 184 | [alertView setDelegate:self]; 185 | 186 | dispatch_async(dispatch_get_main_queue(),^ { 187 | [alertView show]; 188 | }); 189 | } 190 | 191 | }]; 192 | 193 | [self.taskItems removeObjectAtIndex:indexPath.row]; 194 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 195 | 196 | } 197 | 198 | [self.taskItems removeAllObjects]; 199 | [self.tableView reloadData]; 200 | [self loadData]; 201 | 202 | 203 | } 204 | 205 | 206 | 207 | 208 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 209 | { 210 | if (buttonIndex == 0) 211 | { 212 | [alertView dismissWithClickedButtonIndex:0 animated:NO]; 213 | } 214 | } 215 | 216 | - (IBAction)unwindToList:(UIStoryboardSegue *)segue { 217 | 218 | } 219 | 220 | @end 221 | -------------------------------------------------------------------------------- /Microsoft Tasks/SamplesSelectUserViewController.m: -------------------------------------------------------------------------------- 1 | #import "SamplesSelectUserViewController.h" 2 | #import 3 | #import "ADALiOS/ADAuthenticationContext.h" 4 | #import "SamplesApplicationData.h" 5 | #import "samplesTaskListTableViewController.h" 6 | 7 | @interface SamplesSelectUserViewController () 8 | 9 | @property NSMutableArray *userList; 10 | 11 | @end 12 | 13 | @implementation SamplesSelectUserViewController 14 | 15 | 16 | - (void)viewDidLoad 17 | { 18 | [super viewDidLoad]; 19 | self.refreshControl = [[UIRefreshControl alloc] init]; 20 | 21 | [self.refreshControl addTarget:self action:@selector(refreshInvoked:forState:) forControlEvents:UIControlEventValueChanged]; 22 | 23 | [self setRefreshControl:self.refreshControl]; 24 | self.userList = [[NSMutableArray alloc] init]; 25 | 26 | [self loadData]; 27 | } 28 | 29 | -(void)viewDidAppear:(BOOL)animated 30 | { 31 | 32 | [self loadData]; 33 | 34 | } 35 | 36 | -(void) loadData 37 | { 38 | ADAuthenticationError* error; 39 | id cache = [ADAuthenticationSettings sharedInstance].defaultTokenCacheStore; 40 | NSArray* array = [cache allItemsWithError:&error]; 41 | 42 | if (error) 43 | { 44 | UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[[NSString alloc]initWithFormat:@"%@", error.errorDetails] delegate:nil cancelButtonTitle:@"Retry" otherButtonTitles:@"Cancel", nil]; 45 | 46 | [alertView setDelegate:self]; 47 | 48 | dispatch_async(dispatch_get_main_queue(),^ { 49 | [alertView show]; 50 | }); 51 | } else 52 | { 53 | NSMutableSet* users = [NSMutableSet new]; 54 | self.userList = [NSMutableArray new]; 55 | for(ADTokenCacheStoreItem* item in array) 56 | { 57 | ADUserInformation *user = item.userInformation; 58 | if (!item.userInformation) 59 | { 60 | user = [ADUserInformation userInformationWithUserId:@"Unknown user" error:nil]; 61 | } 62 | if (![users containsObject:user.userId]) 63 | { 64 | //New user, add and print: 65 | [self.userList addObject:item]; 66 | [users addObject:user.userId]; 67 | } 68 | } 69 | 70 | // Refresh main thread since we are async 71 | dispatch_async(dispatch_get_main_queue(), ^{ 72 | [self.tableView reloadData]; 73 | }); 74 | } 75 | } 76 | 77 | - (IBAction)cancelPressed:(id)sender 78 | { 79 | [self dismissViewControllerAnimated:YES completion:nil]; 80 | } 81 | 82 | -(void) refreshInvoked:(id)sender forState:(UIControlState)state { 83 | // Refresh table here... 84 | [self.userList removeAllObjects]; 85 | [self.tableView reloadData]; 86 | [self loadData]; 87 | [self.refreshControl endRefreshing]; 88 | } 89 | 90 | 91 | 92 | #pragma mark - Table view data source 93 | 94 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 95 | { 96 | // Return the number of sections. 97 | return 1; 98 | } 99 | 100 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 101 | { 102 | // Return the number of rows in the section. 103 | return [self.userList count]; 104 | } 105 | 106 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 107 | { 108 | 109 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UserPrototypeCell" forIndexPath:indexPath]; 110 | 111 | ADTokenCacheStoreItem *userItem = [self.userList objectAtIndex:indexPath.row]; 112 | if(userItem) 113 | { 114 | if(userItem.userInformation){ 115 | 116 | cell.textLabel.text = userItem.userInformation.userId; 117 | } 118 | else 119 | { 120 | cell.textLabel.text = @"ADFS User"; 121 | } 122 | } 123 | // if (taskItem.completed) { 124 | // cell.accessoryType = UITableViewCellAccessoryCheckmark; 125 | // } else { 126 | // cell.accessoryType = UITableViewCellAccessoryNone; 127 | // } 128 | 129 | return cell; 130 | } 131 | 132 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 133 | 134 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 135 | ADTokenCacheStoreItem *userItem = [self.userList objectAtIndex:indexPath.row]; 136 | [self getToken:userItem]; 137 | 138 | //tappedItem.completed = !tappedItem.completed; 139 | [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; 140 | 141 | [self.navigationController popToRootViewControllerAnimated:TRUE]; 142 | 143 | } 144 | 145 | - (void) getToken:(ADTokenCacheStoreItem*) userItem 146 | { 147 | SamplesApplicationData* appData = [SamplesApplicationData getInstance]; 148 | ADAuthenticationError *error; 149 | ADAuthenticationContext* authContext = [ADAuthenticationContext authenticationContextWithAuthority:appData.authority validateAuthority:NO error:&error]; 150 | NSString* userId = nil; 151 | 152 | if(userItem && userItem.userInformation){ 153 | if(userItem.userInformation.userIdDisplayable){ 154 | userId = userItem.userInformation.userId; 155 | } 156 | } 157 | 158 | authContext.parentController = self; 159 | [ADAuthenticationSettings sharedInstance].enableFullScreen = appData.fullScreen; 160 | 161 | if(!appData.correlationId || 162 | [[appData.correlationId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) 163 | { 164 | authContext.correlationId = [[NSUUID alloc] initWithUUIDString:appData.correlationId]; 165 | } 166 | 167 | ADPromptBehavior promptBehavior = AD_PROMPT_AUTO; 168 | if(!userItem){ 169 | promptBehavior = AD_PROMPT_ALWAYS; 170 | } 171 | 172 | NSURL *redirectUri = [[NSURL alloc]initWithString:appData.redirectUriString]; 173 | [authContext acquireTokenWithResource:appData.resourceId 174 | clientId:appData.clientId 175 | redirectUri:redirectUri 176 | promptBehavior:promptBehavior 177 | userId:userId 178 | extraQueryParameters:@"nux=1" 179 | completionBlock:^(ADAuthenticationResult *result) { 180 | 181 | if (result.status != AD_SUCCEEDED) 182 | { 183 | UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:nil message:[[NSString alloc]initWithFormat:@"Error : %@", error.localizedDescription] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; 184 | 185 | [alertView setDelegate:self]; 186 | 187 | dispatch_async(dispatch_get_main_queue(),^ { 188 | [alertView show]; 189 | }); 190 | } 191 | else 192 | { 193 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 194 | data.userItem = result.tokenCacheStoreItem; 195 | [self cancelPressed:self]; 196 | } 197 | }]; 198 | 199 | } 200 | 201 | 202 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 203 | { 204 | if (buttonIndex == 0) 205 | { 206 | [alertView dismissWithClickedButtonIndex:0 animated:NO]; 207 | [self loadData]; 208 | } 209 | } 210 | 211 | 212 | 213 | @end 214 | 215 | -------------------------------------------------------------------------------- /Microsoft Tasks/samplesWebAPIConnector.m: -------------------------------------------------------------------------------- 1 | // 2 | // samplesWebAPIConnector.m 3 | // Microsoft Tasks 4 | // 5 | // Created by Brandon Werner on 3/11/14. 6 | // Copyright (c) 2014 Microsoft. All rights reserved. 7 | // 8 | 9 | 10 | #import "SamplesApplicationData.h" 11 | #import "samplesWebAPIConnector.h" 12 | #import "ADALiOS/ADAuthenticationContext.h" 13 | #import "samplesTaskItem.h" 14 | #import "samplesPolicyData.h" 15 | #import "ADALiOS/ADAuthenticationSettings.h" 16 | #import "NSDictionary+UrlEncoding.h" 17 | 18 | @implementation samplesWebAPIConnector 19 | 20 | ADAuthenticationContext* authContext; 21 | bool loadedApplicationSettings; 22 | 23 | + (void) readApplicationSettings { 24 | loadedApplicationSettings = YES; 25 | } 26 | 27 | +(NSString*) trimString: (NSString*) toTrim 28 | { 29 | //The white characters set is cached by the system: 30 | NSCharacterSet* set = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 31 | return [toTrim stringByTrimmingCharactersInSet:set]; 32 | } 33 | 34 | //getToken for generic Web API flows. Returns a token with no additional parameters provided. 35 | // 36 | // 37 | 38 | +(void) getToken : (BOOL) clearCache 39 | parent:(UIViewController*) parent 40 | completionHandler:(void (^) (NSString*, NSError*))completionBlock; 41 | { 42 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 43 | if(data.userItem){ 44 | completionBlock(data.userItem.accessToken, nil); 45 | return; 46 | } 47 | 48 | ADAuthenticationError *error; 49 | authContext = [ADAuthenticationContext authenticationContextWithAuthority:data.authority error:&error]; 50 | authContext.parentController = parent; 51 | NSURL *redirectUri = [[NSURL alloc]initWithString:data.redirectUriString]; 52 | 53 | if(!data.correlationId || 54 | [[data.correlationId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) 55 | { 56 | authContext.correlationId = [[NSUUID alloc] initWithUUIDString:data.correlationId]; 57 | } 58 | 59 | [ADAuthenticationSettings sharedInstance].enableFullScreen = data.fullScreen; 60 | [authContext acquireTokenWithResource:data.resourceId 61 | clientId:data.clientId 62 | redirectUri:redirectUri 63 | promptBehavior:AD_PROMPT_AUTO 64 | userId:data.userItem.userInformation.userId 65 | extraQueryParameters: @"nux=1" // if this strikes you as strange it was legacy to display the correct mobile UX. You most likely won't need it in your code. 66 | completionBlock:^(ADAuthenticationResult *result) { 67 | 68 | if (result.status != AD_SUCCEEDED) 69 | { 70 | completionBlock(nil, result.error); 71 | } 72 | else 73 | { 74 | data.userItem = result.tokenCacheStoreItem; 75 | completionBlock(result.tokenCacheStoreItem.accessToken, nil); 76 | } 77 | }]; 78 | } 79 | 80 | //getToken for support of sending extra (and unknown) params to the authorization and token endpoints 81 | // 82 | // 83 | 84 | +(void) getTokenWithExtraParams : (BOOL) clearCache 85 | params:(NSDictionary*) params 86 | parent:(UIViewController*) parent 87 | completionHandler:(void (^) (NSString*, NSError*))completionBlock; 88 | { 89 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 90 | 91 | 92 | ADAuthenticationError *error; 93 | authContext = [ADAuthenticationContext authenticationContextWithAuthority:data.authority error:&error]; 94 | authContext.parentController = parent; 95 | NSURL *redirectUri = [[NSURL alloc]initWithString:data.redirectUriString]; 96 | 97 | if(!data.correlationId || 98 | [[data.correlationId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) 99 | { 100 | authContext.correlationId = [[NSUUID alloc] initWithUUIDString:data.correlationId]; 101 | } 102 | 103 | [ADAuthenticationSettings sharedInstance].enableFullScreen = data.fullScreen; 104 | [authContext acquireTokenWithResource:data.resourceId 105 | clientId:data.clientId 106 | redirectUri:redirectUri 107 | promptBehavior:AD_PROMPT_AUTO 108 | userId:data.userItem.userInformation.userId 109 | extraQueryParameters: params.urlEncodedString 110 | completionBlock:^(ADAuthenticationResult *result) { 111 | 112 | if (result.status != AD_SUCCEEDED) 113 | { 114 | completionBlock(nil, result.error); 115 | } 116 | else 117 | { 118 | data.userItem = result.tokenCacheStoreItem; 119 | completionBlock(result.tokenCacheStoreItem.accessToken, nil); 120 | } 121 | }]; 122 | } 123 | 124 | // getToken for support of sending extra (and unknown) params to the authorization and token endpoints. 125 | // This method returns the entire claimset as stored in the userInformation collection instead of a token. 126 | // Use this only for display purposes, it is not necessary 127 | 128 | +(void) getClaimsWithExtraParams : (BOOL) clearCache 129 | params:(NSDictionary*) params 130 | parent:(UIViewController*) parent 131 | completionHandler:(void (^) (ADUserInformation*, NSError*))completionBlock; 132 | { 133 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 134 | 135 | 136 | ADAuthenticationError *error; 137 | authContext = [ADAuthenticationContext authenticationContextWithAuthority:data.authority error:&error]; 138 | authContext.parentController = parent; 139 | NSURL *redirectUri = [[NSURL alloc]initWithString:data.redirectUriString]; 140 | 141 | if(!data.correlationId || 142 | [[data.correlationId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) 143 | { 144 | authContext.correlationId = [[NSUUID alloc] initWithUUIDString:data.correlationId]; 145 | } 146 | 147 | [ADAuthenticationSettings sharedInstance].enableFullScreen = data.fullScreen; 148 | [authContext acquireTokenWithResource:data.resourceId 149 | clientId:data.clientId 150 | redirectUri:redirectUri 151 | promptBehavior:AD_PROMPT_ALWAYS 152 | userId:data.userItem.userInformation.userId 153 | extraQueryParameters: params.urlEncodedString 154 | completionBlock:^(ADAuthenticationResult *result) { 155 | 156 | if (result.status != AD_SUCCEEDED) 157 | { 158 | completionBlock(nil, result.error); 159 | } 160 | else 161 | { 162 | data.userItem = result.tokenCacheStoreItem; 163 | completionBlock(result.tokenCacheStoreItem.userInformation, nil); 164 | } 165 | }]; 166 | } 167 | 168 | 169 | // This method returns the entire claimset as stored in the userInformation collection instead of a token. 170 | // This is meant to show that Claims can be retreived without extra query params. You could easily pass getClaimsWithExtraParams with params = nil. 171 | 172 | +(void) getClaims : (BOOL) clearCache 173 | parent:(UIViewController*) parent 174 | completionHandler:(void (^) (ADUserInformation*, NSError*))completionBlock; 175 | { 176 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 177 | 178 | ADAuthenticationError *error; 179 | authContext = [ADAuthenticationContext authenticationContextWithAuthority:data.authority error:&error]; 180 | authContext.parentController = parent; 181 | NSURL *redirectUri = [[NSURL alloc]initWithString:data.redirectUriString]; 182 | 183 | if(!data.correlationId || 184 | [[data.correlationId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) 185 | { 186 | authContext.correlationId = [[NSUUID alloc] initWithUUIDString:data.correlationId]; 187 | } 188 | 189 | [ADAuthenticationSettings sharedInstance].enableFullScreen = data.fullScreen; 190 | [authContext acquireTokenWithResource:data.resourceId 191 | clientId:data.clientId 192 | redirectUri:redirectUri 193 | promptBehavior:AD_PROMPT_ALWAYS 194 | userId:nil 195 | extraQueryParameters: @"nux=1" // if this strikes you as strange it was legacy to display the correct mobile UX. You most likely won't need it in your code. 196 | 197 | completionBlock:^(ADAuthenticationResult *result) { 198 | 199 | if (result.status != AD_SUCCEEDED) 200 | { 201 | completionBlock(nil, result.error); 202 | } 203 | else 204 | { 205 | data.userItem = result.tokenCacheStoreItem; 206 | completionBlock(result.tokenCacheStoreItem.userInformation, nil); 207 | } 208 | }]; 209 | } 210 | 211 | +(void) getTaskList:(void (^) (NSArray*, NSError*))completionBlock 212 | parent:(UIViewController*) parent; 213 | { 214 | if (!loadedApplicationSettings) 215 | { 216 | [self readApplicationSettings]; 217 | } 218 | 219 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 220 | 221 | [self craftRequest:[self.class trimString:data.taskWebApiUrlString] 222 | parent:parent 223 | completionHandler:^(NSMutableURLRequest *request, NSError *error) { 224 | 225 | if (error != nil) 226 | { 227 | completionBlock(nil, error); 228 | } 229 | else 230 | { 231 | 232 | NSOperationQueue *queue = [[NSOperationQueue alloc]init]; 233 | 234 | [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 235 | 236 | if (error == nil && data != nil){ 237 | 238 | NSArray *tasks = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 239 | 240 | //each object is a key value pair 241 | NSDictionary *keyValuePairs; 242 | NSMutableArray* sampleTaskItems = [[NSMutableArray alloc]init]; 243 | 244 | for(int i =0; i < tasks.count; i++) 245 | { 246 | keyValuePairs = [tasks objectAtIndex:i]; 247 | 248 | samplesTaskItem *s = [[samplesTaskItem alloc]init]; 249 | s.itemName = [keyValuePairs valueForKey:@"Text"]; 250 | 251 | [sampleTaskItems addObject:s]; 252 | } 253 | 254 | completionBlock(sampleTaskItems, nil); 255 | } 256 | else 257 | { 258 | completionBlock(nil, error); 259 | } 260 | 261 | }]; 262 | } 263 | }]; 264 | 265 | } 266 | 267 | +(void) addTask:(samplesTaskItem*)task 268 | parent:(UIViewController*) parent 269 | completionBlock:(void (^) (bool, NSError* error)) completionBlock 270 | { 271 | if (!loadedApplicationSettings) 272 | { 273 | [self readApplicationSettings]; 274 | } 275 | 276 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 277 | [self craftRequest:data.taskWebApiUrlString parent:parent completionHandler:^(NSMutableURLRequest* request, NSError* error){ 278 | 279 | if (error != nil) 280 | { 281 | completionBlock(NO, error); 282 | } 283 | else 284 | { 285 | NSDictionary* taskInDictionaryFormat = [self convertTaskToDictionary:task]; 286 | 287 | NSData* requestBody = [NSJSONSerialization dataWithJSONObject:taskInDictionaryFormat options:0 error:nil]; 288 | 289 | [request setHTTPMethod:@"POST"]; 290 | [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 291 | [request setHTTPBody:requestBody]; 292 | 293 | NSOperationQueue *queue = [[NSOperationQueue alloc]init]; 294 | 295 | [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 296 | 297 | NSString* content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 298 | NSLog(@"%@", content); 299 | 300 | if (error == nil){ 301 | 302 | completionBlock(true, nil); 303 | } 304 | else 305 | { 306 | completionBlock(false, error); 307 | } 308 | }]; 309 | } 310 | }]; 311 | } 312 | 313 | +(void) deleteTask:(samplesTaskItem*)task 314 | parent:(UIViewController*) parent 315 | completionBlock:(void (^) (bool, NSError* error)) completionBlock 316 | { 317 | if (!loadedApplicationSettings) 318 | { 319 | [self readApplicationSettings]; 320 | } 321 | 322 | SamplesApplicationData* data = [SamplesApplicationData getInstance]; 323 | [self craftRequest:data.taskWebApiUrlString parent:parent completionHandler:^(NSMutableURLRequest* request, NSError* error){ 324 | 325 | if (error != nil) 326 | { 327 | completionBlock(NO, error); 328 | } 329 | else 330 | { 331 | NSDictionary* taskInDictionaryFormat = [self convertTaskToDictionary:task]; 332 | 333 | NSData* requestBody = [NSJSONSerialization dataWithJSONObject:taskInDictionaryFormat options:0 error:nil]; 334 | 335 | [request setHTTPMethod:@"DELETE"]; 336 | [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 337 | [request setHTTPBody:requestBody]; 338 | 339 | NSLog(@"%@", request); 340 | 341 | NSOperationQueue *queue = [[NSOperationQueue alloc]init]; 342 | 343 | [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 344 | 345 | NSString* content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 346 | NSLog(@"%@", content); 347 | 348 | if (error == nil){ 349 | 350 | completionBlock(true, nil); 351 | } 352 | else 353 | { 354 | completionBlock(false, error); 355 | } 356 | }]; 357 | } 358 | }]; 359 | } 360 | 361 | 362 | // A simple callback that makes sense of all the getClaims* above. 363 | 364 | +(void) doLogin:(BOOL) prompt 365 | parent:(UIViewController*) parent 366 | completionBlock:(void (^) (ADUserInformation* userInfo, NSError* error)) completionBlock 367 | { 368 | if (!loadedApplicationSettings) 369 | { 370 | [self readApplicationSettings]; 371 | } 372 | 373 | [self getClaims:NO parent:parent completionHandler:^(ADUserInformation* userInfo, NSError* error) { 374 | 375 | if (userInfo == nil) 376 | { 377 | completionBlock(nil, error); 378 | } 379 | 380 | else { 381 | 382 | completionBlock(userInfo, nil); 383 | } 384 | }]; 385 | 386 | } 387 | 388 | // Although not yet used in this sample, this demonstrates how you could pass policies to the server. 389 | // See the Native-iOS-B2C sample for more information. 390 | 391 | +(void) doPolicy:(samplesPolicyData *)policy 392 | parent:(UIViewController*) parent 393 | completionBlock:(void (^) (ADUserInformation* userInfo, NSError* error)) completionBlock 394 | { 395 | if (!loadedApplicationSettings) 396 | { 397 | [self readApplicationSettings]; 398 | } 399 | 400 | NSDictionary* params = [self convertPolicyToDictionary:policy]; 401 | 402 | [self getClaimsWithExtraParams:NO params:params parent:parent completionHandler:^(ADUserInformation* userInfo, NSError* error) { 403 | 404 | if (userInfo == nil) 405 | { 406 | completionBlock(nil, error); 407 | } 408 | 409 | else { 410 | 411 | completionBlock(userInfo, nil); 412 | } 413 | }]; 414 | 415 | } 416 | 417 | +(void) craftRequest : (NSString*)webApiUrlString 418 | parent:(UIViewController*) parent 419 | completionHandler:(void (^)(NSMutableURLRequest*, NSError* error))completionBlock 420 | { 421 | [self getToken:NO parent:parent completionHandler:^(NSString* accessToken, NSError* error){ 422 | 423 | if (accessToken == nil) 424 | { 425 | completionBlock(nil,error); 426 | } 427 | else 428 | { 429 | NSURL *webApiURL = [[NSURL alloc]initWithString:webApiUrlString]; 430 | 431 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:webApiURL]; 432 | 433 | NSString *authHeader = [NSString stringWithFormat:@"Bearer %@", accessToken]; 434 | 435 | [request addValue:authHeader forHTTPHeaderField:@"Authorization"]; 436 | 437 | completionBlock(request, nil); 438 | } 439 | }]; 440 | } 441 | 442 | // Here we have some converstion helpers that allow us to parse passed items in to dictionaries for URLEncoding later. 443 | 444 | +(NSDictionary*) convertTaskToDictionary:(samplesTaskItem*)task 445 | { 446 | NSMutableDictionary* dictionary = [[NSMutableDictionary alloc]init]; 447 | 448 | if (task.itemName){ 449 | [dictionary setValue:task.itemName forKey:@"Text"]; 450 | } 451 | 452 | return dictionary; 453 | } 454 | 455 | +(NSDictionary*) convertPolicyToDictionary:(samplesPolicyData*)policy 456 | { 457 | NSMutableDictionary* dictionary = [[NSMutableDictionary alloc]init]; 458 | 459 | // Using UUID for nonce. Not recommended. 460 | 461 | NSString *UUID = [[NSUUID UUID] UUIDString]; 462 | 463 | 464 | if (policy.policyID){ 465 | [dictionary setValue:policy.policyID forKey:@"p"]; 466 | [dictionary setValue:@"openid" forKey:@"scope"]; 467 | [dictionary setValue:UUID forKey:@"nonce"]; 468 | [dictionary setValue:@"query" forKey:@"response_mode"]; 469 | [dictionary setValue:@"1" forKey:@"nux"]; 470 | } 471 | 472 | return dictionary; 473 | } 474 | 475 | 476 | 477 | +(void) signOut 478 | { 479 | [authContext.tokenCacheStore removeAllWithError:nil]; 480 | 481 | NSHTTPCookie *cookie; 482 | 483 | NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; 484 | for (cookie in [storage cookies]) 485 | { 486 | [storage deleteCookie:cookie]; 487 | } 488 | } 489 | 490 | @end 491 | -------------------------------------------------------------------------------- /Microsoft Tasks/Main_iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 190 | 191 | 192 | 193 | Access Microsoft Tasks using your Microsoft Work Account. You can use any user in your tenant if you have granted permission to use the app in your Azure administrative console. 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 267 | 268 | 269 | 270 | 271 | 272 | 278 | 279 | 280 | 281 | 282 | 283 | 289 | 290 | 291 | 292 | 293 | 294 | 300 | 301 | 302 | 303 | 304 | 305 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 324 | 325 | 326 | 327 | 328 | 329 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 407 | 408 | 409 | 410 | Change the settings this application uses at runtime. Very convinient for changing your Task server or for changing user policies that are invoked at the server. 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | -------------------------------------------------------------------------------- /Microsoft Tasks.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 97C15AF41A27FDF0004A0419 /* SamplesSelectUserViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C15AF31A27FDF0004A0419 /* SamplesSelectUserViewController.m */; }; 11 | 97C15AF71A280BEF004A0419 /* SamplesApplicationData.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C15AF61A280BEF004A0419 /* SamplesApplicationData.m */; }; 12 | 97C15AFA1A29C9F3004A0419 /* SamplesAppSettingsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C15AF91A29C9F3004A0419 /* SamplesAppSettingsController.m */; }; 13 | A7C8E8174A44140EEB0E7EF2 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 075B6E5720AC4E29872664F4 /* libPods.a */; }; 14 | B82906B71AE6C98300E1977C /* NSDictionary+UrlEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = B82906B61AE6C98300E1977C /* NSDictionary+UrlEncoding.m */; }; 15 | B82906B91AE6CA8100E1977C /* samplesPolicyData.m in Sources */ = {isa = PBXBuildFile; fileRef = B82906B81AE6CA8100E1977C /* samplesPolicyData.m */; }; 16 | B82906BD1AE6CD1100E1977C /* samplesShowClaimsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B82906BC1AE6CD1100E1977C /* samplesShowClaimsViewController.m */; }; 17 | B82906C01AE6DA2A00E1977C /* samplesLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B82906BF1AE6DA2A00E1977C /* samplesLoginViewController.m */; }; 18 | EC01CD8C7777703E90A7F804 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 075B6E5720AC4E29872664F4 /* libPods.a */; }; 19 | FB33714918CA5B7E00234804 /* settings.plist in Resources */ = {isa = PBXBuildFile; fileRef = FB33714818CA5B7E00234804 /* settings.plist */; }; 20 | FB3BF22018D0106C007E645E /* samplesWebAPIConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3BF21F18D0106C007E645E /* samplesWebAPIConnector.m */; }; 21 | FB3BF22118D0106C007E645E /* samplesWebAPIConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3BF21F18D0106C007E645E /* samplesWebAPIConnector.m */; }; 22 | FB3BF23518D03A88007E645E /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB3BF23218D03A88007E645E /* Main_iPhone.storyboard */; }; 23 | FB3BF23618D03A88007E645E /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FB3BF23218D03A88007E645E /* Main_iPhone.storyboard */; }; 24 | FB3F00DA18C7016200173598 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00D918C7016200173598 /* Foundation.framework */; }; 25 | FB3F00DC18C7016200173598 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00DB18C7016200173598 /* CoreGraphics.framework */; }; 26 | FB3F00DE18C7016200173598 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00DD18C7016200173598 /* UIKit.framework */; }; 27 | FB3F00E018C7016200173598 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00DF18C7016200173598 /* CoreData.framework */; }; 28 | FB3F00E618C7016200173598 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FB3F00E418C7016200173598 /* InfoPlist.strings */; }; 29 | FB3F00E818C7016200173598 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3F00E718C7016200173598 /* main.m */; }; 30 | FB3F00EC18C7016200173598 /* samplesAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3F00EB18C7016200173598 /* samplesAppDelegate.m */; }; 31 | FB3F00EF18C7016200173598 /* Microsoft_Tasks.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FB3F00ED18C7016200173598 /* Microsoft_Tasks.xcdatamodeld */; }; 32 | FB3F00F118C7016200173598 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FB3F00F018C7016200173598 /* Images.xcassets */; }; 33 | FB3F00F818C7016200173598 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00F718C7016200173598 /* XCTest.framework */; }; 34 | FB3F00F918C7016200173598 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00D918C7016200173598 /* Foundation.framework */; }; 35 | FB3F00FA18C7016200173598 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00DD18C7016200173598 /* UIKit.framework */; }; 36 | FB3F00FB18C7016200173598 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB3F00DF18C7016200173598 /* CoreData.framework */; }; 37 | FB3F010318C7016200173598 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FB3F010118C7016200173598 /* InfoPlist.strings */; }; 38 | FB3F010518C7016200173598 /* Microsoft_TasksTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3F010418C7016200173598 /* Microsoft_TasksTests.m */; }; 39 | FB3F011618C7092700173598 /* sampleAddTaskItemViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3F011518C7092700173598 /* sampleAddTaskItemViewController.m */; }; 40 | FB3F011C18C709FE00173598 /* samplesTaskListTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3F011B18C709FE00173598 /* samplesTaskListTableViewController.m */; }; 41 | FB3F011F18C713E600173598 /* samplesTaskItem.m in Sources */ = {isa = PBXBuildFile; fileRef = FB3F011E18C713E600173598 /* samplesTaskItem.m */; }; 42 | /* End PBXBuildFile section */ 43 | 44 | /* Begin PBXContainerItemProxy section */ 45 | FB3F00FC18C7016200173598 /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = FB3F00CE18C7016200173598 /* Project object */; 48 | proxyType = 1; 49 | remoteGlobalIDString = FB3F00D518C7016200173598; 50 | remoteInfo = "Microsoft Tasks"; 51 | }; 52 | /* End PBXContainerItemProxy section */ 53 | 54 | /* Begin PBXFileReference section */ 55 | 075B6E5720AC4E29872664F4 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 268C6853C490B04D8D505AD7 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 57 | 32C2DA3BB2D20EAD1E82DBA0 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 58 | 971963C41A6845950026BC5F /* Microsoft Tasks.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Microsoft Tasks.entitlements"; sourceTree = ""; }; 59 | 97C15AF01A27FAD6004A0419 /* SamplesSelectUserViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SamplesSelectUserViewController.h; sourceTree = ""; }; 60 | 97C15AF31A27FDF0004A0419 /* SamplesSelectUserViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SamplesSelectUserViewController.m; sourceTree = ""; }; 61 | 97C15AF51A280B69004A0419 /* SamplesApplicationData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SamplesApplicationData.h; sourceTree = ""; }; 62 | 97C15AF61A280BEF004A0419 /* SamplesApplicationData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SamplesApplicationData.m; sourceTree = ""; }; 63 | 97C15AF81A29C9E3004A0419 /* SamplesAppSettingsController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplesAppSettingsController.h; sourceTree = ""; }; 64 | 97C15AF91A29C9F3004A0419 /* SamplesAppSettingsController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SamplesAppSettingsController.m; sourceTree = ""; }; 65 | B82906B51AE6C98300E1977C /* NSDictionary+UrlEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+UrlEncoding.h"; sourceTree = ""; }; 66 | B82906B61AE6C98300E1977C /* NSDictionary+UrlEncoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+UrlEncoding.m"; sourceTree = ""; }; 67 | B82906B81AE6CA8100E1977C /* samplesPolicyData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = samplesPolicyData.m; sourceTree = ""; }; 68 | B82906BA1AE6CA9400E1977C /* samplesPolicyData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = samplesPolicyData.h; sourceTree = ""; }; 69 | B82906BB1AE6CD1100E1977C /* samplesShowClaimsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = samplesShowClaimsViewController.h; sourceTree = ""; }; 70 | B82906BC1AE6CD1100E1977C /* samplesShowClaimsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = samplesShowClaimsViewController.m; sourceTree = ""; }; 71 | B82906BE1AE6DA2A00E1977C /* samplesLoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = samplesLoginViewController.h; sourceTree = ""; }; 72 | B82906BF1AE6DA2A00E1977C /* samplesLoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = samplesLoginViewController.m; sourceTree = ""; }; 73 | FB33714818CA5B7E00234804 /* settings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = settings.plist; sourceTree = ""; }; 74 | FB3BF21E18D0106C007E645E /* samplesWebAPIConnector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = samplesWebAPIConnector.h; sourceTree = ""; }; 75 | FB3BF21F18D0106C007E645E /* samplesWebAPIConnector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = samplesWebAPIConnector.m; sourceTree = ""; }; 76 | FB3BF23218D03A88007E645E /* Main_iPhone.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main_iPhone.storyboard; sourceTree = ""; }; 77 | FB3F00D618C7016200173598 /* Microsoft Tasks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Microsoft Tasks.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 78 | FB3F00D918C7016200173598 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 79 | FB3F00DB18C7016200173598 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 80 | FB3F00DD18C7016200173598 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 81 | FB3F00DF18C7016200173598 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 82 | FB3F00E318C7016200173598 /* Microsoft Tasks-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Microsoft Tasks-Info.plist"; sourceTree = ""; }; 83 | FB3F00E518C7016200173598 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 84 | FB3F00E718C7016200173598 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 85 | FB3F00E918C7016200173598 /* Microsoft Tasks-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Microsoft Tasks-Prefix.pch"; sourceTree = ""; }; 86 | FB3F00EA18C7016200173598 /* samplesAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = samplesAppDelegate.h; sourceTree = ""; }; 87 | FB3F00EB18C7016200173598 /* samplesAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = samplesAppDelegate.m; sourceTree = ""; }; 88 | FB3F00EE18C7016200173598 /* Microsoft_Tasks.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Microsoft_Tasks.xcdatamodel; sourceTree = ""; }; 89 | FB3F00F018C7016200173598 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 90 | FB3F00F618C7016200173598 /* Microsoft TasksTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Microsoft TasksTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 91 | FB3F00F718C7016200173598 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 92 | FB3F010018C7016200173598 /* Microsoft TasksTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Microsoft TasksTests-Info.plist"; sourceTree = ""; }; 93 | FB3F010218C7016200173598 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 94 | FB3F010418C7016200173598 /* Microsoft_TasksTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Microsoft_TasksTests.m; sourceTree = ""; }; 95 | FB3F011418C7092700173598 /* sampleAddTaskItemViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sampleAddTaskItemViewController.h; sourceTree = ""; }; 96 | FB3F011518C7092700173598 /* sampleAddTaskItemViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = sampleAddTaskItemViewController.m; sourceTree = ""; }; 97 | FB3F011A18C709FE00173598 /* samplesTaskListTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = samplesTaskListTableViewController.h; sourceTree = ""; }; 98 | FB3F011B18C709FE00173598 /* samplesTaskListTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = samplesTaskListTableViewController.m; sourceTree = ""; }; 99 | FB3F011D18C713E600173598 /* samplesTaskItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = samplesTaskItem.h; sourceTree = ""; }; 100 | FB3F011E18C713E600173598 /* samplesTaskItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = samplesTaskItem.m; sourceTree = ""; }; 101 | /* End PBXFileReference section */ 102 | 103 | /* Begin PBXFrameworksBuildPhase section */ 104 | FB3F00D318C7016200173598 /* Frameworks */ = { 105 | isa = PBXFrameworksBuildPhase; 106 | buildActionMask = 2147483647; 107 | files = ( 108 | FB3F00DC18C7016200173598 /* CoreGraphics.framework in Frameworks */, 109 | FB3F00E018C7016200173598 /* CoreData.framework in Frameworks */, 110 | FB3F00DE18C7016200173598 /* UIKit.framework in Frameworks */, 111 | FB3F00DA18C7016200173598 /* Foundation.framework in Frameworks */, 112 | A7C8E8174A44140EEB0E7EF2 /* libPods.a in Frameworks */, 113 | ); 114 | runOnlyForDeploymentPostprocessing = 0; 115 | }; 116 | FB3F00F318C7016200173598 /* Frameworks */ = { 117 | isa = PBXFrameworksBuildPhase; 118 | buildActionMask = 2147483647; 119 | files = ( 120 | FB3F00F818C7016200173598 /* XCTest.framework in Frameworks */, 121 | FB3F00FB18C7016200173598 /* CoreData.framework in Frameworks */, 122 | FB3F00FA18C7016200173598 /* UIKit.framework in Frameworks */, 123 | FB3F00F918C7016200173598 /* Foundation.framework in Frameworks */, 124 | EC01CD8C7777703E90A7F804 /* libPods.a in Frameworks */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | /* End PBXFrameworksBuildPhase section */ 129 | 130 | /* Begin PBXGroup section */ 131 | 3815BCDF3B86DDADB63BCC4F /* Pods */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 268C6853C490B04D8D505AD7 /* Pods.debug.xcconfig */, 135 | 32C2DA3BB2D20EAD1E82DBA0 /* Pods.release.xcconfig */, 136 | ); 137 | name = Pods; 138 | sourceTree = ""; 139 | }; 140 | FB3F00CD18C7016200173598 = { 141 | isa = PBXGroup; 142 | children = ( 143 | FB3F00E118C7016200173598 /* Microsoft Tasks */, 144 | FB3F00FE18C7016200173598 /* Microsoft TasksTests */, 145 | FB3F00D818C7016200173598 /* Frameworks */, 146 | FB3F00D718C7016200173598 /* Products */, 147 | 3815BCDF3B86DDADB63BCC4F /* Pods */, 148 | ); 149 | sourceTree = ""; 150 | }; 151 | FB3F00D718C7016200173598 /* Products */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | FB3F00D618C7016200173598 /* Microsoft Tasks.app */, 155 | FB3F00F618C7016200173598 /* Microsoft TasksTests.xctest */, 156 | ); 157 | name = Products; 158 | sourceTree = ""; 159 | }; 160 | FB3F00D818C7016200173598 /* Frameworks */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | FB3F00D918C7016200173598 /* Foundation.framework */, 164 | FB3F00DB18C7016200173598 /* CoreGraphics.framework */, 165 | FB3F00DD18C7016200173598 /* UIKit.framework */, 166 | FB3F00DF18C7016200173598 /* CoreData.framework */, 167 | FB3F00F718C7016200173598 /* XCTest.framework */, 168 | 075B6E5720AC4E29872664F4 /* libPods.a */, 169 | ); 170 | name = Frameworks; 171 | sourceTree = ""; 172 | }; 173 | FB3F00E118C7016200173598 /* Microsoft Tasks */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 971963C41A6845950026BC5F /* Microsoft Tasks.entitlements */, 177 | FB3BF23218D03A88007E645E /* Main_iPhone.storyboard */, 178 | FB3F00E418C7016200173598 /* InfoPlist.strings */, 179 | FB3F00EA18C7016200173598 /* samplesAppDelegate.h */, 180 | FB3F00EB18C7016200173598 /* samplesAppDelegate.m */, 181 | FB3F00F018C7016200173598 /* Images.xcassets */, 182 | FB3F00ED18C7016200173598 /* Microsoft_Tasks.xcdatamodeld */, 183 | FB3F00E218C7016200173598 /* Supporting Files */, 184 | FB3F011418C7092700173598 /* sampleAddTaskItemViewController.h */, 185 | FB3F011518C7092700173598 /* sampleAddTaskItemViewController.m */, 186 | FB3F011A18C709FE00173598 /* samplesTaskListTableViewController.h */, 187 | FB3F011B18C709FE00173598 /* samplesTaskListTableViewController.m */, 188 | FB3F011D18C713E600173598 /* samplesTaskItem.h */, 189 | FB3F011E18C713E600173598 /* samplesTaskItem.m */, 190 | FB3BF21E18D0106C007E645E /* samplesWebAPIConnector.h */, 191 | FB3BF21F18D0106C007E645E /* samplesWebAPIConnector.m */, 192 | 97C15AF01A27FAD6004A0419 /* SamplesSelectUserViewController.h */, 193 | 97C15AF31A27FDF0004A0419 /* SamplesSelectUserViewController.m */, 194 | 97C15AF51A280B69004A0419 /* SamplesApplicationData.h */, 195 | 97C15AF61A280BEF004A0419 /* SamplesApplicationData.m */, 196 | 97C15AF81A29C9E3004A0419 /* SamplesAppSettingsController.h */, 197 | 97C15AF91A29C9F3004A0419 /* SamplesAppSettingsController.m */, 198 | B82906B51AE6C98300E1977C /* NSDictionary+UrlEncoding.h */, 199 | B82906B61AE6C98300E1977C /* NSDictionary+UrlEncoding.m */, 200 | B82906B81AE6CA8100E1977C /* samplesPolicyData.m */, 201 | B82906BA1AE6CA9400E1977C /* samplesPolicyData.h */, 202 | B82906BB1AE6CD1100E1977C /* samplesShowClaimsViewController.h */, 203 | B82906BC1AE6CD1100E1977C /* samplesShowClaimsViewController.m */, 204 | B82906BE1AE6DA2A00E1977C /* samplesLoginViewController.h */, 205 | B82906BF1AE6DA2A00E1977C /* samplesLoginViewController.m */, 206 | ); 207 | path = "Microsoft Tasks"; 208 | sourceTree = ""; 209 | }; 210 | FB3F00E218C7016200173598 /* Supporting Files */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | FB3F00E318C7016200173598 /* Microsoft Tasks-Info.plist */, 214 | FB3F00E718C7016200173598 /* main.m */, 215 | FB3F00E918C7016200173598 /* Microsoft Tasks-Prefix.pch */, 216 | FB33714818CA5B7E00234804 /* settings.plist */, 217 | ); 218 | name = "Supporting Files"; 219 | sourceTree = ""; 220 | }; 221 | FB3F00FE18C7016200173598 /* Microsoft TasksTests */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | FB3F010418C7016200173598 /* Microsoft_TasksTests.m */, 225 | FB3F00FF18C7016200173598 /* Supporting Files */, 226 | ); 227 | path = "Microsoft TasksTests"; 228 | sourceTree = ""; 229 | }; 230 | FB3F00FF18C7016200173598 /* Supporting Files */ = { 231 | isa = PBXGroup; 232 | children = ( 233 | FB3F010018C7016200173598 /* Microsoft TasksTests-Info.plist */, 234 | FB3F010118C7016200173598 /* InfoPlist.strings */, 235 | ); 236 | name = "Supporting Files"; 237 | sourceTree = ""; 238 | }; 239 | /* End PBXGroup section */ 240 | 241 | /* Begin PBXNativeTarget section */ 242 | FB3F00D518C7016200173598 /* Microsoft Tasks */ = { 243 | isa = PBXNativeTarget; 244 | buildConfigurationList = FB3F010818C7016200173598 /* Build configuration list for PBXNativeTarget "Microsoft Tasks" */; 245 | buildPhases = ( 246 | 242E920A0FC14065B8E09F12 /* Check Pods Manifest.lock */, 247 | FB3F00D218C7016200173598 /* Sources */, 248 | FB3F00D318C7016200173598 /* Frameworks */, 249 | FB3F00D418C7016200173598 /* Resources */, 250 | 2E16D7D83C534279873FC06F /* Copy Pods Resources */, 251 | B844A9A71AEF103A00224ED9 /* ShellScript */, 252 | ); 253 | buildRules = ( 254 | ); 255 | dependencies = ( 256 | ); 257 | name = "Microsoft Tasks"; 258 | productName = "Microsoft Tasks"; 259 | productReference = FB3F00D618C7016200173598 /* Microsoft Tasks.app */; 260 | productType = "com.apple.product-type.application"; 261 | }; 262 | FB3F00F518C7016200173598 /* Microsoft TasksTests */ = { 263 | isa = PBXNativeTarget; 264 | buildConfigurationList = FB3F010B18C7016200173598 /* Build configuration list for PBXNativeTarget "Microsoft TasksTests" */; 265 | buildPhases = ( 266 | 573F442CE68680C3300FD91C /* Check Pods Manifest.lock */, 267 | FB3F00F218C7016200173598 /* Sources */, 268 | FB3F00F318C7016200173598 /* Frameworks */, 269 | FB3F00F418C7016200173598 /* Resources */, 270 | AD96A739D75DFECDEA53C42D /* Copy Pods Resources */, 271 | ); 272 | buildRules = ( 273 | ); 274 | dependencies = ( 275 | FB3F00FD18C7016200173598 /* PBXTargetDependency */, 276 | ); 277 | name = "Microsoft TasksTests"; 278 | productName = "Microsoft TasksTests"; 279 | productReference = FB3F00F618C7016200173598 /* Microsoft TasksTests.xctest */; 280 | productType = "com.apple.product-type.bundle.unit-test"; 281 | }; 282 | /* End PBXNativeTarget section */ 283 | 284 | /* Begin PBXProject section */ 285 | FB3F00CE18C7016200173598 /* Project object */ = { 286 | isa = PBXProject; 287 | attributes = { 288 | CLASSPREFIX = samples; 289 | LastUpgradeCheck = 0510; 290 | ORGANIZATIONNAME = Microsoft; 291 | TargetAttributes = { 292 | FB3F00D518C7016200173598 = { 293 | DevelopmentTeam = QPA5Y64RGS; 294 | SystemCapabilities = { 295 | com.apple.Keychain = { 296 | enabled = 1; 297 | }; 298 | }; 299 | }; 300 | FB3F00F518C7016200173598 = { 301 | TestTargetID = FB3F00D518C7016200173598; 302 | }; 303 | }; 304 | }; 305 | buildConfigurationList = FB3F00D118C7016200173598 /* Build configuration list for PBXProject "Microsoft Tasks" */; 306 | compatibilityVersion = "Xcode 3.2"; 307 | developmentRegion = English; 308 | hasScannedForEncodings = 0; 309 | knownRegions = ( 310 | en, 311 | ); 312 | mainGroup = FB3F00CD18C7016200173598; 313 | productRefGroup = FB3F00D718C7016200173598 /* Products */; 314 | projectDirPath = ""; 315 | projectRoot = ""; 316 | targets = ( 317 | FB3F00D518C7016200173598 /* Microsoft Tasks */, 318 | FB3F00F518C7016200173598 /* Microsoft TasksTests */, 319 | ); 320 | }; 321 | /* End PBXProject section */ 322 | 323 | /* Begin PBXResourcesBuildPhase section */ 324 | FB3F00D418C7016200173598 /* Resources */ = { 325 | isa = PBXResourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | FB3BF23518D03A88007E645E /* Main_iPhone.storyboard in Resources */, 329 | FB3F00E618C7016200173598 /* InfoPlist.strings in Resources */, 330 | FB3F00F118C7016200173598 /* Images.xcassets in Resources */, 331 | FB33714918CA5B7E00234804 /* settings.plist in Resources */, 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | FB3F00F418C7016200173598 /* Resources */ = { 336 | isa = PBXResourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | FB3F010318C7016200173598 /* InfoPlist.strings in Resources */, 340 | FB3BF23618D03A88007E645E /* Main_iPhone.storyboard in Resources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | /* End PBXResourcesBuildPhase section */ 345 | 346 | /* Begin PBXShellScriptBuildPhase section */ 347 | 242E920A0FC14065B8E09F12 /* Check Pods Manifest.lock */ = { 348 | isa = PBXShellScriptBuildPhase; 349 | buildActionMask = 2147483647; 350 | files = ( 351 | ); 352 | inputPaths = ( 353 | ); 354 | name = "Check Pods Manifest.lock"; 355 | outputPaths = ( 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | shellPath = /bin/sh; 359 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 360 | showEnvVarsInLog = 0; 361 | }; 362 | 2E16D7D83C534279873FC06F /* Copy Pods Resources */ = { 363 | isa = PBXShellScriptBuildPhase; 364 | buildActionMask = 2147483647; 365 | files = ( 366 | ); 367 | inputPaths = ( 368 | ); 369 | name = "Copy Pods Resources"; 370 | outputPaths = ( 371 | ); 372 | runOnlyForDeploymentPostprocessing = 0; 373 | shellPath = /bin/sh; 374 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 375 | showEnvVarsInLog = 0; 376 | }; 377 | 573F442CE68680C3300FD91C /* Check Pods Manifest.lock */ = { 378 | isa = PBXShellScriptBuildPhase; 379 | buildActionMask = 2147483647; 380 | files = ( 381 | ); 382 | inputPaths = ( 383 | ); 384 | name = "Check Pods Manifest.lock"; 385 | outputPaths = ( 386 | ); 387 | runOnlyForDeploymentPostprocessing = 0; 388 | shellPath = /bin/sh; 389 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 390 | showEnvVarsInLog = 0; 391 | }; 392 | AD96A739D75DFECDEA53C42D /* Copy Pods Resources */ = { 393 | isa = PBXShellScriptBuildPhase; 394 | buildActionMask = 2147483647; 395 | files = ( 396 | ); 397 | inputPaths = ( 398 | ); 399 | name = "Copy Pods Resources"; 400 | outputPaths = ( 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | shellPath = /bin/sh; 404 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 405 | showEnvVarsInLog = 0; 406 | }; 407 | B844A9A71AEF103A00224ED9 /* ShellScript */ = { 408 | isa = PBXShellScriptBuildPhase; 409 | buildActionMask = 2147483647; 410 | files = ( 411 | ); 412 | inputPaths = ( 413 | ); 414 | outputPaths = ( 415 | ); 416 | runOnlyForDeploymentPostprocessing = 0; 417 | shellPath = /bin/sh; 418 | shellScript = "FILE=\"${SRCROOT}/HockeySDK-iOS/BuildAgent\"\nif [ -f \"$FILE\" ]; then\n\"$FILE\"\nfi"; 419 | }; 420 | /* End PBXShellScriptBuildPhase section */ 421 | 422 | /* Begin PBXSourcesBuildPhase section */ 423 | FB3F00D218C7016200173598 /* Sources */ = { 424 | isa = PBXSourcesBuildPhase; 425 | buildActionMask = 2147483647; 426 | files = ( 427 | 97C15AFA1A29C9F3004A0419 /* SamplesAppSettingsController.m in Sources */, 428 | FB3F011618C7092700173598 /* sampleAddTaskItemViewController.m in Sources */, 429 | B82906B71AE6C98300E1977C /* NSDictionary+UrlEncoding.m in Sources */, 430 | FB3F011F18C713E600173598 /* samplesTaskItem.m in Sources */, 431 | FB3F00EF18C7016200173598 /* Microsoft_Tasks.xcdatamodeld in Sources */, 432 | B82906B91AE6CA8100E1977C /* samplesPolicyData.m in Sources */, 433 | B82906BD1AE6CD1100E1977C /* samplesShowClaimsViewController.m in Sources */, 434 | FB3F011C18C709FE00173598 /* samplesTaskListTableViewController.m in Sources */, 435 | FB3F00EC18C7016200173598 /* samplesAppDelegate.m in Sources */, 436 | 97C15AF71A280BEF004A0419 /* SamplesApplicationData.m in Sources */, 437 | B82906C01AE6DA2A00E1977C /* samplesLoginViewController.m in Sources */, 438 | FB3BF22018D0106C007E645E /* samplesWebAPIConnector.m in Sources */, 439 | 97C15AF41A27FDF0004A0419 /* SamplesSelectUserViewController.m in Sources */, 440 | FB3F00E818C7016200173598 /* main.m in Sources */, 441 | ); 442 | runOnlyForDeploymentPostprocessing = 0; 443 | }; 444 | FB3F00F218C7016200173598 /* Sources */ = { 445 | isa = PBXSourcesBuildPhase; 446 | buildActionMask = 2147483647; 447 | files = ( 448 | FB3F010518C7016200173598 /* Microsoft_TasksTests.m in Sources */, 449 | FB3BF22118D0106C007E645E /* samplesWebAPIConnector.m in Sources */, 450 | ); 451 | runOnlyForDeploymentPostprocessing = 0; 452 | }; 453 | /* End PBXSourcesBuildPhase section */ 454 | 455 | /* Begin PBXTargetDependency section */ 456 | FB3F00FD18C7016200173598 /* PBXTargetDependency */ = { 457 | isa = PBXTargetDependency; 458 | target = FB3F00D518C7016200173598 /* Microsoft Tasks */; 459 | targetProxy = FB3F00FC18C7016200173598 /* PBXContainerItemProxy */; 460 | }; 461 | /* End PBXTargetDependency section */ 462 | 463 | /* Begin PBXVariantGroup section */ 464 | FB3F00E418C7016200173598 /* InfoPlist.strings */ = { 465 | isa = PBXVariantGroup; 466 | children = ( 467 | FB3F00E518C7016200173598 /* en */, 468 | ); 469 | name = InfoPlist.strings; 470 | sourceTree = ""; 471 | }; 472 | FB3F010118C7016200173598 /* InfoPlist.strings */ = { 473 | isa = PBXVariantGroup; 474 | children = ( 475 | FB3F010218C7016200173598 /* en */, 476 | ); 477 | name = InfoPlist.strings; 478 | sourceTree = ""; 479 | }; 480 | /* End PBXVariantGroup section */ 481 | 482 | /* Begin XCBuildConfiguration section */ 483 | FB3F010618C7016200173598 /* Debug */ = { 484 | isa = XCBuildConfiguration; 485 | buildSettings = { 486 | ALWAYS_SEARCH_USER_PATHS = NO; 487 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 488 | CLANG_CXX_LIBRARY = "libc++"; 489 | CLANG_ENABLE_MODULES = YES; 490 | CLANG_ENABLE_OBJC_ARC = YES; 491 | CLANG_WARN_BOOL_CONVERSION = YES; 492 | CLANG_WARN_CONSTANT_CONVERSION = YES; 493 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 494 | CLANG_WARN_EMPTY_BODY = YES; 495 | CLANG_WARN_ENUM_CONVERSION = YES; 496 | CLANG_WARN_INT_CONVERSION = YES; 497 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 498 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 499 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 500 | COPY_PHASE_STRIP = NO; 501 | GCC_C_LANGUAGE_STANDARD = gnu99; 502 | GCC_DYNAMIC_NO_PIC = NO; 503 | GCC_OPTIMIZATION_LEVEL = 0; 504 | GCC_PREPROCESSOR_DEFINITIONS = ( 505 | "DEBUG=1", 506 | "$(inherited)", 507 | ); 508 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 509 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 510 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 511 | GCC_WARN_UNDECLARED_SELECTOR = YES; 512 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 513 | GCC_WARN_UNUSED_FUNCTION = YES; 514 | GCC_WARN_UNUSED_VARIABLE = YES; 515 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 516 | ONLY_ACTIVE_ARCH = YES; 517 | SDKROOT = iphoneos; 518 | }; 519 | name = Debug; 520 | }; 521 | FB3F010718C7016200173598 /* Release */ = { 522 | isa = XCBuildConfiguration; 523 | buildSettings = { 524 | ALWAYS_SEARCH_USER_PATHS = NO; 525 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 526 | CLANG_CXX_LIBRARY = "libc++"; 527 | CLANG_ENABLE_MODULES = YES; 528 | CLANG_ENABLE_OBJC_ARC = YES; 529 | CLANG_WARN_BOOL_CONVERSION = YES; 530 | CLANG_WARN_CONSTANT_CONVERSION = YES; 531 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 532 | CLANG_WARN_EMPTY_BODY = YES; 533 | CLANG_WARN_ENUM_CONVERSION = YES; 534 | CLANG_WARN_INT_CONVERSION = YES; 535 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 536 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 537 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 538 | COPY_PHASE_STRIP = YES; 539 | ENABLE_NS_ASSERTIONS = NO; 540 | GCC_C_LANGUAGE_STANDARD = gnu99; 541 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 542 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 543 | GCC_WARN_UNDECLARED_SELECTOR = YES; 544 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 545 | GCC_WARN_UNUSED_FUNCTION = YES; 546 | GCC_WARN_UNUSED_VARIABLE = YES; 547 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 548 | SDKROOT = iphoneos; 549 | VALIDATE_PRODUCT = YES; 550 | }; 551 | name = Release; 552 | }; 553 | FB3F010918C7016200173598 /* Debug */ = { 554 | isa = XCBuildConfiguration; 555 | baseConfigurationReference = 268C6853C490B04D8D505AD7 /* Pods.debug.xcconfig */; 556 | buildSettings = { 557 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 558 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 559 | CODE_SIGN_ENTITLEMENTS = "Microsoft Tasks/Microsoft Tasks.entitlements"; 560 | CODE_SIGN_IDENTITY = "iPhone Developer"; 561 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 562 | FRAMEWORK_SEARCH_PATHS = ( 563 | "$(inherited)", 564 | "$(PROJECT_DIR)", 565 | ); 566 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 567 | GCC_PREFIX_HEADER = "Microsoft Tasks/Microsoft Tasks-Prefix.pch"; 568 | INFOPLIST_FILE = "Microsoft Tasks/Microsoft Tasks-Info.plist"; 569 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 570 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 571 | OTHER_LDFLAGS = "$(inherited)"; 572 | PRODUCT_NAME = "$(TARGET_NAME)"; 573 | PROVISIONING_PROFILE = ""; 574 | TARGETED_DEVICE_FAMILY = 1; 575 | WRAPPER_EXTENSION = app; 576 | }; 577 | name = Debug; 578 | }; 579 | FB3F010A18C7016200173598 /* Release */ = { 580 | isa = XCBuildConfiguration; 581 | baseConfigurationReference = 32C2DA3BB2D20EAD1E82DBA0 /* Pods.release.xcconfig */; 582 | buildSettings = { 583 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 584 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 585 | CODE_SIGN_ENTITLEMENTS = "Microsoft Tasks/Microsoft Tasks.entitlements"; 586 | CODE_SIGN_IDENTITY = "iPhone Developer"; 587 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 588 | FRAMEWORK_SEARCH_PATHS = ( 589 | "$(inherited)", 590 | "$(PROJECT_DIR)", 591 | ); 592 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 593 | GCC_PREFIX_HEADER = "Microsoft Tasks/Microsoft Tasks-Prefix.pch"; 594 | INFOPLIST_FILE = "Microsoft Tasks/Microsoft Tasks-Info.plist"; 595 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 596 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 597 | OTHER_LDFLAGS = "$(inherited)"; 598 | PRODUCT_NAME = "$(TARGET_NAME)"; 599 | PROVISIONING_PROFILE = ""; 600 | TARGETED_DEVICE_FAMILY = 1; 601 | WRAPPER_EXTENSION = app; 602 | }; 603 | name = Release; 604 | }; 605 | FB3F010C18C7016200173598 /* Debug */ = { 606 | isa = XCBuildConfiguration; 607 | baseConfigurationReference = 268C6853C490B04D8D505AD7 /* Pods.debug.xcconfig */; 608 | buildSettings = { 609 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Microsoft Tasks.app/Microsoft Tasks"; 610 | FRAMEWORK_SEARCH_PATHS = ( 611 | "$(SDKROOT)/Developer/Library/Frameworks", 612 | "$(inherited)", 613 | "$(DEVELOPER_FRAMEWORKS_DIR)", 614 | ); 615 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 616 | GCC_PREFIX_HEADER = "Microsoft Tasks/Microsoft Tasks-Prefix.pch"; 617 | GCC_PREPROCESSOR_DEFINITIONS = ( 618 | "DEBUG=1", 619 | "$(inherited)", 620 | ); 621 | INFOPLIST_FILE = "Microsoft TasksTests/Microsoft TasksTests-Info.plist"; 622 | PRODUCT_NAME = "$(TARGET_NAME)"; 623 | TEST_HOST = "$(BUNDLE_LOADER)"; 624 | WRAPPER_EXTENSION = xctest; 625 | }; 626 | name = Debug; 627 | }; 628 | FB3F010D18C7016200173598 /* Release */ = { 629 | isa = XCBuildConfiguration; 630 | baseConfigurationReference = 32C2DA3BB2D20EAD1E82DBA0 /* Pods.release.xcconfig */; 631 | buildSettings = { 632 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Microsoft Tasks.app/Microsoft Tasks"; 633 | FRAMEWORK_SEARCH_PATHS = ( 634 | "$(SDKROOT)/Developer/Library/Frameworks", 635 | "$(inherited)", 636 | "$(DEVELOPER_FRAMEWORKS_DIR)", 637 | ); 638 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 639 | GCC_PREFIX_HEADER = "Microsoft Tasks/Microsoft Tasks-Prefix.pch"; 640 | INFOPLIST_FILE = "Microsoft TasksTests/Microsoft TasksTests-Info.plist"; 641 | PRODUCT_NAME = "$(TARGET_NAME)"; 642 | TEST_HOST = "$(BUNDLE_LOADER)"; 643 | WRAPPER_EXTENSION = xctest; 644 | }; 645 | name = Release; 646 | }; 647 | /* End XCBuildConfiguration section */ 648 | 649 | /* Begin XCConfigurationList section */ 650 | FB3F00D118C7016200173598 /* Build configuration list for PBXProject "Microsoft Tasks" */ = { 651 | isa = XCConfigurationList; 652 | buildConfigurations = ( 653 | FB3F010618C7016200173598 /* Debug */, 654 | FB3F010718C7016200173598 /* Release */, 655 | ); 656 | defaultConfigurationIsVisible = 0; 657 | defaultConfigurationName = Release; 658 | }; 659 | FB3F010818C7016200173598 /* Build configuration list for PBXNativeTarget "Microsoft Tasks" */ = { 660 | isa = XCConfigurationList; 661 | buildConfigurations = ( 662 | FB3F010918C7016200173598 /* Debug */, 663 | FB3F010A18C7016200173598 /* Release */, 664 | ); 665 | defaultConfigurationIsVisible = 0; 666 | defaultConfigurationName = Release; 667 | }; 668 | FB3F010B18C7016200173598 /* Build configuration list for PBXNativeTarget "Microsoft TasksTests" */ = { 669 | isa = XCConfigurationList; 670 | buildConfigurations = ( 671 | FB3F010C18C7016200173598 /* Debug */, 672 | FB3F010D18C7016200173598 /* Release */, 673 | ); 674 | defaultConfigurationIsVisible = 0; 675 | defaultConfigurationName = Release; 676 | }; 677 | /* End XCConfigurationList section */ 678 | 679 | /* Begin XCVersionGroup section */ 680 | FB3F00ED18C7016200173598 /* Microsoft_Tasks.xcdatamodeld */ = { 681 | isa = XCVersionGroup; 682 | children = ( 683 | FB3F00EE18C7016200173598 /* Microsoft_Tasks.xcdatamodel */, 684 | ); 685 | currentVersion = FB3F00EE18C7016200173598 /* Microsoft_Tasks.xcdatamodel */; 686 | path = Microsoft_Tasks.xcdatamodeld; 687 | sourceTree = ""; 688 | versionGroupType = wrapper.xcdatamodel; 689 | }; 690 | /* End XCVersionGroup section */ 691 | }; 692 | rootObject = FB3F00CE18C7016200173598 /* Project object */; 693 | } 694 | --------------------------------------------------------------------------------