如何检索和使用 Graph API 访问令牌在 C# 中发送电子邮件

如何检索和使用 Graph API 访问令牌在 C# 中发送电子邮件
如何检索和使用 Graph API 访问令牌在 C# 中发送电子邮件

简化 Microsoft Graph API 的访问令牌检索

您是否曾经遇到过每天从 Graph Explorer 手动检索访问令牌的不便?这可能会令人沮丧,尤其是当您所在的团队依赖自动化通过 Microsoft Graph API 发送电子邮件时。手动流程很快就会成为生产力的瓶颈。 🤔

为了简化这一过程,我决定构建一个 Azure 函数,自动为我的团队检索访问令牌。该解决方案消除了重复性任务的需要,并确保每个人都可以专注于自己的核心工作,而不是代币管理。这就像为您的工作流程提供急需的咖啡因提升! ☕

然而,与大多数开发旅程一样,这一旅程也并非没有挑战。尽管成功生成了令牌,但我遇到了障碍:我的函数返回的令牌与 Graph Explorer 中的令牌不匹配。这种意外的差异引发了有关其有效性和功能的几个问题。

在本文中,我将分享我使用的代码、遇到的问题以及解决问题所采取的步骤。无论您是要构建类似的功能还是只是对 Azure 和 Graph API 感到好奇,本指南都将通过实用见解和相关示例引导您完成整个过程。让我们深入了解一下! 🚀

命令 使用示例
FormUrlEncodedContent 此 C# 命令用于为 POST 请求创建请求正文,其中数据以 application/x-www-form-urlencoded 格式编码。它简化了将键值对传递给需要此格式的 API 的过程。
HttpResponseMessage 表示从 C# 中的 HTTP 请求收到的响应。它允许您检查服务器响应的状态、标头和内容。
EnsureSuccessStatusCode 确保 HTTP 响应状态代码成功 (2xx) 的方法。如果没有,它会抛出异常,使错误处理变得简单。
JsonConvert.DeserializeObject<T> 此 Newtonsoft.Json 方法用于将 JSON 字符串解析为 C# 对象或动态类型。从 API 响应中提取访问令牌至关重要。
os.getenv 检索环境变量的 Python 方法。它对于安全访问客户端 ID 和机密等敏感数据至关重要。
requests.post 发送 HTTP POST 请求的 Python 方法。它在此处用于使用必要的负载调用 Microsoft Graph API 令牌端点。
raise Exception 发生错误时显式引发异常的 Python 命令。这用于 API 响应不成功时的错误处理。
Environment.GetEnvironmentVariable 此 C# 方法获取环境变量。它提供了一种安全的方式来访问凭据,而无需将其硬编码到源代码中。
dynamic 一个 C# 关键字,允许创建类型在运行时解析的对象。对于处理具有不可预测结构的 JSON 响应很有用。
httpClient.PostAsync 用于发送异步 HTTP POST 请求的 C# 方法。此处用于调用 Microsoft Identity 的令牌端点。

了解和优化 Graph API 令牌检索

为了自动执行使用 Microsoft Graph API 发送电子邮件的过程,第一个脚本演示了如何使用 C# 中的 客户端凭据流 检索访问令牌。这在构建不需要用户交互的服务器端应用程序或服务(例如 Azure Function)时特别有用。该脚本通过使用环境变量来存储敏感数据(例如“ClientId”、“ClientSecret”和“TenantId”)安全地获取令牌。这通过避免源代码中的硬编码凭据来确保安全性。

该解决方案的核心围绕“FormUrlEncodedContent”类,该类以身份验证所需的格式创建请求负载。负载准备就绪后,“httpClient.PostAsync”方法将向 Microsoft 身份令牌终结点发送 HTTP POST 请求。此调用确保应用程序可以以编程方式检索有效令牌,然后可以使用该令牌访问 Microsoft Graph API 等资源以发送电子邮件或管理数据。

Python 示例通过提供令牌检索的轻量级替代方案来补充 C# 脚本。通过利用“os.getenv”方法,它直接从环境中提取敏感凭据,就像 C# 脚本一样。 “requests.post”函数执行令牌端点调用,为更熟悉 Python 的开发人员简化了流程。这两个脚本都包含使用“response.EnsureSuccessStatusCode”(C#)进行的强大错误处理以及 Python 中的显式异常引发(“raise Exception”),以管理身份验证失败或 API 错误等问题。

应用这些脚本的一个现实示例是团队通知系统,该系统向团队成员发送有关关键事件的电子邮件,例如即将到来的截止日期或服务中断。这些脚本无需每天登录 Graph Explorer 手动检索令牌,而是自动执行该过程,减少人为错误并提高效率。 🚀 这种自动化不仅节省时间,而且确保系统即使在下班时间也能无缝运行。无论您选择 C# 是为了与企业级解决方案集成,还是选择 Python 是为了简单性,这两种方法都可以有效解决核心问题。 😊

在 C# 中检索 Microsoft Graph API 的访问令牌

该解决方案使用 C# 中的模块化安全后端脚本以编程方式获取和处理 Microsoft Graph API 令牌。

// Import necessary namespaces
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
namespace GraphApiTokenFetcher
{
    public class TokenService
    {
        private static readonly HttpClient httpClient = new HttpClient();
        // Fetch access token using Client Credentials flow
        public static async Task<string> GetGraphAccessTokenAsync(ILogger log)
        {
            try
            {
                // Retrieve environment variables
                var clientId = Environment.GetEnvironmentVariable("ClientId");
                var clientSecret = Environment.GetEnvironmentVariable("ClientSecret");
                var tenantId = Environment.GetEnvironmentVariable("TenantId");
                var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
                // Prepare the request body
                var body = new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair<string, string>("client_id", clientId),
                    new KeyValuePair<string, string>("scope", "https://graph.microsoft.com/.default"),
                    new KeyValuePair<string, string>("client_secret", clientSecret),
                    new KeyValuePair<string, string>("grant_type", "client_credentials")
                });
                // Make the HTTP POST request
                HttpResponseMessage response = await httpClient.PostAsync(tokenEndpoint, body);
                response.EnsureSuccessStatusCode();
                // Read and parse the response
                string responseContent = await response.Content.ReadAsStringAsync();
                var tokenResult = JsonConvert.DeserializeObject<dynamic>(responseContent);
                return tokenResult.access_token;
            }
            catch (Exception ex)
            {
                log.LogError($"Error fetching Graph API token: {ex.Message}");
                throw;
            }
        }
    }
}

使用简单的 Python 脚本测试令牌检索

此方法演示了使用“requests”库使用 Python 检索和验证令牌作为替代后端解决方案。

# Import required libraries
import os
import requests
import json
# Function to fetch access token
def get_graph_access_token():
    client_id = os.getenv("ClientId")
    client_secret = os.getenv("ClientSecret")
    tenant_id = os.getenv("TenantId")
    token_endpoint = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token"
    # Prepare request payload
    payload = {
        "client_id": client_id,
        "client_secret": client_secret,
        "scope": "https://graph.microsoft.com/.default",
        "grant_type": "client_credentials"
    }
    # Send the POST request
    response = requests.post(token_endpoint, data=payload)
    if response.status_code == 200:
        return response.json().get("access_token")
    else:
        raise Exception(f"Failed to retrieve token: {response.text}")
# Retrieve and print token
if __name__ == "__main__":
    try:
        token = get_graph_access_token()
        print("Access Token:", token)
    except Exception as e:
        print("Error:", str(e))

克服 Graph API 令牌验证中的挑战

使用 Microsoft Graph API 时,开发人员经常面临的一项关键挑战是确保访问令牌的有效性和范围。虽然使用客户端凭据流检索令牌非常简单,但其可用性取决于 Azure AD 中授予应用程序的权限。一个常见的疏忽是未能正确配置 API 权限,从而导致使用令牌发送电子邮件或执行其他操作时出现错误。

另一个重要的考虑因素是了解通过 Graph Explorer 检索的令牌与以编程方式生成的令牌之间的差异。 Graph Explorer 令牌通常与用户的上下文及其特定权限相关联,而使用客户端凭据流的编程令牌则仅限于应用程序范围。这种区别解释了为什么返回的令牌可能不匹配,即使底层配置看起来相似。

要解决这些差异,您应该验证应用程序是否具有必要的 Mail.Send 或​​ Azure 门户中的等效委派权限。此外,使用 [JWT.io](https://jwt.io) 等工具检查解码的令牌有效负载可以帮助识别丢失或不正确的声明,例如“scp”(范围)或“角色”。在现实世界中,这一点至关重要的场景是自动发送大量电子邮件以发送客户通知。如果没有正确的配置,系统可能会在生产过程中出现故障,影响客户沟通。采取这些步骤可确保无缝集成并为您的解决方案构建可靠性。 😊

有关检索和使用 Graph API 令牌的热门问题

  1. 为什么我的令牌与 Graph Explorer 中的令牌不匹配?
  2. 以编程方式检索的令牌使用 Client Credentials flow,与 Graph Explorer 基于用户的令牌不同,它限制了应用程序的权限范围。
  3. 的作用是什么 scope 令牌请求中的参数?
  4. scope 指定API访问级别,例如 https://graph.microsoft.com/.default,确保适当的访问权限。
  5. 如何解码访问令牌?
  6. 使用类似的工具 JWT.io 检查令牌的有效负载是否有声明,例如“scp”或“roles”,以验证权限。
  7. 为什么我在使用令牌时收到“错误请求”响应?
  8. 确保您的应用程序具有所需的 API permissions (例如。, Mail.Send)在 Azure AD 中配置并获得管理员同意。
  9. 我可以自动刷新令牌吗?
  10. 是的,您可以使用以下方法在新令牌过期时以编程方式检索新令牌: Client Credentials flow,绕过手动干预的需要。

关于自动化令牌检索的最终想法

通过自动检索令牌 图形API,开发人员可以节省时间并确保安全、无错误的流程。此方法对于需要可靠访问资源而无需手动干预的服务器端应用程序特别有用。 😊

了解令牌范围、权限以及用户和应用程序令牌之间的差异对于成功至关重要。有了这些见解,您可以自信地实施高效的工作流程,最大限度地减少干扰并提高团队或组织的生产力。

Microsoft Graph API 令牌检索的来源和参考
  1. 综合指南 Microsoft Graph API 身份验证 涵盖客户端凭证流程、范围和权限。
  2. 官方文档 .NET 中的 HttpClient 使用 ,包括异步 HTTP 请求的示例。
  3. 见解来自 智威汤逊 用于解码和验证 Microsoft Graph API 身份验证中使用的 JSON Web 令牌 (JWT)。
  4. 详细教程上 Azure Active Directory 应用程序注册 配置 API 权限和客户端机密。