Populating School Timetable at Once Using Graph API

Populating School Timetable at Once Using Graph API

There are total four steps involve in populating timetable using Graph API

  • 1-      Application Registration
  • 2-      Configuring Application permission
  • 3-      Authentication and Authorization
  • 4-      Schedule Timetable

Application Registration

The first step to connect to Graph and make requests is to register a new Azure Active Directory Application. The application is used to connect to Graph and manage permissions.

Navigate to App Registrations in Azure and select “New Registration” (Azure Portal > Azure Active Directory > App Registration > New Application Registration)

Creating a new Azure Active Directory Application in the Azure Portal

Next, give your application a name. In my example, I am naming my application, “Education-Graph”. Then, specify who can use this application. Click on the “Register” button to create your new application.

Giving the Application a valid name and scope

You will now see your newly created application. Some key items regarding the application are the Application ID (which is the Client ID), the Directory ID (which is the Tenant ID) and Client Secret, which is required if you use the Application Permission type but not if you use the Delegated Permission Type.

And finally, we need to configure and get our applications redirect URI. Go to your Azure Applications Overview page by going to Azure Active Directory > App Registrations. Click on “Add a Redirect URI”

Enter in ANY URI as a redirect URI value. It DOES NOT have to even resolve! You could put http://localhost, in my example I put a URL that isn’t even valid on my website. Press ‘Save’ and take note of this URL.

Configuring App Permissions

Now that we have created an Application, we need to configure its permissions. When Apps try to access information, they must have the appropriate permissions to do.

Application Permissions vs Delegated Permissions

It is important to understand the difference between Application permissions and Delegated permissions as well as effective permissions. Effective permissions are the permissions that your app will have when making requests to the Graph API.

Application permissions are used by apps that run without a signed-in user present; for example, apps that run as background services or daemons. Application permissions can only be consented by an administrator. This permission type would be preferred for items like automated scripts and runbooks.

For application permissions, the effective permissions of your app will be the full level of privileges implied by the permission. For example, an app that has the User.ReadWrite.All application permission can update the profile of every user in the organization.

Delegated permissions are used by apps that have a signed-in user present. For these apps, either the user or an administrator consents to the permissions that the app requests and the app is delegated permission to act as the signed-in user when making calls to the target resource. Some delegated permissions can be consented to by non-administrative users, but some higher-privileged permissions require administrator consent.

For delegated permissions, the effective permissions of your app will be the least privileged intersection of the delegated permissions the app has been granted and the privileges of the currently signed-in user. Your app can never have more privileges than the signed-in user. Within organizations, the privileges of the signed-in user may be determined by policy or by membership in one or more administrator roles. For example, assume your app has been granted the User.ReadWrite.All delegated permission. This permission nominally grants your app permission to read and update the profile of every user in an organization. If the signed-in user is a global administrator, your app will be able to update the profile of every user in the organization. However, if the signed-in user isn’t in an administrator role, your app will be able to update only the profile of the signed-in user. It will not be able to update the profiles of other users in the organization because the user that it has permission to act on behalf of does not have those privileges.

Permission Requirements

The Microsoft Graph documentation provides details on which permission levels are required or allowed for each permission type (application vs delegated). Some resources can only be reached using Delegated Permissions, others by Application permissions, and others by either of the two. Pictured below we can see the permissions listed to retrieve a list of all user objects for Application or Delegated. Permissions are listed from least privileged to most privileged.

Assigning Permissions

You can assign your application different permissions in the Azure Portal. First navigate to Azure Portal > Azure Active Directory >App Registrations and then select your application that you made above. Once you have selected your application, select “API Permissions” or “View API Permissions”

In my example I will give my application permission to return all groups that are in my tenant, Create event etc.

To assign a new permission to your application, click the “Add a permission” button.

In the “Request API Permissions” blade “Microsoft Graph”

Next, we will have to choose the permission type. Remember that some permissions are only available for application permission type, some for delegated permission type, and some are available for both types. If, for example, I wanted to be able to List All Groups in my organization, I can see in the Graph API Documentation that I can use either delegated permissions or application permissions. So now it all depends how I will use my Azure Application. In my example I will be selecting Application Permissions.

But since this permission type grants access to protected resources, I need to grant Admin Consent. 

And now I see that my permissions have been granted and my application can now read all groups in my organization as well as read all user’s profiles, calendar etc.

Authentication and Authorization

There are multiple ways to authenticate and authorize, we will be using device code for this

Device Code

Important – You need to set allowPublicClient to True in the applications Manifest. Otherwise you will see a similar error to:

“error_description”:”AADSTS7000218: The request body must contain the following parameter: ‘client_assertion’ or ‘client_secret’

For Device Code flow you do not need to know your Azure Applications client secret, but you do need to provide the client ID, and tenant name.

The first item we need to get is the Tenant Name. This can be found in Azure by going to Azure Active Directory > Custom Domain Names, and then finding the .onmicrosoft.com domain.

Second, we want to find the Client ID of our Azure Application that we created earlier. To find this go to Azure and then Azure Active Directory > App Registrations > select your application and then copy the Application (client) ID value:

Now in the below code replace your Client ID and Tenant Name which you got in previous steps and run the code in PowerShell

$clientId = "36433296-767e-4c39-------"

$redirectUrl = [System.Uri]"urn:ietf:wg:oauth:2.0:oob" # This is the standard Redirect URI for Windows Azure PowerShell

$tenant = "M36534568321.onmicrosoft.com"

$resource = "https://graph.microsoft.com/";

$serviceRootURL = "https://graph.microsoft.com//$tenant"

$authUrl = "https://login.microsoftonline.com/$tenant";

$postParams = @{ resource = "$resource"; client_id = "$clientId" }

$response = Invoke-RestMethod -Method POST -Uri "$authurl/oauth2/devicecode" -Body $postParams

Write-Host $response.message

#I got tired of manually copying the code, so I did string manipulation and stored the code in a variable and added to the clipboard automatically

$code = ($response.message -split "code " | Select-Object -Last 1) -split " to authenticate."

Set-Clipboard -Value $code

#Start-Process "https://microsoft.com/devicelogin"

Add-Type -AssemblyName System.Windows.Forms

$form = New-Object -TypeName System.Windows.Forms.Form -Property @{ Width = 440; Height = 640 }

$web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{ Width = 440; Height = 600; Url = "https://www.microsoft.com/devicelogin" }

$web.Add_DocumentCompleted($DocComp)

$web.DocumentText

$form.Controls.Add($web)

$form.Add_Shown({ $form.Activate() })

$web.ScriptErrorsSuppressed = $true

$form.AutoScaleMode = 'Dpi'

$form.text = "Graph API Authentication"

$form.ShowIcon = $False

$form.AutoSizeMode = 'GrowAndShrink'

$Form.StartPosition = 'CenterScreen'

$form.ShowDialog() | Out-Null

$tokenParams = @{ grant_type = "device_code"; resource = "$resource"; client_id = "$clientId"; code = "$($response.device_code)" }

$tokenResponse = $null

try

{

                $tokenResponse = Invoke-RestMethod -Method POST -Uri "$authurl/oauth2/token" -Body $tokenParams

}

catch [System.Net.WebException]

{

                if ($_.Exception.Response -eq $null)

                {

                                throw

                }

               

                $result = $_.Exception.Response.GetResponseStream()

                $reader = New-Object System.IO.StreamReader($result)

                $reader.BaseStream.Position = 0

                $errBody = ConvertFrom-Json $reader.ReadToEnd();

               

                if ($errBody.Error -ne "authorization_pending")

                {

                                throw

                }

}

If ($null -eq $tokenResponse)

{

                Write-Warning "Not Connected"

}

Else

{

                Write-Host -ForegroundColor Green "Connected"

}

Now if I run the script within PowerShell, the shell will display my device code and a winform to enter the code and sign in

After you sign in you will be greeted with a message saying you have signed into the application and you can close the window.

Now you are connected to the GraphAPI.

Schedule Timetable

In our case we are Scheduling timetable using an csv file. We need to put as much information as possible in that excel sheet.

See the below SS for clarification

Location: What’s the location of the class physically.

UPN: Teams’s email where the meeting held online.

Subject: Subject of the Team Meeting

STime: Start time of the meeting

ETime: End time of the meeting

Content: Description of the teams meeting

Day: If the class is recursive, we need to mention the day.

Teacher: Email address of the organizer

After creating this excel sheet, we can use the code below to schedule all the classes

Import-Csv -Path "C:\Users\Awais\OneDrive - Communication Square\Desktop\GraphAPICS.csv" | foreach { $apiUrl = "https://graph.microsoft.com/v1.0/me/events"

  $bodyy = @"

  {

    "subject": "$($_.Subject)",

    "body": {

      "contentType": "HTML",

      "content": "$($_.Content)"

    },

    "start": {

        "dateTime": "$($_.STime)",

        "timeZone": "Pakistan Standard Time"

    },

    "end": {

        "dateTime": "$($_.Etime)",

        "timeZone": "Pakistan Standard Time"

    },

    "location":{

        "displayName": "$($_.Location)"

    },

   "recurrence": {

     "pattern": {

       "type": "weekly",

       "interval": 1,

       "daysOfWeek": [ "$($_.Day)" ]

     },

     "range": {

       "type": "endDate",

       "startDate": "2020-08-14",

       "endDate": "2020-12-31"

     }

   },

 "attendees": [

      {

        "emailAddress": {

          "address": "$($_.UPN)"

        },

        "type": "required"

      },

      {

        "emailAddress": {

          "address": "$($_.Teacher)"

        }

      }

    ],

    "allowNewTimeProposals": true,

    "isOnlineMeeting": true,

    "onlineMeetingProvider": "teamsForBusiness"

  }

"@

$DataPOST = Invoke-RestMethod -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $apiUrl -Method POST -Body $bodyy  -ContentType 'application/json'}}

In case of using recursive meeting please define range in above code.

After running this code all the meeting will be scheduled in the specific Teams. 

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.