0

我正努力嘗試從Xamarin Forms Android應用訪問存儲的api(這是默認的web api,帶有值控制器等)。我發現了大量關於如何實現這一點的文檔,但我不想使用「傳統方式」,例如處理AuthenticationContext \ Authentication Result。該請求是在應用程序,而不是由微軟,谷歌提供了一個等訪問xamarin訪問Azure存儲的web api android

使用自定義登錄表單我的登錄工作是這樣的:

HttpClient client = new HttpClient(); 
    var tokenEndpoint = "https://login.microsoftonline.com/testdir.onmicrosoft.com/oauth2/token"; 
    var body = "resource=www.graph.microsoft.com&client_id=" + App.ClientId + "&grant_type=password&username=" + UsernameEntry.Text + "&password=" + PasswordEntry.Text + ""; 
    var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded"); 
    var result = await client.PostAsync(tokenEndpoint, stringContent).ContinueWith<string>(response => response.Result.Content.ReadAsStringAsync().Result); 
    var jobject = JObject.Parse(result); 
    App.AccessToken = jobject["access_token"].Value<string>(); 

這就像一個魅力。我現在有了訪問令牌,我可以使用它來從Azure AD中檢索用戶或任何內容。

我想要的東西類似於從web api中檢索數據。我希望登錄發生在幕後,而不是通過提供Microsoft登錄表單並提示用戶登錄。

我想是這樣的:

tokenEndpoint = "https://login.microsoftonline.com/testdir.onmicrosoft.com/oauth2/authorize"; 
    body = "client_id=xxxx&response_type=code&redirect_uri=https://testapi.azurewebsites.net/"; 
    result = await client.PostAsync(tokenEndpoint, stringContent).ContinueWith<string>(response => response.Result.Content.ReadAsStringAsync().Result); 
    jobject = JObject.Parse(result); 

但我總是得到一個錯誤,指出用戶必須登錄。 (我認爲它基本上會嘗試生成一個Microsoft登錄表單,並且在嘗試成功之後,它將直接訪問api所需的授權代碼)。

如果我可以從一次調用中檢索授權碼,然後用它來查詢Web API,那將是非常棒的。

這裏是我發現的,說明類似問題\情景一些有用的問題,但我沒能包住所有信息成片的工作代碼:

​​

Use OAuth2 for authentication against Azure AD to call WebAPI

Unable to use bearer token to access AAD-secure Web API

任何幫助將非常感謝。謝謝!

回答

0

這花了很長時間,但我終於得到它的工作。我使用了與登錄部分幾乎相同的方法,但使用了一個轉義(查看工作登錄機制的代碼示例,請參閱問題的第一部分)。 使用下面的代碼片段,我能夠獲得一個令牌,然後用它來訪問我的自定義API:

var clientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; 
var client_secret = "yyyy"; 
HttpClient client = new HttpClient(); 
string tokenEndpoint = "https://login.microsoftonline.com/testTenant.onmicrosoft.com/oauth2/token"; 
var body = "resource=" + clientId + "&client_id=" + clientId + "&client_secret=" + client_secret + "&grant_type=password&username=" + username + "&password=" + password + ""; 
var stringContent = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded"); 
var result = await client.PostAsync(tokenEndpoint, stringContent).ContinueWith<string>(response => response.Result.Content.ReadAsStringAsync().Result); 
     JObject jobject = JObject.Parse(result); 
var accessToken = jobject["access_token"].Value<string>(); 

最棘手的部分是找出這些參數「資源」和「的client_id」必須具有相同的值,如Azure註冊的自定義web api的App ID。在我做出允許代碼工作的更改之前,我收到以下錯誤:

1)在名爲testTenant.onmicrosoft.com的租戶中未找到名爲https://customApi.azurewebsites.net/的應用程序。如果應用程序尚未由租戶的管理員安裝或由租戶中的任何用戶同意,則可能會發生這種情況。您可能已將驗證請求發送給錯誤的承租人。

這裏的問題是我使用「https://customApi.azurewebsites.net/」作爲資源。

2)應用程序'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'正在爲自己請求一個令牌。僅當使用基於GUID的應用程序標識符指定資源時才支持此場景。

第一次出錯後,我試着將資源替換爲「https://testTenant.onmicrosoft.com/CustomApi」。看到錯誤消息,我用我的API的APP ID替換了鏈接。那就是訣竅。

雖然您生成了有效的密鑰,但您也可能會遇到錯誤,指出client_secret無效。我不得不重新生成幾次密鑰,然後才能正常工作。

我還在MSDN上發佈了關於此問題的線索。你可以在那裏找到有用的資源。

請注意,這不是推薦的方法,並存在嚴重的安全風險。但在適用情況下可能會出現極少數情況:

「可能有些時候密碼授予機制可以」可接受「 - 例如在僅供內部用戶使用的核準公司計算機上安裝的非公開應用程序中。那正是我的場景。

肖恩提供了寶貴的文檔,包括如何做到這一點以及推薦的做法。

0

您在尋找Resource Owner Password Credentials Grant的。

有關於此流程的基本文檔here

您應該知道,一般來說,Azure Active Directory團隊強烈建議不要使用此流程,因爲它需要您的應用程序處理用戶的用戶名和密碼,這會帶來許多安全問題。

請在這裏閱讀更多關於爲什麼你不應該這樣做的警告。

Vittorio Bertocci - Using ADAL .NET to Authenticate Users via Username/Password

Rich Randall - How to authenticate user with Azure Active Directory using OAuth 2.0?

OAuth 2.0 Specification - Security Considerations

總結:我已經向您展示您如何做到這一點...但你不應該這樣做。

+0

謝謝肖恩。我已經使用文章中描述的機制來製作自定義登錄表單。我努力從自定義web api中檢索數據,這些數據也是以azure託管的。我不知道如何檢索所謂的「authorization_code」,並將其用於對自定義api的http請求中。我知道我的方法不被推薦,但我們的客戶希望這種方法,因爲實施的應用程序將用於安全的內部網絡,應用程序將只在它們之間進行通信。 –

+1

對不起,我不太瞭解你目前的問題。你不知道如何獲得授權碼,然後獲得訪問令牌?授權碼不能直接用於調用API。它必須交換爲訪問令牌。你是否能夠獲得訪問令牌? –

+0

我能夠從Microsoft圖表獲取訪問令牌並使用它登錄到Azure AD。現在我想使用類似的機制來訪問我實現的自定義Web API。如果我理解正確,則建議使用與登錄場景('https:// login.microsoftonline.com/testdir.onmicrosoft.com/oauth2/token')相同的端點調用,但使用作爲資源的自定義web api我創建的,而不是微軟的圖形,這將提供一個令牌,我可以用它來訪問我的API?我不知道如何交換授權碼的訪問令牌。 –