iOS 客户端:我可以让用户登录到 Active Directory,但是如何访问 MS Graph API?

iOS client: I can have user sign into Active Directory, but how to access MS Graph API?

我正在开发需要从 MS Azure Active Directory 读取用户数据的 iOS 应用程序。

我已成功遵循 MS Azure 文档中有关 iOS 应用程序的一些示例,并成功调出他们的身份验证页面并让用户登录。我得到的是一些用户数据,形式为ADUserInformation object.

这是我的代码:

    NSString *authority = @"https://login.microsoftonline.com/a5960f61-0bf9-4bf6-96cd-98c61d30XXXX/federationmetadata/2007-06/federationmetadata.xml";

    NSString *resourceId    = @"74cd2559-0389-4871-9904-bc767d71XXXX"; // (server)

    NSString *clientId      = @"c8a956a7-84b7-4050-875c-896aab6bXXXX";   //ios-client (us)

    NSURL *redirectUri = [[NSURL alloc]initWithString:@"https://XXXXevents.azurewebsites.net/.auth/login/done"];

    ADAuthenticationError *error;

    ADAuthenticationContext * authContext = [ADAuthenticationContext authenticationContextWithAuthority:authority error:&error];

    //authContext.parentController = parent;

    [ADAuthenticationSettings sharedInstance].enableFullScreen = YES;

    [authContext acquireTokenWithResource:resourceId
                                 clientId:clientId
                              redirectUri:redirectUri
                          completionBlock:^(ADAuthenticationResult *result) {

          if (result.status != AD_SUCCEEDED) {
              NSLog(@"%@", result);
              return;
          }
          else {

              //save all of this information into core data

              NSDictionary * payload = @{@"access_token" : result.tokenCacheItem.accessToken};
              NSLog(@"%@", payload);

              //@"aad"
              //@"windowsazureactivedirectory"

              [[QSActivityService defaultService].client loginWithProvider:     @"aad"
                                                                     token:     payload
                                                                completion:     ^(MSUser * _Nullable user, NSError * _Nullable error) {

                                                                NSLog(@"loginWithProvider-------");
                  if(!error) {
                      NSLog(@"YAY! %s - user: %@ ", __FUNCTION__, user.userId);

                      ADUserInformation * temp = result.tokenCacheItem.userInformation;

                                           [[CoreDataStack defaultStack] updateUserDetailFamilyName:temp.allClaims[@"family_name"]
                                                                           version:temp.allClaims[@"ver"]
                                                                             email:temp.allClaims[@"email"]
                                                                               nbf:temp.allClaims[@"nbf"]
                                                                               exp:temp.allClaims[@"exp"]
                                                                         givenName:temp.allClaims[@"given_name"]
                                                                               idp:temp.allClaims[@"idp"]
                                                                            ipaddr:temp.allClaims[@"ipaddr"]
                                                                               iss:temp.allClaims[@"iss"]
                                                                               oid:temp.allClaims[@"oid"]
                                                                               typ:temp.allClaims[@"typ"]
                                                                               sub:temp.allClaims[@"sub"]
                                                                               amr:temp.allClaims[@"amr"]
                                                                               aud:temp.allClaims[@"aud"]
                                                                               alg:temp.allClaims[@"alg"]
                                                                               iat:temp.allClaims[@"iat"]
                                                                               tid:temp.allClaims[@"tid"]
                                                                              name:temp.allClaims[@"name"]
                                                                        uniqueName:temp.allClaims[@"unique_name"]];

    //other code, no problems here

MS 图API

但是,我想访问个人资料图片和所有其他数据。我读过 MS Graph API 提供了它,但我不确定我将如何以及在哪里放置令牌。

我是否使用来自 result.tokenCacheItem.accessToken 的令牌?如果是这样,在 header?或 body?

或者我只是按 graph.windows.com 两次。第一次拿到Authentication Token,第二次拿到数据?

我阅读了很多文档,其中 none 有效,因为我不断收到 Token Missing or Malformed 错误消息。

我的图表 API 代码如下所示:

-(void)getUsersUsingAccessToken:(NSDictionary*)token completion:(void (^)    (void))completion {

    NSString * tenant = @"a5960f61-0bf9-4bf6-96cd-98c61d306f12";

    NSString * accessToken = token[@"access_token"];

    NSString * urlString = [NSString stringWithFormat: @"https://graph.windows.net/%@/tenantDetails?api-version=1.6", tenant];

    NSString * httpVerb = @"POST";

    //build an info object and convert to json
    NSDictionary * bodyFormDict

    = [NSDictionary dictionaryWithObjectsAndKeys:
     @"client_credentials",                              @"grant_type",
     @"https://graph.windows.net",                       @"resource",
     @"c8a956a7-84b7-4050-875c-896aab6xxxx",            @"client_id",
     @"XLlZl69aUKiQTo4dpeiprItm+LYbDtpt6e9dn0bxxxx",    @"client_secret",
     nil];

    NSError *error = nil;

    //1st step
    NSData * jsonInputData = [NSJSONSerialization dataWithJSONObject:bodyFormDict
                                                             options:NSJSONWritingPrettyPrinted
                                                               error:&error];

    //2nd step
    NSString * httpBodyString = [[NSString alloc]
                                 initWithData:jsonInputData
                                 encoding:NSUTF8StringEncoding];


    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    sessionConfiguration.allowsCellularAccess = YES;

    self.session = [NSURLSession sessionWithConfiguration:sessionConfiguration];

    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
    request.HTTPMethod = httpVerb;

    [request setValue:  @"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request setValue:  accessToken forHTTPHeaderField:@"Authorization: Bearer"];

    [request setHTTPBody:[httpBodyString dataUsingEncoding:NSUTF8StringEncoding]];

    //asynchronous
    NSURLSessionDataTask * getDataTask = [self.session dataTaskWithRequest:request
                                                         completionHandler:^(NSData * _Nullable data,
                                                                             NSURLResponse * _Nullable response,
                                                                             NSError * _Nullable error) {

    //other code

}

如果有人可以提供使用 objective c 成功从 MS Graph API 检索数据的工作代码示例,那将是一个很大的帮助。

感谢您的宝贵时间!

我认为您遇到的问题是 http header 字段设置不正确。试试这个 -

    NSString *authValue = [NSString stringWithFormat:@"Bearer %@", accessToken];
    [request setValue:authValue forHTTPHeaderField:@"Authorization"];

我在 MS MSDN 的入门项目和代码示例中找到了答案

https://msdn.microsoft.com/en-us/office/office365/howto/starter-projects-and-code-samples

对我有帮助的具体项目是这样的: https://github.com/OfficeDev/O365-iOS-Microsoft-Graph-Profile

在浏览该示例时请记住:

替换 INSERT-AUTHORITY-HERE - 您在其中配置应用程序的租户的名称。格式应为 https://login.windows.net/(YourAzureUserName).onmicrosoft.com

我发现 https://login.microsoftonline.com/YourAzureAccountID/federationmetadata/2007-06/federationmetadata.xml

也有效

替换 INSERT-RESOURCE-ID-HERE - 您的移动应用后端的 ID。这是 Web API 服务应用程序 ID。不是本机客户端 iOS 应用程序。

替换 INSERT-CLIENT-ID-HERE - 您从 iOS NATIVE 客户端应用程序复制的客户端 ID。不是 Web API 服务应用程序。

使用 HTTPS 方案替换 INSERT-REDIRECT-URI-HERE - 您网站的 /.auth/login/done 端点。这个值应该类似于 @"https://XXXXXXXXXX.azurewebsites.net/.auth/login/done"

如果您在导入 ADAL 框架时遇到问题...

http://shanghaiseagull.com/index.php/2016/05/11/import-another-project-framework-into-your-project/

库可以在这里找到:https://github.com/AzureAD/azure-activedirectory-library-for-objc

希望它能帮助刚起步的人...如果我能提供进一步的帮助,请告诉我。