Introduction to AzureGraph

Hong Ooi

Microsoft Graph is a comprehensive framework for accessing data in various online Microsoft services, including Azure Active Directory (AAD), Office 365, OneDrive, Teams, and more. AzureGraph is a simple R6-based interface to the Graph REST API, and is the companion package to AzureRMR and AzureAuth.

Currently, AzureGraph aims to provide an R interface only to the AAD part, with a view to supporting R interoperability with Azure: registered apps and service principals, users and groups. Like AzureRMR, it could potentially be extended to support other services.

Authentication

AzureGraph uses a similar authentication procedure to AzureRMR and the Azure CLI. The first time you authenticate with a given Azure Active Directory tenant, you call create_graph_login() and supply your credentials. AzureGraph will prompt you for permission to create a special data directory in which to cache the obtained authentication token and AD Graph login. Once this information is saved on your machine, it can be retrieved in subsequent R sessions with get_graph_login(). Your credentials will be automatically refreshed so you don’t have to reauthenticate.

library(AzureGraph)

# authenticate with AAD
# - on first login, call create_graph_login()
# - on subsequent logins, call get_graph_login()
gr <- create_graph_login()

Linux DSVM note If you are using a Linux Data Science Virtual Machine in Azure, you may have problems running create_graph_login() (ie, without arguments). In this case, try create_graph_login(auth_type="device_code").

Users and groups

The basic classes for interacting with user accounts and groups are az_user and az_group. To instantiate these, call the get_user and get_group methods of the login client object.

# account of the logged-in user (if you authenticated via the default method)
me <- gr$get_user()

# alternative: supply an email address or GUID
me2 <- gr$get_user("hongooi@microsoft.com")

# IDs of my groups
head(me$list_group_memberships)
#> [1] "98326d14-365a-4257-b0f1-5c3ce3104f75" "b21e5600-8ac5-407b-8774-396168150210"
#> [3] "be42ef66-5c13-48cb-be5c-21e563e333ed" "dd58be5a-1eac-47bd-ab78-08a452a08ea0"
#> [5] "4c2bfcfe-5012-4136-ab33-f10389f2075c" "a45fbdbe-c365-4478-9366-f6f517027a22"

# a specific group
(grp <- gr$get_group("82d27e38-026b-4e5d-ba1a-a0f5a21a2e85"))
#> <Graph group 'AIlyCATs'>
#>   directory id: 82d27e38-026b-4e5d-ba1a-a0f5a21a2e85
#>   description: ADS AP on Microsoft Teams.
#> - Instant communication.
#> - Share files/links/codes/...
#> - Have fun. :)

The actual properties of an object are stored as a list in the properties field:

# properties of a user account
names(me$properties)
#>  [1] "@odata.context"                 "id"                             "deletedDateTime"
#>  [4] "accountEnabled"                 "ageGroup"                       "businessPhones"
#>  [7] "city"                           "createdDateTime"                "companyName"
#> [10] "consentProvidedForMinor"        "country"                        "department"
#> [13] "displayName"                    "employeeId"                     "faxNumber"
#> ...

me$properties$companyName
#> [1] "MICROSOFT PTY LIMITED"

# properties of a group
names(grp$properties)
#>  [1] "@odata.context"                "id"                            "deletedDateTime"
#>  [4] "classification"                "createdDateTime"               "description"
#>  [7] "displayName"                   "expirationDateTime"            "groupTypes"
#> [10] "mail"                          "mailEnabled"                   "mailNickname"
#> [13] "membershipRule"                "membershipRuleProcessingState" "onPremisesLastSyncDateTime"
#> ...

You can also view any directory objects that you own and/or created, via the list_owned_objects and list_registered_objects methods of the user object. These accept a type argument to filter the list of objects by the specified type(s).

me$list_owned_objects(type="application")
#> [[1]]
#> <Graph registered app 'AzureRapp'>
#>   app id: 5af7bc65-8834-4ee6-90df-e7271a12cc62
#>   directory id: 132ce21b-ebb9-4e75-aa04-ad9155bb921f
#>   domain: microsoft.onmicrosoft.com

me$list_owned_objects(type="group")
#> [[1]]
#> <Graph group 'AIlyCATs'>
#>   directory id: 82d27e38-026b-4e5d-ba1a-a0f5a21a2e85
#>   description: ADS AP on Microsoft Teams.
#> - Instant communication.
#> - Share files/links/codes/...
#> - Have fun. :)
#>
#> [[2]] 
#> <Graph group 'ANZ Data Science and AI V-Team'>
#>   directory id: 4e237eed-5f9b-4abd-830b-9322cb472b66
#>   description: ANZ Data Science V-Team
#>
#> ...

Registered apps and service principals

To get the details for a registered app, use the get_app or create_app methods of the login client object. These return an object of class az_app. The first method retrieves an existing app, while the second creates a new app.

# an existing app
gr$get_app("5af7bc65-8834-4ee6-90df-e7271a12cc62")
#> <Graph registered app 'AzureRapp'>
#>   app id: 5af7bc65-8834-4ee6-90df-e7271a12cc62
#>   directory id: 132ce21b-ebb9-4e75-aa04-ad9155bb921f
#>   domain: microsoft.onmicrosoft.com

# create a new app
(appnew <- gr$create_app("AzureRnewapp"))
#> <Graph registered app 'AzureRnewapp'>
#>   app id: 1751d755-71b1-40e7-9f81-526d636c1029
#>   directory id: be11df41-d9f1-45a0-b460-58a30daaf8a9
#>   domain: microsoft.onmicrosoft.com

By default, creating a new app will also generate a strong password with a duration of two years, and create a corresponding service principal in your AAD tenant. You can retrieve this with the get_service_principal method, which returns an object of class az_service_principal.

appnew$get_service_principal()
#> <Graph service principal 'AzureRnewapp'>
#>   app id: 1751d755-71b1-40e7-9f81-526d636c1029
#>   directory id: 7dcc9602-2325-4912-a32e-03e262ffd240
#>   app tenant: 72f988bf-86f1-41af-91ab-2d7cd011db47

# or directly from the login client (supply the app ID in this case)
gr$get_service_principal("1751d755-71b1-40e7-9f81-526d636c1029")
#> <Graph service principal 'AzureRnewapp'>
#>   app id: 1751d755-71b1-40e7-9f81-526d636c1029
#>   directory id: 7dcc9602-2325-4912-a32e-03e262ffd240
#>   app tenant: 72f988bf-86f1-41af-91ab-2d7cd011db47

To update an app, call its update method. For example, use this to set a redirect URL or change its permissions. Consult the Microsoft Graph documentation for what properties you can update.

#' # set a public redirect URL
newapp$update(publicClient=list(redirectUris=I("http://localhost:1410")))

One app property you cannot change with update is its password. As a security measure, app passwords are auto-generated on the server, rather than being specified manually. To manage an app’s password, call the add_password and remove_password methods.

#' # add a password
newapp$add_password()

#' remove a password
pwd_id <- newapp$properties$passwordCredentials[[1]]$keyId
newapp$remove_password(pwd_id)

Similarly, to manage an app’s certificate for authentication, call the add_certificate and remove_certificate methods.

#' add a certificate:
#' can be specified as a filename, openssl::cert object, AzureKeyVault::stored_cert object,
#' or raw or character vector
newapp$add_certificate("cert.pem")

#' remove a certificate
cert_id <- newapp$properties$keyCredentials[[1]]$keyId
newapp$remove_certificate(cert_id)

Common methods

The classes described above inherit from a base az_object class, which represents an arbitrary object in Azure Active Directory. This has the following methods:

For efficiency the list_group_memberships and list_object_memberships methods return only the IDs of the groups/objects, since these lists can be rather long.

# get my OneDrive
me$do_operation("drive")

See also

See the following links on Microsoft Docs for more information.