Microsoft Graph API

💡 Vad är Microsoft Graph?

Microsoft Graph är som nyckeln till hela Microsoft-universumet!

Tänk dig Microsoft Graph som en universalfernkontroll för allt Microsoft - Outlook, Teams, OneDrive, Azure AD, Office 365. Istället för att komma ihåg hundra olika API:er kan du använda EN Graph-query för att hämta allt.

🎯 TL;DR

Microsoft Graph = EN API för alla Microsoft-tjänster. Hämta emails, kalendrar, filer, användare, Teams-meddelanden - allt via samma endpoint med OAuth2-autentisering.

📋 Efter att ha läst detta kommer du att kunna

  • Förstå vad Microsoft Graph är och vad du kan göra med det
  • Registrera en app i Azure AD för Graph-åtkomst
  • Implementera OAuth2-autentisering för Graph
  • Hämta data från olika Microsoft-tjänster
  • Skapa och uppdatera data via Graph

🔧 Grundprinciper

Princip 1: En endpoint för allt

https://graph.microsoft.com/v1.0/ + vad du vill ha

Princip 2: OAuth2-säkerhet

Alla anrop kräver access tokens från Azure AD.

Princip 3: RESTful men enhetligt

Samma mönster för alla Microsoft-tjänster.

💭 Vad kan du hämta?

💬 Microsoft Graph ger dig åtkomst till:


ANVÄNDARE & GRUPPER:
/me                    - Din profil
/users                 - Alla användare
/groups                - Alla grupper

OUTLOOK & EMAIL:
/me/messages           - Dina emails
/me/calendar/events    - Din kalender
/me/contacts           - Dina kontakter

ONEDRIVE & FILER:
/me/drive/root/children - Dina filer
/sites                 - SharePoint-sajter

TEAMS & SAMARBETE:
/me/chats              - Teams-chattar
/teams                 - Teams du är med i
/me/presence           - Din status (online/offline)

OFFICE DOKUMENT:
/me/drive/items/{id}/workbook - Excel-filer

graph TB A[Microsoft Graph API] --> B[Azure AD] A --> C[Outlook/Exchange] A --> D[OneDrive/SharePoint] A --> E[Teams] A --> F[Office 365] B --> B1[Users] B --> B2[Groups] B --> B3[Applications] C --> C1[Mail] C --> C2[Calendar] C --> C3[Contacts] D --> D1[Files] D --> D2[Sites] D --> D3[Lists] E --> E1[Chats] E --> E2[Channels] E --> E3[Meetings]

🚀 Microsoft Graph i praktiken

🟢 Registrera app i Azure AD


1. Gå till https://portal.azure.com
2. Azure Active Directory → App registrations → New registration
3. Ge appen ett namn: "Min Graph App"
4. Supported account types: "Accounts in this organizational directory only"
5. Redirect URI: Web → https://localhost:5001/signin-oidc
6. Register

7. Anteckna:
   - Application (client) ID
   - Directory (tenant) ID

8. Certificates & secrets → New client secret
   - Anteckna Secret Value (visas bara en gång!)

9. API permissions → Add a permission → Microsoft Graph
   - Lägg till nödvändiga permissions (t.ex. User.Read, Mail.Read)

🟡 Grundläggande Graph-klient i C-Sharp


// Install: dotnet add package Microsoft.Graph
//         dotnet add package Microsoft.Graph.Auth

using Microsoft.Graph;
using Microsoft.Graph.Auth;
using Microsoft.Identity.Client;

public class GraphService
{
    private readonly GraphServiceClient _graphServiceClient;

    public GraphService(IConfiguration configuration)
    {
        // Konfiguration från appsettings.json
        var clientId = configuration["AzureAd:ClientId"];
        var clientSecret = configuration["AzureAd:ClientSecret"];
        var tenantId = configuration["AzureAd:TenantId"];

        // Skapa MSAL-klient för autentisering
        var confidentialClientApplication = ConfidentialClientApplicationBuilder
            .Create(clientId)
            .WithClientSecret(clientSecret)
            .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}"))
            .Build();

        // Skapa Graph-klient
        var authProvider = new ClientCredentialProvider(confidentialClientApplication);
        _graphServiceClient = new GraphServiceClient(authProvider);
    }

    // Hämta alla användare
    public async Task<List<User>> GetUsersAsync()
    {
        var users = await _graphServiceClient.Users
            .Request()
            .Select("id,displayName,mail,userPrincipalName")
            .GetAsync();

        return users.ToList();
    }

    // Hämta specifik användare
    public async Task<User> GetUserAsync(string userId)
    {
        return await _graphServiceClient.Users[userId]
            .Request()
            .GetAsync();
    }

    // Hämta användarens emails
    public async Task<List<Message>> GetUserEmailsAsync(string userId)
    {
        var messages = await _graphServiceClient.Users[userId].Messages
            .Request()
            .Select("subject,from,receivedDateTime,bodyPreview")
            .Top(10)
            .OrderBy("receivedDateTime desc")
            .GetAsync();

        return messages.ToList();
    }
}

appsettings.json:


{
  "AzureAd": {
    "ClientId": "din-client-id-från-azure",
    "ClientSecret": "din-client-secret-från-azure",
    "TenantId": "din-tenant-id-från-azure"
  }
}

🔴 Avancerat: Web-app med användarinloggning


// Program.cs för web-app med Microsoft Graph
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;

var builder = WebApplication.CreateBuilder(args);

// Lägg till Microsoft Identity Web
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
    .AddInMemoryTokenCaches();

// Kräv autentisering för alla controllers
builder.Services.AddControllersWithViews(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
});

builder.Services.AddRazorPages().AddMicrosoftIdentityUI();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.MapRazorPages();

app.Run();

// Controller som använder Graph
[Authorize]
public class HomeController : Controller
{
    private readonly GraphServiceClient _graphServiceClient;

    public HomeController(GraphServiceClient graphServiceClient)
    {
        _graphServiceClient = graphServiceClient;
    }

    public async Task<IActionResult> Index()
    {
        // Hämta inloggad användares profil
        var user = await _graphServiceClient.Me
            .Request()
            .GetAsync();

        ViewBag.UserName = user.DisplayName;
        ViewBag.UserEmail = user.Mail;

        return View();
    }

    public async Task<IActionResult> Emails()
    {
        // Hämta användarens emails
        var messages = await _graphServiceClient.Me.Messages
            .Request()
            .Select("subject,from,receivedDateTime,bodyPreview")
            .Top(20)
            .OrderBy("receivedDateTime desc")
            .GetAsync();

        return View(messages);
    }

    public async Task<IActionResult> Calendar()
    {
        // Hämta kommande kalenderhändelser
        var events = await _graphServiceClient.Me.Calendar.Events
            .Request()
            .Filter($"start/dateTime ge '{DateTime.Now:yyyy-MM-ddTHH:mm:ss}'")
            .OrderBy("start/dateTime")
            .Top(10)
            .GetAsync();

        return View(events);
    }
}

📧 Specifika Graph-operationer

Skicka email


public async Task SendEmailAsync(string recipientEmail, string subject, string body)
{
    var message = new Message
    {
        Subject = subject,
        Body = new ItemBody
        {
            ContentType = BodyType.Html,
            Content = body
        },
        ToRecipients = new List<Recipient>
        {
            new Recipient
            {
                EmailAddress = new EmailAddress
                {
                    Address = recipientEmail
                }
            }
        }
    };

    await _graphServiceClient.Me.SendMail(message)
        .Request()
        .PostAsync();
}

Skapa kalenderhändelse


public async Task<Event> CreateCalendarEventAsync(string subject, DateTime startTime, DateTime endTime)
{
    var newEvent = new Event
    {
        Subject = subject,
        Start = new DateTimeTimeZone
        {
            DateTime = startTime.ToString("yyyy-MM-ddTHH:mm:ss"),
            TimeZone = "Europe/Stockholm"
        },
        End = new DateTimeTimeZone
        {
            DateTime = endTime.ToString("yyyy-MM-ddTHH:mm:ss"),
            TimeZone = "Europe/Stockholm"
        }
    };

    return await _graphServiceClient.Me.Calendar.Events
        .Request()
        .AddAsync(newEvent);
}

Ladda upp fil till OneDrive


public async Task<DriveItem> UploadFileAsync(string fileName, Stream fileStream)
{
    return await _graphServiceClient.Me.Drive.Root
        .ItemWithPath(fileName)
        .Content
        .Request()
        .PutAsync<DriveItem>(fileStream);
}

🔐 Permissions och säkerhet

Application Permissions vs Delegated Permissions


DELEGATED PERMISSIONS (för web-appar med inloggade användare):
- User.Read         - Läs användarens profil
- Mail.Read         - Läs användarens mail
- Calendar.ReadWrite - Läs/skriv kalendern
- Files.ReadWrite   - Läs/skriv filer

APPLICATION PERMISSIONS (för daemon/service-appar):
- User.Read.All     - Läs alla användares profiler
- Mail.Read.All     - Läs alla användares mail
- Calendar.ReadWrite.All - Läs/skriv alla kalendrar

VIKTIGT: Application permissions kräver admin-godkännande!

⚠️ Vanliga misstag

  • Misstag 1: Glömma registrera rätt permissions

    • Graph returnerar 403 Forbidden
    • Lösning: Lägg till permission i Azure AD och be admin att godkänna
  • Misstag 2: Använda fel token-typ

    • Application permissions behöver client credentials flow
    • User permissions behöver authorization code flow
  • Misstag 3: Inte hantera rate limiting

    • Graph har gränser för hur många anrop du kan göra
    • Lösning: Implementera retry-logic med exponential backoff

// Retry-logic för Graph API
public async Task<T> ExecuteWithRetryAsync<T>(Func<Task<T>> graphCall)
{
    int maxRetries = 3;
    int delay = 1000; // ms

    for (int i = 0; i < maxRetries; i++)
    {
        try
        {
            return await graphCall();
        }
        catch (ServiceException ex) when (ex.Error.Code == "TooManyRequests")
        {
            if (i == maxRetries - 1) throw;

            // Vänta längre för varje retry
            await Task.Delay(delay * (int)Math.Pow(2, i));
        }
    }

    throw new Exception("Max retries exceeded");
}

🧪 Testing med Graph Explorer

Graph Explorer (https://developer.microsoft.com/en-us/graph/graph-explorer) låter dig testa Graph-queries direkt:


GET https://graph.microsoft.com/v1.0/me
GET https://graph.microsoft.com/v1.0/me/messages?$top=5
GET https://graph.microsoft.com/v1.0/me/calendar/events?$filter=start/dateTime ge '2024-01-01T00:00:00'

📚 Sammanfattning

Microsoft Graph är kraftfullt för Microsoft-integrationer:

  • En API för hela Microsoft-ekosystemet
  • OAuth2-säkerhet via Azure AD
  • RESTful med konsekvent struktur
  • Rika permissions för olika scenarion
  • Bra dokumentation och verktyg

🎯 Övningar

  1. 🟢 Grundläggande: Registrera en app och hämta din profil via Graph
  2. 🟡 Utmanande: Bygg en enkel mail-reader som visar dina emails
  3. 🔴 Expert: Skapa en Teams-bot som kan skicka meddelanden via Graph

😄 Obligatorisk dad joke

Varför är Microsoft Graph så populär på kontoret? För att det är det enda som kan grafera alla relationer mellan kollegorna! 📊


Upp

Upp


Licens: Apache 2.0 | © 2023 Marcus Medina, Campus Mölndal. Alla rättigheter förbehållna.
Du får använda och modifiera detta verk enligt villkoren i Apache License, Version 2.0. Du får inte använda detta verk för kommersiella ändamål utan tillstånd från upphovsmannen.