c# - 如何使用登录用户的 AccessToken 实例化 Microsoft GraphClient?

标签 c# asp.net-mvc azure-active-directory microsoft-graph-api adal

我的 Startup.Auth.cs 看起来像这样:

public partial class Startup
{
    private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private static string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
    private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
    private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];

    public static readonly string Authority = aadInstance + tenantId;

    // This is the resource ID of the AAD Graph API.  We'll need this to request a token to call the Graph API.
    string graphResourceId = "https://graph.microsoft.com";

    public void ConfigureAuth(IAppBuilder app)
    {
        ApplicationDbContext db = new ApplicationDbContext();

        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = Authority,
                PostLogoutRedirectUri = postLogoutRedirectUri,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                   AuthorizationCodeReceived = (context) => 
                   {
                       var code = context.Code;
                       ClientCredential credential = new ClientCredential(clientId, appKey);
                       string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;

                       TokenCache userTokenCache = new ADALTokenCache(signedInUserID);

                       AuthenticationContext authContext = new AuthenticationContext(Authority, userTokenCache);
                       AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                       code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);

                       string token = result.AccessToken;

                       return Task.FromResult(0);
                   }
                }
            });
    }
}

上面倒数第二行代码(字符串变量“token”)正确包含当前登录用户的 AccessToken。后来,我的 Web 应用程序项目尝试实例化 Microsoft GraphClient 对象,如下所示:

GraphServiceClient graphClient = new GraphServiceClient(new AuthenticationController());

当上面的代码被调用时,一个新的 AuthenticationController 被创建,像这样:

public class AuthenticationController : IAuthenticationProvider
{
    private string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
    private string appKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
    private string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];

    public async Task AuthenticateRequestAsync(HttpRequestMessage request)
    {

        string signedInUserID = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
        string tenantID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;

        // get a token for the Graph without triggering any user interaction (from the cache, via multi-resource refresh token, etc)
        ClientCredential creds = new ClientCredential(clientId, appKey);

        TokenCache tokenCache = new ADALTokenCache(signedInUserID);
        // initialize AuthenticationContext with the token cache of the currently signed in user, as kept in the app's database
        AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID, tokenCache);
        AuthenticationResult authResult = await authenticationContext.AcquireTokenAsync("https://graph.microsoft.com/", creds);

        request.Headers.Add("Authorization", "Bearer " + authResult.AccessToken);
    }
}

我的问题是上面的 AuthenticationController 代码检索与 Web 应用程序关联的 AccessToken,而不是当前登录的用户。我需要使用当前登录用户的 AccessToken 实例化一个 GraphClient,而不是 Web 应用程序。 具体来说,我希望最后一行代码中的变量 authResult.AccessToken 包含当前登录用户的 AccessToken-在用户。有什么方法可以安全地将当前登录用户的 token 缓存保存在 Startup.Auth.cs 中,然后在 AuthenticationController 类中检索它?

最佳答案

如果您已经有一个 token ,您可以调用告诉 GraphServiceClient 来简单地使用该 token ,而不是尝试重新获取一个 token 。这是使用 DelegateAuthenticationProvider 完成的类:

var graphserviceClient = new GraphServiceClient(
    new DelegateAuthenticationProvider(
        (requestMessage) =>
        {
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);

            return Task.FromResult(0);
        }));

您存储该 token 的位置取决于应用程序的类型和您的架构。对于 Web 应用程序,您可以将其存储在 Session 或 Cookie 中,对于内存中的 native 应用程序。 token 是短暂的,因此任何临时存储通常都是可以接受的。

关于c# - 如何使用登录用户的 AccessToken 实例化 Microsoft GraphClient?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48478987/

相关文章:

c# - 如何在 C# 中使用反射来列出 .asmx 的方法

c# - 为给定对象从服务器向客户端发送 ‘updated only fields’ 的模式/技术?

c# - goto 语句范围内没有这样的标签 'Label_05C0'

c# - base64 编码 HttpPostedFileBase

asp.net-mvc - SignalR Sql Server/Owin 依赖问题

jquery - 使用 qTip jQuery 插件进行 ASP.NET MVC 验证

azure - 将 Azure AD 用户同步到本地 AD

azure - 检查 MVC 应用程序中的用户角色以获取 Azure Active Directory 的授权

json - 使用 Powershell,如何将 Azure AD 组成员转换为 Json 对象(文件),然后进行更新?

c# - 通过反射在属性上设置私有(private) setter