2016-06-14 45 views
0

我有一個需要向Signalr Realtime Api(Api2)發送消息的Asp.Net Web Api(Api1)。我正在嘗試使用Azure AD承載標記進行身份驗證。 Api1的客戶端是一個使用ADAL.js從Azure獲取令牌的JavaScript客戶端。Web Api到Signalr Azure令牌不起作用

var authContext = new AuthenticationContext({  
      tenant: tenantId, 
      clientId: jsclientId, 
      postLogoutRedirectUri: window.location.origin, 
      cacheLocation: 'localStorage', 
      endpoints: { 
       api1Url: api1ResourceUri 
      } 
    }); 

    authContext.acquireToken(jsclientId, function (error, token) { 
     if (error || !token) { 
      authContext.clearCache(); 
      authContext.login(); 
     } 
    }); 

JS客戶端將此令牌附加到授權頭中的所有Api調用到Api1。在Api1中,我使用以下代碼從Azure AD獲取訪問令牌。

var userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName); 

var result = await authenticationContext.AcquireTokenAsync(api2ResourceId, new ClientCredential(api1clientId, api1clientSecret), userAssertion); 

我將此訪問令牌作爲授權標頭「Bearer tokenvalue」附加到請求中。在Signalr Hub Owin Startup類中,我有以下代碼。

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions 
{ 
    TokenValidationParameters = new TokenValidationParameters 
    { 
      ValidAudiences = api1Audiences, 
      SaveSigninToken = true 
    }, 
    Tenant = configSection.TenantId 
}); 

雖然集線器上的ClaimsIdentity顯示爲已驗證,但用戶的身份未設置。 identity.name爲null。它看起來像用戶身份沒有被傳遞到信號中心。

回答

1

您的API中沒有用戶身份,因爲您是以應用程序的身份進行身份驗證,而不是以用戶的身份進行身份驗證。

僅在資源和ClientCredentials中採用的acquireTokenAsync重載用於客戶端憑證流(也稱爲App-only流)。

你需要做的是使用代表流來交換你爲API2獲得的令牌API2的令牌。

所以在API1的 Startup.Auth,TokenValidation參數設置保存SigninToken爲true,像這樣:

app.UseOpenIdConnectAuthentication(
    OpenIdConnectAuthenticationOptions 
    { 
     // ... 
     TokenValidationParameters = new TokenValidationParameters 
     { 
     SaveSigninToken = true 
     }, 
     // ... 
    }); 

然後,無論你想打電話給你的API2,請執行以下操作:

ClientCredential clientCred = new ClientCredential(clientId, appKey); 
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext; 
string userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value; 
string userAccessToken = bootstrapContext.Token; 
UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName); 

result = await authContext.AcquireTokenAsync(api2ResourceId, clientCred, userAssertion); 

在示例中查看:https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof,具體說明ToDoService的Startup.Auth.cs和TodoListController.cs。

注意:本示例適用於本機應用程序+ web api,您正在使其適用於web應用程序+ web api。

編輯 - 確保您的JS代碼由JS調用acquireToken像這樣指定API1請求您API1令牌:

var authContext = new AuthenticationContext({  
     tenant: tenantId, 
     clientId: jsclientId, 
     postLogoutRedirectUri: window.location.origin, 
     cacheLocation: 'localStorage', 
     endpoints: { 
      api1Url: api1ResourceUri 
     } 
}); 

authContext.acquireToken(api1clientId, function (error, token) { 
    if (error || !token) { 
     authContext.clearCache(); 
     authContext.login(); 
    } 
}); 
+0

graphResourceId會https://graph.windows.net? – Bipindas

+0

我的不好,那應該是api2ResourceId,修好了。 – Saca

+0

我更新了AcquireTokenAsync和UserAssertion,如上所述。現在,我收到一條錯誤「聲明觀衆聲明與所需值不符」。它表示觀衆期望的是Api1,但觀衆是調用Api1的JavaScript客戶端。我已經更新了該問題以顯示JS客戶端代碼。 – Bipindas