首页 文章

Azure Active Directory WebApi - 服务器到服务器

提问于
浏览
2

我正在尝试使用azure活动目录验证多个客户端(从Windows服务器应用程序连接 - 无浏览器)访问我的.Net4.51 webAPI .

我为我的webapi创建了一个名为“ServerWebApi”的Azure AD应用程序,并使用以下应用程序设置将我的webapi应用程序代码配置为在webConfig中指向它 .

<add key="ida:Tenant" value="myDomainName.onmicrosoft.com" />
<add key="ida:Audience" value="https://myDomainName.onmicrosoft.com/ServerWebApi" />
<add key="ida:ClientID" value="<client id>" />

因此,当请求带有令牌时,它应该使用这些设置来针对名为ServerWebApi的AD WebApi应用程序验证令牌 .

现在,为了让每个客户端都能够获取令牌,我为每个客户端创建了一个Azure应用程序 . (我没有创建它作为本机应用程序,而是作为webapi应用程序创建,以便我可以为每个客户端创建一个单独的键) . 我还将Azure中的实际webAPI应用程序(ServerWebApi)添加到“此应用程序访问的Web API”列表中 . (对于此示例,我的第一个客户端称为myClientWebApiApp)

所以现在我的客户端可以成功地从AD中的客户端App请求令牌,但是当它发布到服务器(webapi)时,我得到401 - 未经授权 . 因此,我认为我无法验证我的Azure AD ServerWebApi webApi上的令牌 .

我用来获取令牌并调用我的webApi的客户端应用程序代码如下

// Create an ADAL AuthenticationContext object and link it to my tennant domain myDomainName.onmicrosoft.com
var authority = ConfigurationManager.AppSettings["Tenant"];
authenticationContext = new AuthenticationContext(authority);

//Client Cerdential Object used while Acquiring a token from Windows Azure AD
ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

// Invoke AuthenticationContext.AcquireToken to obtain an AccessToken. 
// Uses previously-created ClientCredential to authenticate
authenticationResult = authenticationContext.AcquireToken(resource, clientCred);

httpClient.DefaultRequestHeaders.Clear();
//Add authorization header to HttpClient
httpClient.DefaultRequestHeaders.Authorization = new        AuthenticationHeaderValue("Bearer",authenticationResult.AccessToken);

var data = "new Value";

// Call the Service web api to update                    
HttpResponseMessage response = httpClient.PostAsJsonAsync(resourceurl + "api/Values", data).Result;

它使用以下配置设置

<add key="Tenant" value="https://login.windows.net/myDomainName.onmicrosoft.com"/>
<add key="ClientId" value= "<client id>"/>
<add key="ClientSecret" value= "<client secret>"/>
<add key="ResourceUrl" value="https://localhost:44300/"/>
<add key="AppIdUri" value="https://myDomainName.onmicrosoft.com/myClientWebApiApp"/>

客户端ID是我创建的客户端webapi应用程序的ID,ClientSecret是我在Azure AD中针对该应用程序创建的密钥 .

有谁知道我在做什么是可能的,如果是的话,我做错了什么?

2 回答

  • 1

    我相信您的问题最终在于如何设置AuthorizationHeader以及您的ServerWebApi如何响应请求 .

    看看this blog . 我相信这是您正在寻找的解决方案 .

  • 0

    我也面临类似的问题并等待解决方案 . 但是作为一种解决方法,我创建如下 . 我相信这可能不是一个合适的解决方案 . 更好的答案建议肯定会对我们有所帮助 .

    步骤1:在WebApiConfig.cs中向Register方法添加以下行

    config.MessageHandlers.Add(new AzureADAuthorizationHandler
    {
        Audience = ConfigurationManager.AppSettings["Audience"],
        SymmetricKey = ConfigurationManager.AppSettings["ClientSecretKey"]
    });
    

    第2步: ( Note below implementation is Work In Progress as mentioned in the comments)

    using System;
    using System.IdentityModel.Tokens;
    using System.Net;
    using System.Net.Http;
    using System.Security.Claims;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Http.Controllers;
    
    namespace MyDevWebApiService.Common
    {
        public class AzureADAuthorizationHandler : DelegatingHandler //: AuthorizeAttribute
        {
             //public override void OnAuthorization(HttpActionContext actionContext)
            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage httpRequestObject, CancellationToken cancellationToken)
            {
                HttpResponseMessage httpResponseMessage = null;
    
                try
                {
                    var RequuestObj = System.Web.HttpContext.Current.Request;
                    var AuthHeader = RequuestObj.Headers["Authorization"];
    
                    if (AuthHeader == null)
                    {
                        httpResponseMessage = httpRequestObject.CreateErrorResponse(HttpStatusCode.BadRequest, "No authorization header present in the request");
                    }
                    else
                    {
                        string encodedTokenString = AuthHeader.StartsWith("Bearer ") ? AuthHeader.Substring(7) : AuthHeader;
                        //Validate date the token - Work in Progress. Should be able to handle Bearer and Basic headers.
                        //Extract the Azure Ad info (tenant, client id and client security key etc) and use ADAL to authenticate with Azure AD.
                        SetCurrentPrincipal(encodedTokenString);
                    }
                }            
                catch (Exception ex)
                {
                    httpResponseMessage = httpRequestObject.CreateErrorResponse(HttpStatusCode.BadRequest, ex + "Invalid header, header token extration failed");
                }
    
                return httpResponseMessage != null ? Task.FromResult(httpResponseMessage) : base.SendAsync(httpRequestObject, cancellationToken);
            }
    
            public void SetCurrentPrincipal(string encodedTokenString)
            {
                try
                {
                    ClaimsIdentity ClaimsIdentityObject = new ClaimsIdentity();
    
                    JwtSecurityToken JwtSecurityTokenObject = new System.IdentityModel.Tokens.JwtSecurityToken(encodedTokenString);
    
                    foreach (Claim ClaimObj in JwtSecurityTokenObject.Claims)
                    {
                        ClaimsIdentityObject.AddClaim(ClaimObj);
                    }
    
                    Thread.CurrentPrincipal = new ClaimsPrincipal(ClaimsIdentityObject);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
    }
    

    ================================================== ================================================= Note: 被动联邦:

    当我们在VS2013和.NET4.5.1中创建MVC项目时,它将在项目中创建持久性本地数据库并存储所有身份验证详细信息 .

    调整此被动联合以进行活动联合,尤其是持久性存储角度,这并不合适 .

    下面的类将自动生成 .

    • Models.TenantDbContext

    • Models.IssuingAuthorityKey

    • Models.Tenant

    • Utils.DatabaseIssuerNameRegistry

    • IdentityConfig

    • 附加行 - > IdentityConfig.ConfigureIdentity();在Global.asax.cs中Application_Start()

    • 配置文件条目 .

相关问题