I need to register the azure application on behalf of the user. I used the Azure Graph API to do the following:
- create an application with the required resources
- create a service principle for a registered application
- create an OAuth2PermissionGrant object for the service principal with the required areas
After that, I successfully acquired access_token for the created upp. But unfortunately, 401 Unauthorized was returned when I tried to access O365 resources using this token. Without any json'ed error!
HTTP / 1.1 401 Unauthorized use of Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Expires: -1
Server: Microsoft-IIS / 8.5
Server: Microsoft-IIS / 8.5
WWW Authentication: Media
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ASP.NET
Date: Thu, Dec 10 2015 11:58:59 GMT
... here it is!
Then I went to the Azure portal - everything was in order. After several experiments, I noticed that the access_token becomes valid after any changes through the portal (even cosmetic).
So, I compared tokens using a JWT decoder and found that Scopes were not included:
image - token BEFORE portal changes
image - token AFTER changes in the portal
I also noticed that the OAuth2PermissionGrant object was overwritten after the changes.
I used the following web resources and libraries:
- authorization library: ADAL
- library for accessing the graphical API: www.nuget.org/packages/Microsoft.Azure.ActiveDirectory.GraphClient
- A complete list of GraphClient examples can be found here github.com/Azure-Samples/active-directory-dotnet-graphapi-console/blob/master/GraphConsoleAppV3/Program.cs
Below I have attached the code that creates the application programmatically. I can also attach fiddler logs and other information.
ActiveDirectoryClient activeDirectoryClient; string clientSecret = "...hidden..."; string name = "O365 auto created client"; try { activeDirectoryClient = AuthenticationHelper.GetActiveDirectoryClientAsUser(); var appObject = new Application { DisplayName = "O365 auto created client", Homepage = "https://sign", LogoutUrl = "http://logout1.net" }; appObject.IdentifierUris.Add("https://localhost/demo/" + Guid.NewGuid()); appObject.ReplyUrls.Add("https://localhost/demo"); var officeAccess = new RequiredResourceAccess { ResourceAppId = "c5393580-f805-4401-95e8-94b7a6ef2fc2", // OfficeManagePlatform ResourceAccess = new List<ResourceAccess> { new ResourceAccess { Id = new Guid("825c9d21-ba03-4e97-8007-83f020ff8c0f"), Type = "Role,Scope" }, new ResourceAccess { Id = new Guid("e2cea78f-e743-4d8f-a16a-75b629a038ae"), Type = "Role,Scope" }, new ResourceAccess { Id = new Guid("594c1fb6-4f81-4475-ae41-0c394909246c"), Type = "Role,Scope" } } }; appObject.RequiredResourceAccess.Add(officeAccess); var passCreds = new PasswordCredential { StartDate = DateTime.UtcNow, EndDate = DateTime.UtcNow.AddYears(1), Value = clientSecret, KeyId = null, CustomKeyIdentifier = null }; appObject.PasswordCredentials.Add(passCreds); try { await activeDirectoryClient.Applications.AddApplicationAsync(appObject); } catch (Exception e) { Console.WriteLine("Application Creation exception: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : ""); } ServicePrincipal newServicePrincpal = new ServicePrincipal(); if (appObject!= null && appObject.AppId != null) { newServicePrincpal.DisplayName = appObject.DisplayName; newServicePrincpal.AccountEnabled = true; newServicePrincpal.AppId = appObject.AppId; newServicePrincpal.Tags.Add("WindowsAzureActiveDirectoryIntegratedApp"); try { activeDirectoryClient.ServicePrincipals.AddServicePrincipalAsync(newServicePrincpal).Wait(); Console.WriteLine("New Service Principal created: " + newServicePrincpal.ObjectId); } catch (Exception e) { Console.WriteLine("Service Principal Creation execption: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : ""); } } OAuth2PermissionGrant permissionObject = new OAuth2PermissionGrant(); permissionObject.ConsentType = "AllPrincipals"; permissionObject.Scope = "ServiceHealth.Read"; permissionObject.StartTime = DateTime.MinValue; permissionObject.ExpiryTime = (DateTime.Now).AddMonths(12); // resourceId is objectId of the resource manage.office.com // in this case objectId of AzureAd (Graph API) permissionObject.ResourceId = "52f62a75-b73d-496a-9bfa-1bf41339a90a"; // "52620afb-80de-4096-a826-95f4ad481686"; //ClientId = objectId of servicePrincipal permissionObject.ClientId = newServicePrincpal.ObjectId; try { activeDirectoryClient.Oauth2PermissionGrants.AddOAuth2PermissionGrantAsync(permissionObject).Wait(); Console.WriteLine("New Permission object created: " + permissionObject.ObjectId); } catch (Exception e) { Console.WriteLine("Permission Creation exception: {0} {1}", e.Message, e.InnerException != null ? e.InnerException.Message : ""); } return new ClientCredential(clientId: appObject.AppId, clientSecret: clientSecret); } catch (Exception ex) { return null; }