如何让AccessToken访问使用Azure AD保护的web api

时间:2018-03-08 10:37:56

标签: asp.net-mvc asp.net-web-api azure-active-directory openid-connect

我有一个使用Azure AD保护的web api应用程序(http://localhost:54540),如下所示,

enter image description here

现在我尝试使用OpenIdConnect从常规MVC应用程序访问web api,这里是MVC的startup类,

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

    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectUri
            });
    }
}

现在,我正在尝试将web api访问到MVC控制器之一,如下所示,

[Authorize]
public class HomeController : Controller
{
    public string AccessToken
    {
        get
        {
            //var claim = Context.User?.FindFirst("access_token");
            //if (claim == null)
            //{
            //    throw new InvalidOperationException();
            //}

            //return claim.Value;
        }
    }

    public async Task<ActionResult> Index(CancellationToken cancellationToken)
    {

        using (var client = new HttpClient())
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:54540/api/message");
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);

            var response = await client.SendAsync(request, cancellationToken);
            response.EnsureSuccessStatusCode();


            return View();
        }



    }
} 

问题 - 获取AccessToken需要哪些代码?谢谢!

1 个答案:

答案 0 :(得分:1)

根据您的说明,您在Azure Web App上托管的WebAPI应用程序使用App Service Authentication / Authorization(EasyAuth),而无需在WebAPI应用程序中添加相关的身份验证中间件(例如Microsoft.Owin.Security.ActiveDirectory)。

要使用OpenIdConnect从MVC Web应用程序访问WebAPI,您可以按照以下方法操作:

对于AAD v1.0 app ,您可以在Azure门户上为MVC应用程序创建AAD应用程序,并设置访问WebAPI AAD应用程序所需的权限。然后,您可以按照juunas提供的教程添加OnAuthorizationCodeReceived方法以通过ADAL检索令牌并缓存检索到的令牌,然后您可以使用authContext.AcquireTokenSilentAsync在后​​续请求中获取访问令牌而无需要求用户凭证。

    private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
    {
        var code = context.Code;

        ClientCredential credential = new ClientCredential(clientId, appKey);
        string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
        AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));

        // If you create the redirectUri this way, it will contain a trailing slash.  
        // Make sure you've registered the same exact Uri in the Azure Portal (including the slash).
        Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));

        AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, "<resource, you could specify it to the AAD app ClientId for your WebAPI application>");
    }

注意:对于resource中的AcquireTokenByAuthorizationCodeAsync参数,您可以将其设置为WebAPI应用程序的AAD应用程序ClientId,而不是github中的graphResourceId样品。如果在调用authContext.AcquireTokenSilentAsync时tokenCache中没有有效令牌,则可能会遇到以下错误:

enter image description here

对于AAD v2.0应用,您需要在App Registration Portal注册应用。我已经检查过EasyAuth可以与v2.0应用程序配合使用,您可以使用Azure Portal上v2.0应用程序的clientId,clientSecret来配置AAD身份验证。对于此方法,在使用OpenIdConnect时,您需要MSAL使用ConfidentialClientApplication.AcquireTokenByAuthorizationCodeAsync获取令牌并在后续请求中使用ConfidentialClientApplication.AcquireTokenSilentAsync。您可以针对OpenIdConnect相关代码示例关注here,关于AcquireTokenSilentAsync关注SampleAuthProvider

此外,如果您在没有用户交互的情况下处理Daemon or Server Application to Web API,则可以使用OAuth 2.0客户端凭据授权流并提供clientId和clientSecret以通过使用MSAL for v2.0 app或ADAL获取访问令牌对于v1.0 app。