Integration Guide: Effortless Microsoft Graph API Access SSO

Previous Article Link: Click Here

Microsoft Graph API

Microsoft Graph API

Microsoft Graph API is a comprehensive set of RESTful web APIs provided by Microsoft to enable developers to access and interact with a wide range of Microsoft 365 services. Microsoft 365, formerly known as Office 365, includes services such as Microsoft Outlook, OneDrive, SharePoint, Microsoft Teams, and more.

Microsoft Graph API allows developers to build applications that can access data and perform various tasks across different Microsoft 365 services using a single endpoint. It provides a unified programming model that simplifies the development process by offering a consistent way to interact with diverse Microsoft 365 data and services.

Key features and capabilities of Microsoft Graph API

  1. Unified Endpoint: Developers can use a single API endpoint (https://graph.microsoft.com) to access data and resources across multiple Microsoft 365 services.
  2. Authentication: Microsoft Graph API uses OAuth 2.0 for authentication, ensuring secure access to user and organizational data.
  3. Rich Data Access: It provides access to a wide range of data, including user profiles, emails, calendar events, files, and more.
  4. Webhooks and Change Notifications: Developers can subscribe to changes in data and receive real-time notifications, allowing for more efficient and responsive applications.
  5. Consistent Query Language: Microsoft Graph API uses the OData query language, making it easy for developers to retrieve and filter data based on specific criteria.
  6. Application Integration: Developers can integrate Microsoft Graph API into their applications, whether they are web, mobile, desktop, or server applications.
  7. Open Standards: Microsoft Graph API follows open standards, facilitating interoperability and integration with various platforms and technologies.

Developers can use Microsoft Graph API to create a wide range of applications, from productivity tools and workflow automation to business intelligence and analytics solutions. It provides a powerful way to leverage the capabilities of Microsoft 365 in custom applications and services.

Graph API Explore: https://developer.microsoft.com/en-us/graph/graph-explorer

How can I get started

To get started with Microsoft Graph API in C#, you can follow these steps.

  1. Set Up a Microsoft 365 Developer Account: If you don't have one, create a Microsoft 365 developer account. This will provide you access to the Microsoft 365 Developer Program, which includes a subscription with development resources.
  2. Register Your Application
    • Go to the Microsoft Azure Portal.
    • Navigate to the "Azure Active Directory" section.
    • Register a new application to obtain the client ID and client secret.
  3. Configure API Permissions: In the registered application, configure the required API permissions, such as Calendars.Read for accessing calendar data or User.Read for reading user data.
  4. Acquire Access Token: In your C# application, use OAuth 2.0 to obtain an access token. You will need the client ID, client secret, and the appropriate endpoint.

Example. Settings File

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "MicrosoftSSO": [
    {
      "Domain": "doamin.com",
      "TenantId": "TenantId",
      "ClientId": "ClientId",
      "ClientSecret": "ClientSecret",
      "RedirectURI": "https%3A%2F%2Flocalhost%3A7240%2FHome%2FOAuth",
      "Scopes": "user.read,Directory.Read.All",
      "GrantType": "authorization_code"
    }
  ]
}

Model Class for Settings and Token Object of Microsoft Login.

public class BoSSOModel
{
    public BoSSOModel()
    {
        Domain = string.Empty;
        TenantId = string.Empty;
        ClientId = string.Empty;
        ClientSecret = string.Empty;
        RedirectURI = string.Empty;
        Scopes = string.Empty;
        GrantType = string.Empty;
    }
    public string Domain { get; set; }
    public string TenantId { get; set; }
    public string ClientId { get; set; }
    public string ClientSecret { get; set; }
    public string RedirectURI { get; set; }
    public string Scopes { get; set; }
    public string GrantType { get; set; }
}

public class TokenObjectFromOutlook
{
    public TokenObjectFromOutlook()
    {
        TokenType = string.Empty;
        Scope = string.Empty;
        AccessToken = string.Empty;
        RefreshToken = string.Empty;
    }
    [JsonProperty("token_type")]
    public string TokenType { get; set; }
    [JsonProperty("scope")]
    public string Scope { get; set; }
    [JsonProperty("expires_in")]
    public int ExpiresIn { get; set; }
    [JsonProperty("ext_expires_in")]
    public int ExtExpiresIn { get; set; }
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }
    [JsonProperty("refresh_token")]
    public string RefreshToken { get; set; }
}

Initialize the Controller class with specified settings.

 public class HomeController(ILogger<HomeController> logger, IMSGraphEventAccess mSGraphEventAccess, IMSGraphUserAccess mSGraphUser, IConfiguration configurationManager) : Controller
 {
     private readonly ILogger<HomeController> _logger = logger;
     private readonly IMSGraphEventAccess _mSGraphEventAccess = mSGraphEventAccess;
     private readonly IMSGraphUserAccess _mSGraphUser = mSGraphUser;
     private readonly IConfiguration _configurationManager = configurationManager;

     private List<BoSSOModel> BoSSOModels => _configurationManager.GetSection("MicrosoftSSO").Get<List<BoSSOModel>>() ?? [];

}

Single Sign-On Implementation

Web Application

    <a href="@Url.Action("SingleSignOn", "Home")" style="text-decoration: none;">
        <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="300px" height="50px" viewBox="0 0 3278 522" class="SignInButton">
        <style type="text/css">
            .fil0:hover {
                fill: #4B4B4B;
            }

            .fnt0 {
                font-size: 260px;
                font-family: 'Segoe UI Semibold', 'Segoe UI';
                text-decoration: none;
            }
</style>
        <rect class="fil0" x="2" y="2" width="3174" height="517" fill="black" />
        <rect x="150" y="129" width="122" height="122" fill="#F35325" />
        <rect x="284" y="129" width="122" height="122" fill="#81BC06" />
        <rect x="150" y="263" width="122" height="122" fill="#05A6F0" />
        <rect x="284" y="263" width="122" height="122" fill="#FFBA08" />
        <text x="470" y="357" fill="white" class="fnt0">Login With Microsoft</text>
        </svg>
    </a>
public void SingleSignOn()
{  
    if (BoSSOModels?.Count > 0)
    {
        var boSSOModel = BoSSOModels.FirstOrDefault(x => x.Domain == "doamin.com") ?? new BoSSOModel(); 
        string ssoURL = $"https://login.microsoftonline.com/{boSSOModel.TenantId}/oauth2/v2.0/authorize?client_id={boSSOModel.ClientId}&response_type=code&redirect_uri={boSSOModel.RedirectURI}&response_mode=query&Scope={boSSOModel.Scopes}";
        Response.Redirect(ssoURL);
    }
}

Upon successful authentication, the system will redirect to the configurable URL (Redirect URI).

public async Task<IActionResult> OAuth()
{
    if (BoSSOModels?.Count <= 0)
    {
        return null;
    }
    var boSSOModel = BoSSOModels.FirstOrDefault(x => x.Domain == "doamin.com") ?? new BoSSOModel();
    var queryCollection = Request.Query;
    if (queryCollection != null && queryCollection.Count > 0)
    {
        string codePresent = queryCollection["code"];
        if (string.IsNullOrWhiteSpace(codePresent))
            return NotFound();

        codePresent = !string.IsNullOrWhiteSpace(codePresent) ? codePresent : "Code";

        using var client = new HttpClient();
        var request = new HttpRequestMessage(HttpMethod.Post, $"https://login.microsoftonline.com/{boSSOModel.TenantId}/oauth2/v2.0/token");
        var collection = new List<KeyValuePair<string, string>>
        {
            new("Scope", boSSOModel.Scopes),
            new("code", codePresent),
            new("grant_type", boSSOModel.GrantType),
            new("client_secret",boSSOModel.ClientSecret),
            new("client_id", boSSOModel.ClientId),
            new("redirect_uri", boSSOModel.RedirectURI)
        };
        var content = new FormUrlEncodedContent(collection);
        request.Content = content;
        var response = await client.SendAsync(request);
        var res = response.Content.ReadAsStringAsync().Result;
        if (response.IsSuccessStatusCode)
        {
            var tokeninfo = JsonConvert.DeserializeObject<TokenObjectFromOutlook>(res);
            return Redirect("https://localhost:7240?value=" + tokeninfo.RefreshToken);
        }
    }
    return View();
}

This will assist us in retrieving settings from a file and then filtering them based on the specified domain.

 var boSSOModel = BoSSOModels.FirstOrDefault(x => x.Domain == "doamin.com") ?? new BoSSOModel();

Once an AccessToken is obtained, we can utilize the Graph API and initiate HttpClient requests to retrieve details, adhering to the access limits associated with the currently logged-in user.

Thanks


Similar Articles