iOS验证Azure Active Directory&从office 365交换获取日历事件

时间:2014-12-01 16:40:22

标签: ios azure exchangewebservices azure-mobile-services

尝试使用Azure Active Directory进行身份验证并获取邮件,日历数据,accessToken成功返回:

authority = @"https://login.windows.net/common/oauth2/authorize";
redirectUriString = @"http://xxxxxx.xxxxxxx.com/oauth";
resourceId = @"https://outlook.office365.com";
clientId = @"xxxxxxx-xxxxx-xxx";

-(void) getToken : (BOOL) clearCache completionHandler:(void (^) (NSString*))completionBlock;
{
ADAuthenticationError *error;
authContext = [ADAuthenticationContext authenticationContextWithAuthority:authority
                                                                    error:&error];
[authContext setValidateAuthority:YES];

NSURL *redirectUri = [NSURL URLWithString:redirectUriString];

if(clearCache){
    [authContext.tokenCacheStore removeAllWithError:&error];

    if (error) {
        NSLog(@"Error: %@", error);
    }
}


[authContext acquireTokenWithResource:resourceId
                             clientId:clientId
                          redirectUri:redirectUri
                      completionBlock:^(ADAuthenticationResult *result) {
                          if (AD_SUCCEEDED != result.status){
                              // display error on the screen
                              [self showError:result.error.errorDetails];
                          }
                          else{
                              completionBlock(result.accessToken);
                          }
                      }];

}

- (NSArray的*)getEventsList {

__block NSMutableArray * todoList;

[self getToken:YES completionHandler:^(NSString* accessToken){

    NSURL *todoRestApiURL = [[NSURL alloc]initWithString:@"https://outlook.office365.com/api/v1.0/me/folders/inbox/messages?$top=2"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:todoRestApiURL];

    NSString *authHeader = [NSString stringWithFormat:@"Bearer %@", @""];

    [request addValue:authHeader forHTTPHeaderField:@"Authorization"];

    [request addValue:@"application/json; odata.metadata=none" forHTTPHeaderField:@"accept"];


    [request addValue:@"fbbadfe-9211-1234-9654-fe435986a1d6" forHTTPHeaderField:@"client-request-id"];

    [request addValue:@"Presence-Propelics/1.0" forHTTPHeaderField:@"User-Agent"];
    //[request addValue:@"true" forHTTPHeaderField:@"return-client-request-id"];



    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

        if (error == nil){

            NSArray *scenarios = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

            todoList = [[NSMutableArray alloc]initWithArray:scenarios];

            //each object is a key value pair
            NSDictionary *keyVauePairs;

            for(int i =0; i < todoList.count; i++)
            {
                keyVauePairs = [todoList objectAtIndex:i];

                NSLog(@"%@", keyVauePairs);

            }

        }
        NSLog(@"Finished");
        //[delegate updateTodoList:TodoList];

    }];

}];
return nil; }

在响应对象中返回错误:

{     error = {         code = ErrorAccessDenied;         message =“访问被拒绝。检查凭据,然后重试。”;     }; }

2 个答案:

答案 0 :(得分:1)

我知道很晚才回答这个问题,但对于像我这样努力完成同样事情的人来说可能会有所帮助

我使用适用于iOS的office 365 SDK来完成此操作,其中包含所有内置类来完成您的工作。

如果您下载示例代码,它将为您提供执行某些操作所需的所有详细信息(邮件,日历,联系人,一个驱动器)。

在使用SDK之前,请确保您登录Azure AD和register your application and add permissions,这样就不会收到403错误代码或任何拒绝访问的消息。

我使用以下代码从Outlook日历中获取我的活动详情

    [self getClientEvents:^(MSOutlookClient *client) {
        NSURLSessionDataTask *task = [[[client getMe] getEvents] read:^(NSArray<MSOutlookEvent> *events, MSODataException *error) {

            if (error==nil) {
                if (events.count!=0) {

                    dispatch_async(dispatch_get_main_queue(), ^{
                        for(MSOutlookEvent *calendarEvent in events){
                            NSLog(@"name = %@",calendarEvent.Subject);
                        }
                    });
                }else{
                    NSLog(@"No events found for today");
                }
            }
        }];
        [task resume];
    }];

getClientEvents 是一种方法,可以调用Office 365 SDK并获取用户的事件详细信息,但它首先获取资源的令牌,然后使用获取的令牌进行调用

-(void)getClientEvents : (void (^) (MSOutlookClient* ))callback{

[self getTokenWith : @"https://outlook.office365.com" :true completionHandler:^(NSString *token) {

    MSODataDefaultDependencyResolver* resolver = [MSODataDefaultDependencyResolver alloc];
    MSODataOAuthCredentials* credentials = [MSODataOAuthCredentials alloc];
    [credentials addToken:token];

    MSODataCredentialsImpl* credentialsImpl = [MSODataCredentialsImpl alloc];

    [credentialsImpl setCredentials:credentials];
    [resolver setCredentialsFactory:credentialsImpl];
    [[resolver getLogger] log:@"Going to call client API" :(MSODataLogLevel *)INFO];

    callback([[MSOutlookClient alloc] initWithUrl:@"https://outlook.office365.com/api/v1.0" dependencyResolver:resolver]);
}];
}

getTokenWith方法首先获取资源的令牌,然后使用获取的令牌进行必要的调用以获取事件,但在获取令牌之前,它会检查缓存以查看是否有任何令牌可用于相同的资源。

// fetch tokens for resources
- (void) getTokenWith :(NSString *)resourceId : (BOOL) clearCache completionHandler:(void (^) (NSString *))completionBlock;
{
// first check if the token for the resource is present or not
if([self getCacheToken : resourceId completionHandler:completionBlock]) return;

ADAuthenticationError *error;
authContext = [ADAuthenticationContext authenticationContextWithAuthority:[[NSUserDefaults standardUserDefaults] objectForKey:@"authority"] error:&error];

NSURL *redirectUri = [NSURL URLWithString:@"YOUR_REDIRECT_URI"];

[authContext acquireTokenWithResource:resourceId
                             clientId:[[NSUserDefaults standardUserDefaults] objectForKey:@"clientID"]
                          redirectUri:redirectUri
                      completionBlock:^(ADAuthenticationResult  *result) {

                          if (AD_SUCCEEDED != result.status){
                              [self showError:result.error.errorDetails];
                          }
                          else{
                              NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
                              [userDefaults setObject:result.tokenCacheStoreItem.userInformation.userId forKey:@"LogInUser"];
                              [userDefaults synchronize];

                              completionBlock(result.accessToken);
                          }
                      }];
}

getCacheToken方法:检查是否有任何资源的可重用令牌。

-(BOOL)getCacheToken : (NSString *)resourceId  completionHandler:(void (^) (NSString *))completionBlock {
ADAuthenticationError * error;
id<ADTokenCacheStoring> cache = [ADAuthenticationSettings sharedInstance].defaultTokenCacheStore;
NSArray *array = [cache allItemsWithError:&error];

if([array count] == 0) return false;
ADTokenCacheStoreItem *cacheItem;

for (ADTokenCacheStoreItem *item in array) {
    if([item.resource isEqualToString:resourceId]){
        cacheItem = item;
        break;
    }
}

ADUserInformation *user = cacheItem.userInformation;

if(user == nil) return false;

if([cacheItem isExpired]){
    return [self refreshToken:resourceId completionHandler:completionBlock];
}
else
{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setObject:user.userId forKey:@"LogInUser"];
    [userDefaults synchronize];

    completionBlock(cacheItem.accessToken);

    return true;
}
}

使用此代码和Office 365 SDK,您可以获取特定用户的Outlook事件,然后确保您在Azure AD中拥有完整权限,否则您可能会收到0个事件作为响应。

请注意所有方法都来自SDK示例,除了第一种方法,以查看如何获取我建议下载exchange example from the github的事件。

答案 1 :(得分:0)

您还可以使用MSGraph SDK获取日历和事件:

检查此链接:配置过程相同,仅提取事件不同(查看用于获取事件的给定代码):

How to Fetch/Create calender by O365-iOS-Connect?

注意:上面的链接用于从Outlook获取日历,但此过程与此相同,但您应在身份验证后使用此代码并完成获取事件操作,如下所示:

    - (IBAction)getCalendarsEvents:(id)sender {


[NXOAuth2AuthenticationProvider setClientId:clientId
                                     scopes:@[@"https://graph.microsoft.com/Files.ReadWrite",
                                              @"https://graph.microsoft.com/Calendars.ReadWrite"]];
[[NXOAuth2AuthenticationProvider sharedAuthProvider] loginWithViewController:nil completion:^(NSError *error) {
    if (!error) {
        [MSGraphClient setAuthenticationProvider:[NXOAuth2AuthenticationProvider sharedAuthProvider]];
        self.client = [MSGraphClient client];

        // Authentication done

        [[[[_client me] events] request] getWithCompletion:^(MSCollection *response, MSGraphUserEventsCollectionRequest *nextRequest, NSError *error){

            NSArray *arr = response.value;
            MSGraphEvent *event = arr.firstObject;

            // Here you will getting outlook events

        }];

    }
}];

    }