組建多層應用程式使用 On-Behalf-Of (OBO) 使用 AD FS 2016 中的 OAuthBuild a multi-tiered application using On-Behalf-Of (OBO) using OAuth with AD FS 2016

適用於:Windows Server 2016Applies To: Windows Server 2016

本節提供實作開展工作的 (OBO) 驗證的 Windows Server 2016 TP5 AD FS 使用的指示。This walkthrough provides instruction for implementing an on-behalf-of (OBO) authentication using AD FS in Windows Server 2016 TP5. O 深入了解 OBO 驗證請朗讀適用於開發人員 AD FS 案例o learn more about OBO authentication please read AD FS Scenarios for Developers

警告:僅供教育是您可以在此組建的範例。WARNING: The example that you can build here is for educational purposes only. 這些指示僅適用於可能公開所需項目模式的最簡單、最小實作。These instructions are for the simplest, most minimal implementation possible to expose the required elements of the model. 範例可能不會包含錯誤處理的一切和其他相關的功能和聚焦只有在收到成功 OBO 驗證。The example may not include all aspects of error handling and other relate functionality and focuses ONLY on getting a successful OBO authentication.


在此範例中,我們將建立驗證流程位置 client 存取中間層 Web 服務和 web 服務則將會執行代表證取得存取預付碼。In this sample we will be creating an authentication flow where a client will be accessing a middle-tier Web Service and the web service will then act on behalf of the authenticated client to get an access token.


以下是範例達成驗證流程Below is the authentication flow that the sample will achieve

  1. Client 驗證,AD FS 授權結束點,並要求驗證碼Client authenticates to AD FS authorization end point and requests a authorization code
  2. 授權端點回到 client 的驗證碼Authorization endpoint returns authentication code to client
  3. Client 使用驗證碼,並將其給 AD FS 權杖端點要求存取權杖展示 WebAPI 為中間層 Web 服務Client uses authentication code and presents it to the AD FS token endpoint to request access token for Middle Tier Web Service as WebAPI
  4. AD FS 回到中型層 Web 服務的存取預付碼。AD FS returns the access token to Mid Tier Web Service. 需要存取端 WebAPI 中央層服務的額外功能,For additional functionality, Middle Tier Service needs to access to the Backend WebAPI
  5. Client 使用中央層服務使用存取預付碼。Client uses the access token to use Middle Tier service.
  6. 中央層服務提供 AD FS 權杖結束點存取預付碼和要求存取預付碼的端 WebAPI 開展工作的已驗證的使用者Middle Tier service provides the access token to the AD FS token end point and requests access token for Backend WebAPI on-behalf-of the authenticated user
  7. AD FS 回到端 WebAPI 存取權杖中央層服務 actiing client 為AD FS returns access token for backend WebAPI to Middle Tier Service actiing as client
  8. 中央層服務使用 AD FS 執行「步驟 7」中所提供的存取憑證存取端為 client WebAPI 並執行所需的功能Middle Tier Service uses the access token provided by AD FS in step 7 to access the backend WebAPI as client and perform the necessary functions

範例結構Sample Structure

範例會所組成的三個模組Sample will comprise of three modules

模組Module 描述Description
ToDoClientToDoClient 原生 client 與使用者互動Native client with which the user interacts
ToDoServiceToDoService 中間層 web 做為 client WebAPI 端的 APIMiddle Tier web API which acts as a client for the backend WebAPI
WebAPIOBOWebAPIOBO 端網頁,用來執行必要的作業時的使用者新增 ToDoItem ToDoService apiBackend web api that is used by ToDoService to perform the requisite operation when user adds a ToDoItem

開發方塊設定Setting up the development box

這個解說使用 Visual Studio 2015。This walk-through uses Visual Studio 2015. 專案經驗會使用 Active Directory 驗證媒體櫃 (ADAL)。The project heavily uses Active Directory Authentication Library (ADAL). 若要深入了解 ADAL 請朗讀Active Directory 驗證庫.NETTo learn about ADAL please read Active Directory Authentication Library .NET

也會使用 SQL LocalDB v11.0。The sample also uses SQL LocalDB v11.0. 安裝之前處理範例 SQL LocalDB。Install the SQL LocalDB prior to working on the sample.

設定環境Setting up the environment

我們將會使用的基本安裝:We will be working with a basic setup of:

  1. DC:網域控制站 AD FS 可裝載的網域DC: Domain controller for the domain in which AD FS will be hosted
  2. AD FS 伺服器: AD FS 伺服器的網域AD FS Server: The AD FS Server for the domain
  3. 開發電腦:電腦我們已安裝 Visual Studio,將會開發我們範例Development Machine: Machine where we have Visual Studio installed and will be developing our sample

您可以如果您想要使用只兩部電腦。You can, if you want, use only two machines. 另一個用於俠日 ADFS,另一個用於範例開發無障礙。One for DC/ADFS and the other for developing the sample.

如何設定的網域控制站和 AD FS 超出範圍的這篇文章。How to setup the domain controller and AD FS is beyond the scope of this article. 適用於其他部署的資訊查看:For additional deployment information see:

範例已依據針對 Azure Vittorio Bertocci 所建立的現有 OBO 範例也可以使用在此The sample is based on the existing OBO sample against Azure created by Vittorio Bertocci and available here. 請依照下列指示您開發電腦上的專案的複製和建立的範例,若要開始使用的複本。Follow the instructions to clone the project on your development machine and create a copy of the sample to start working with.

複製或下載這個存放庫Clone or download this repository

從命令列或殼層:From your shell or command line:

git clone https://github.com/Azure-Samples/active-directory-dotnet-webapi-onbehalfof.git

修改範例Modifying the sample

當您開放 WebAPI-OnBehalfOf-DotNet.sln 方案,您會注意到您有兩個專案中的方案As soon as you open the solution WebAPI-OnBehalfOf-DotNet.sln, you will notice that you have two projects in the solution -

  • ToDoListClient:這樣做為 OpenID client 的使用者會互動ToDoListClient: This will serve as the OpenID client which the user will be interacting with
  • ToDoListService:這會將中間層 web 伺服器上的應用程式] / [服務,將會與其他端 WebAPI OBO 互動驗證的使用者ToDoListService: This will be the middle-tier WebServer APP / Service that will be interacting with another backend WebAPI OBO the authenticated user

您可以看到時,我們需要新增另一個專案稍後將會做為中間層 ToDoListService 會存取資源。As you can see, we will need to add another project later which will act as the resource that will be accessed by the middle-tier ToDoListService.

AD FS 設定 Client 與 web 伺服器上的應用程式Configuring AD FS for the Client and WebServer App

在目前的形式的範例,是針對 Azure AD 設定驗證。In the current form of the sample, the authentication is configured to be done against Azure AD. 我們想要變更的驗證機制,直接向 AD FS 它部署場所上。We want to change the authentication mechanism and direct it towards AD FS deployed on-premises. 若要這樣做,我們需要設定辨識 client AD FS 與 web 伺服器上的應用程式我們在此範例中。In order to do so, we need to configure AD FS to recognize the client and WebServer App we have in the sample.

建立應用程式群組Creating an application group

打開 AD FS 管理 MMC,並加入新的應用程式群組。Open the AD FS management MMC and add a new application group. 選取 WebAPI-應用程式原生-範本。Select Native-Application-WebAPI template.


按一下 [下一步,您將會看到提供 Client 的應用程式的相關資訊的頁面。Click on Next and you will be presented with the page for providing information about Client App. 給 AD FS 應用程式 client 適當的名稱。Give an appropriate name to the client App in AD FS. 複製 client 識別碼,並儲存這將會需要 visual studio 中的應用程式設定中之後,您可以存取位置。Copy the client Identifier and save it somewhere you can access later as this will be required in the application config in visual studio.

注意:在該真的不是在原生戶端重新導向 URI 可以是任何任意 URINote: The Redirect URI can be any arbitrary URI as it is really not used in case of native clients


按 [下一步,您將會看到提供 WebAPI 的相關資訊的頁面。Click on Next and you will be presented with the page for providing information about WebAPI. 命名適合 AD FS 項目的的 WebAPI 並輸入您看到 Visual Studio 中 ToDoListService URI 重新導向 URIGive a suitable name for the AD FS entry for the WebAPI and enter the redirect URI as the URI you see in Visual Studio for the ToDoListService



按一下 [下一步,您將會看到 [選擇存取控制] 原則頁面。Click on Next and you will see the Choose Access Control Policy Page. 請確定您看到 [允許所有人] 原則一節中。Ensure you see "Permit everyone" in the Policy section.


按 [下一步,您將會看到的 [設定] 應用程式權限頁面。Click on Next and you will be presented with the configure Application Permissions page. 在這個頁面上,選取 [允許的範圍 openid(預設值,選取)和 user_impersonation。On this page, select the permitted scopes as openid (selected by default) and user_impersonation. 範圍 'user_impersonation' 是必要無法順利向 AD FS 要求開展工作的存取權的憑證。The scope 'user_impersonation' is necessary to be successfully able to request an on-behalf-of access token from AD FS.


旁邊就會顯示 [摘要] 頁面。Click next will display the summary page. 瀏覽精靈中的其餘部分,並完成設定。Go through the rest of the wizard and finish the configuration.

為了讓開展工作的驗證,我們需要確定 AD FS 傳回至 client 的範圍 user_impersonation 存取預付碼。In order to enable on-behalf-of authentication, we need to ensure that AD FS returns an access token with scope user_impersonation to the client. 修改為包含下列三種自訂規則 ToDoListServiceWebApi 宣告發行:Modify the claims issuance for ToDoListServiceWebApi to include the following three custom rules:

@RuleName = "All claims"
=> issue(claim = c);

@RuleName = "Issue open id scope"
=> issue(Type = "https://schemas.microsoft.com/identity/claims/scope", Value = "openid");

@RuleName = "Issue user_impersonation scope"
=> issue(Type = "https://schemas.microsoft.com/identity/claims/scope", Value = "user_impersonation");


新增 ToDoListService 為 client 應用程式群組中Adding ToDoListService as a client in the application group

在此階段我們需要中為 web 伺服器上的應用程式做為 client,而不只是資源 AD FS 進行其他項目。At this stage we need to make an additional entry in AD FS for the WebServer App to act as a client and not just as a resource. 打開應用程式群組您剛建立並按一下 [新增應用程式。Open the application group you just created and click on Add Application.


您會看到 [新增新的應用程式來 MySampleGroup] 頁面。You will be presented with the "Add a new application to MySampleGroup" page. 該頁面上,選取 [伺服器應用程式或網站」的獨立應用程式On that page, select "Server Application or Website" as the standalone application


按 [下一步,您將會看到提供應用程式的詳細資料頁面。Click Next and you will be presented with the page to provide application details. 提供設定中的項目名稱] 區段中適用的名稱。Provide a suitable name for the configuration entry in the Name section. 確保 Client 識別碼相同的 ToDoListServiceWebAPI idEnsure that the Client Identifier is same as the identifier for the ToDoListServiceWebAPI


按 [下一步,您將會看到與設定的應用程式認證頁面。Click on Next and you will be presented with the page to configure the application credentials. 按一下 [產生共用的密碼]。Click on "Generate a shared secret". 您會看到所自動密碼。You will be presented with a secret that is automatically generated. 這是必要時我們在 visual studio 設定 ToDoListService 複製某些位置的密碼。Copy the secret at some location as this will be required while we configure the ToDoListService in visual studio.


按 [下一步,完成精靈。Click on Next and complete the wizard.

修改 ToDoListClient 的程式碼Modifying the ToDoListClient code

修改應用程式設定Modify the Application Config

移至您在 ToDoListClient 專案中 WebAPI-OnBehalfOf-DotNet 方案。Go to your the ToDoListClient project in WebAPI-OnBehalfOf-DotNet solution. 打開 App.config 檔案,並進行下列修改Open the App.config file and make the following modifications

  • 加 ida:承租人金鑰的項目Comment the ida:Tenant key entry
  • 針對 ida: RedirectURI 輸入您在 AD FS 設定 MySampleGroup_ClientApplication 時所提供的任意 URI。For the ida:RedirectURI enter the arbitrary URI that you provided while configuring the MySampleGroup_ClientApplication in AD FS.
  • 對於 ida: ClientID 金鑰,提供 client ID 識別碼設定 MySampleGroup_ClientApplication 時,給 AD FS。For the ida:ClientID key, provide the client ID identifier that AD FS gave while configuring the MySampleGroup_ClientApplication.
  • 您的 ida: ToDoListResourceID 提供的資源 ID 提供 AD FS 中設定 ToDoListServiceWebApi 時For the ida:ToDoListResourceID provide the resource ID you gave while configuring the ToDoListServiceWebApi in AD FS
  • 主要 ida: AADInstance 意見Comment the key ida:AADInstance
  • 輸入 ida: ToDoListBaseAddress ToDoListServiceWebApi ID 資源。For the ida:ToDoListBaseAddress enter the resource ID of the ToDoListServiceWebApi. 這將會通話 ToDoList WebAPI 時使用。This will be used while calling the ToDoList WebAPI.
  • 新增 ida:授權金鑰,並提供 AD FS URI 值。Add a key ida:Authority and provide the value as the URI for AD FS.

和 appSettings中 App.Config 應該看起來像這樣:Your appSettings in App.Config should look similar to this:

<!--<add key="ida:Tenant" value="[Enter tenant name, e.g. contoso.onmicrosoft.com]" />-->
<add key="ida:ClientId" value="c7f7b85c-497c-4589-877f-b17a0bd13398" />
<add key="ida:RedirectUri" value="https://arbitraryuri.com/" />
<add key="ida:TodoListResourceId" value="https://localhost:44321/" />
<!--<add key="ida:AADInstance" value="https://login.microsoftonline.com/{0}" />-->
<add key="ida:TodoListBaseAddress" value="https://localhost:44321" />
<add key="ida:Authority" value="https://fs.anandmsft.com/adfs/"/>

修改程式碼Modifying the code


加行朗讀承租人資訊的應用程式設定Comment the line reading the tenant information from the application config

//private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
//private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];

將值字串的權限的變更Change the value of string authority to

private static string authority = ConfigurationManager.AppSettings["ida:Authority"];

若要朗讀 ToDoListResourceId 和 ToDoListBaseAddress 正確的值的程式碼變更Change the code to read correct values of ToDoListResourceId and ToDoListBaseAddress

private static string todoListResourceId = ConfigurationManager.AppSettings["ida:TodoListResourceId"];
private static string todoListBaseAddress = ConfigurationManager.AppSettings["ida:TodoListBaseAddress"];

在 [函式 MainWindow() 變更 authcontext 初始化為:In the function MainWindow() change the authcontext initialization as:

authContext = new AuthenticationContext(authority, false);

新增端資源Adding the backend resource

您必須完成開展工作的流程,才能建立端資源將會存取 ToDoListService 開展工作的已驗證的使用者。In order to complete the on-behalf-of flow, you need to create a backend resource that the ToDoListService will be accessing on-behalf-of the authenticated user. 選擇端資源會依需求,但針對此範例中,您可以建立基本的 WebAPI。The choice of the backend resource can vary as per the requirement, but for the purpose of this sample you can create a basic WebAPI.

  • 方案 ' WebAPI-OnBehalfOf-DotNet' 方案檔案總管中按一下滑鼠右鍵,選取 [新增]-> [新增專案Right click on solution 'WebAPI-OnBehalfOf-DotNet' in the solution explorer and select Add -> New Project
  • 選擇 ASP.NET Web 應用程式範本Choose ASP.NET Web Application template


  • 在下一步提示,按一下 [' 變更驗證]On the next prompt click on 'Change Authentication'
  • 選取 [工作和學校帳號],然後選取 [上正確下拉式清單的 [' 先 'Select 'Work and School Accounts' and on the right drop down list select 'On-Premises'
  • 輸入您的部署 AD FS federationmetadata.xml 路徑,並提供的應用程式 URI(提供任何 URI 現在,以及您將會在稍後變更),按一下 [新增專案方案確定。Enter the federationmetadata.xml path for your AD FS deployment and provide an App URI (provide any URI for now, and you will change it later) and click Ok to add the project to the solution.


  • 按一下滑鼠右鍵在控制器上建立的新專案在總管] 中。Right click on Controllers in the solution explorer under the new project created. 選取 [新增]-> [控制器Select Add -> Controller
  • 選取範本,選取 ['Web API 2 控制器-空白',按一下 [確定]。In the template selection, select 'Web API 2 Controller - Empty' and click Ok.


  • 命名適當的控制器Give appropriate controller name


  • 在控制器中新增下列程式碼Add the following code in the controller
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    namespace WebAPIOBO.Controllers
        public class WebAPIOBOController : ApiController
            public IHttpActionResult Get()
                return Ok("WebAPI via OBO");

任何人的 WebAPI WebAPIOBO 放取得要求時,此驗證碼只會傳回字串This code will simply return the string when anyone puts a Get request for the WebAPI WebAPIOBO

AD FS 以新增新的端 WebAPIAdding the new backend WebAPI to AD FS

打開 MySampleGroup 應用程式群組。Open the MySampleGroup application group. 按一下 [新增應用程式,選取 Web API 範本,按一下 [下一步]Click on Add application and select Web API template and click on Next.


在 [設定網路 API 頁面上提供 WebAPI 項目以及適當的名稱。On the Configure Web API page provide an appropriate name for the WebAPI entry and the identifier. 在 visual studio(類似於我們針對 BackendWebAPIAdfsAdd)識別碼應該 WebAPIOBO 專案的值 SSL URL。The identifier should be the value SSL URL from WebAPIOBO project in visual studio (similar to what we did for BackendWebAPIAdfsAdd).



請繼續透過精靈中的其餘部分相同為我們設定 ToDoListService WebAPI 時。Continue through the rest of the wizard same as when we configured the ToDoListService WebAPI. 結尾您的應用程式群組應該的外觀如下:At the end your application group should look like below:


修改 ToDoListService 的程式碼Modifying the ToDoListService code

修改應用程式設定Modifying the application config

  • 打開 web.configOpen the Web.config file
  • 修改下鍵Modify the following keys
Key 值。Value
對象 ida:ida:Audience 為您提供給 AD FS 設定 ToDoListService WebAPI,例如時 https://localhost:44321/ ToDoListService 的來電顯示ID of the ToDoListService as given to AD FS while configuring the ToDoListService WebAPI, for example, https://localhost:44321/
ida: ClientIDida:ClientID 為您提供給 AD FS 設定 ToDoListService WebAPI,例如時 https://localhost:44321/ ToDoListService 的來電顯示ID of the ToDoListService as given to AD FS while configuring the ToDoListService WebAPI, for example, https://localhost:44321/
請務必 ida: ClientID 與 ida:對象符合彼此It is very important that the ida:Audience and ida:ClientID match each other
ida: ClientSecretida:ClientSecret 這是 AD FS 產生當您已設定 ToDoListService client AD FS 中的密碼This is the secret that AD FS generated when you were configuring the ToDoListService client in AD FS
ida: ADFSMetadataida:ADFSMetadata 這是您 AD FS 的中繼資料,例如 https://fs.anandmsft.com/federationmetadata/2007-06/federationmetadata.xml URLThis is the URL to your AD FS metadata, for e.g. https://fs.anandmsft.com/federationmetadata/2007-06/federationmetadata.xml
ida: OBOWebAPIBaseida:OBOWebAPIBase 這是我們用來呼叫端的 API,例如 https://localhost:44300 的基底地址This is the base address that we will use to call the backend API, for e.g. https://localhost:44300
授權單位 ida:ida:Authority 這是您 AD FS 服務,https://fs.anandmsft.com/adfs/ 的範例 URLThis is the URL for your AD FS service, example https://fs.anandmsft.com/adfs/

所有其他 ida: XXXXXXX 鍵在 [和 appsettings節點可以略過或刪除All other ida:XXXXXXX keys in the appsettings node can be commented out or deleted

Azure AD 來 AD FS 從變更驗證Change authentication from Azure AD to AD FS

  • 打開 Startup.Auth.cs 檔案Open the file Startup.Auth.cs
  • 移除下列程式碼Remove the following code

          new WindowsAzureActiveDirectoryBearerAuthenticationOptions
              Audience = ConfigurationManager.AppSettings["ida:Audience"],
              Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
              TokenValidationParameters = new TokenValidationParameters{ SaveSigninToken = true }


        new ActiveDirectoryFederationServicesBearerAuthenticationOptions
            MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
            TokenValidationParameters = new TokenValidationParameters()
                SaveSigninToken = true,
                ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]

修改 ToDoListControllerModifying the ToDoListController

加入 System.Web 參考。擴充功能。Add reference to System.Web.Extensions. 更換下列程式碼來修改課程成員Modify the class members by replacing the code below

// The Client ID is used by the application to uniquely identify itself to Azure AD.
// The App Key is a credential used by the application to authenticate to Azure AD.
// The Tenant is the name of the Azure AD tenant in which this application is registered.
// The AAD Instance is the instance of Azure, for example public Azure or Azure China.
// The Authority is the sign-in URL of the tenant.
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string appKey = ConfigurationManager.AppSettings["ida:AppKey"];

// To authenticate to the Graph API, the app needs to know the Grah API's App ID URI.
// To contact the Me endpoint on the Graph API we need the URL as well.
private static string graphResourceId = ConfigurationManager.AppSettings["ida:GraphResourceId"];
private static string graphUserUrl = ConfigurationManager.AppSettings["ida:GraphUserUrl"];
private const string TenantIdClaimType = "https://schemas.microsoft.com/identity/claims/tenantid";


// The Client ID is used by the application to uniquely identify itself to Azure AD.
// The client secret is the credentials for the WebServer Client

private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"];
private static string authority = ConfigurationManager.AppSettings["ida:Authority"];

// Base address of the WebAPI
private static string OBOWebAPIBase = ConfigurationManager.AppSettings["ida:OBOWebAPIBase"];

修改用於名稱宣告Modify the claim used for Name

我們從 AD FS 發行 Nmae 理賠要求,但是我們不發行 NameIdentifier 理賠要求。From AD FS we are issuing the Nmae claim but we are not issuing NameIdentifier claim. 範例使用 NameIdentifier 唯一 ToDo 項目] 中的金鑰。The sample uses NameIdentifier to uniquely key in the ToDo items. 為了簡化,您可以放心密碼移除 NameIdentifier 與名稱宣告。For simplicity, you can safely remove the NameIdentifier with Name claim in the code. 尋找和所有場次 NameIdentifier 都取代名稱。Find and replace all occurences of NameIdentifier wiht Name.

修改 CallGraphAPIOnBehalfOfUser() 文章程序Modify Post routine and CallGraphAPIOnBehalfOfUser()

複製和貼上 ToDoListController.cs 下列程式碼的文章與 CallGraphAPIOnBehalfOfUser 取代的程式碼Copy and paste the code below in ToDoListController.cs and replace the code for Post and CallGraphAPIOnBehalfOfUser

// POST api/todolist
public async Task Post(TodoItem todo)
    if (!ClaimsPrincipal.Current.FindFirst("https://schemas.microsoft.com/identity/claims/scope").Value.Contains("user_impersonation"))
        throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.Unauthorized, ReasonPhrase = "The Scope claim does not contain 'user_impersonation' or scope claim not found" });

    // Call the WebAPIOBO On Behalf Of the user who called the To Do list web API.
    string augmentedTitle = null;
    string custommessage = await CallGraphAPIOnBehalfOfUser();
    if (custommessage != null)
        augmentedTitle = String.Format("{0}, Message: {1}", todo.Title, custommessage);
        augmentedTitle = todo.Title;

    if (null != todo && !string.IsNullOrWhiteSpace(todo.Title))
        db.TodoItems.Add(new TodoItem { Title = augmentedTitle, Owner = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Name).Value });

public static async Task<string> CallGraphAPIOnBehalfOfUser()
    string accessToken = null;
    AuthenticationResult result = null;
    AuthenticationContext authContext = null;
    HttpClient httpClient = new HttpClient();
    string custommessage = "";

    // Use ADAL to get a token On Behalf Of the current user.  To do this we will need:
    //      The Resource ID of the service we want to call.
    //      The current user's access token, from the current request's authorization header.
    //      The credentials of this application.
    //      The username (UPN or email) of the user calling the API
    ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
    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);

    string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Name).Value;
    authContext = new AuthenticationContext(authority, false);

    // In the case of a transient error, retry once after 1 second, then abandon.
    // Retrying is optional.  It may be better, for your application, to return an error immediately to the user and have the user initiate the retry.
    bool retry = false;
    int retryCount = 0;

        retry = false;
            result = authContext.AcquireToken(OBOWebAPIBase, clientCred, userAssertion);
            accessToken = result.AccessToken;
        catch (AdalException ex)
            if (ex.ErrorCode == "temporarily_unavailable")
                // Transient error, OK to retry.
                retry = true;
    } while ((retry == true) && (retryCount < 1));

    if (accessToken == null)
        // An unexpected error occurred.
        return (null);

    // Once the token has been returned by ADAL, add it to the http authorization header, before making the call to access the To Do list service.
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);

    // Call the WebAPIOBO.
    HttpResponseMessage response = await httpClient.GetAsync(OBOWebAPIBase + "/api/WebAPIOBO");

    if (response.IsSuccessStatusCode)
        // Read the response and databind to the GridView to display To Do items.
        string s = await response.Content.ReadAsStringAsync();
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        custommessage = serializer.Deserialize<string>(s);
        return custommessage;
        custommessage = "Unsuccessful OBO operation : " + response.ReasonPhrase;
    // An unexpected error occurred calling the Graph API.  Return a null profile.
    return (null);

執行方案Running the solution

Visual studio 預設設定來執行一個專案,當您遇到執行偵錯。By default visual studio is configured to run one project when you hit debug to run.

  • 以滑鼠右鍵按一下方案,然後選取 [屬性。Right click on the solution and select properties.
  • 屬性網頁中選取多個開機專案及變更動作到開始畫面的所有的三個項目。In the properties page select Multiple Startup projects and change the Action to start for all three entries.


F5 並執行方案Hit F5 and execute the solution


按一下 [登入] 按鈕。Click on the sign-in button. 將會提示您登入使用 AD FSYou will be prompted to sign-in using AD FS


在您登入,新增 ToDo 項目清單中。After you sign-in, add a ToDo item in the list. 我們會想要的進一步即可張貼到 WebAPIOBO web API ToDoListService 文章作業幕後的細節。Behind the scenes we are going to do a Post operation to the ToDoListService which further will do a Post to the WebAPIOBO web API.


在順利運作,您會看到的項目已新增至其他訊息清單後端使用 OBO 驗證流程已存取網路 API。On successful operation you will see that the item has been added to the list with the additional message from the backend Web API which was accessed using OBO auth-flow.


您也可以查看詳細的追蹤 Fiddler 上。You can also see the detailed traces on Fiddler. 上市 Fiddler 以及 HTTPS 解密。Launch Fiddler and enable HTTPS decryption. 您可以看到我們對 /adfs/oautincludes 端點的兩個要求。You can see that we make two requests to the /adfs/oautincludes endpoint. 中的第一個互動,我們提供權杖端點存取程式碼,並取得 https://localhost:44321/ 權杖存取![AD FS OBOIn the first interaction, we present the access code to the token endpoint and get an access token for https://localhost:44321/ AD FS OBO</span></span>

在第二個權杖端點互動,您可以看到我們已經requested_token_use設定為on_behalf_of,並使用存取權杖取得中間層 web 服務,亦即 https://localhost:44321/ 為宣告,來取得開展工作的預付碼。In the second interaction with the token endpoint, you can see that we have requested_token_use set as on_behalf_of and we are using the access token obtained for the middle-tier web service, i.e. https://localhost:44321/ as the assertion to obtain the on-behalf-of token. AD FS OBO

後續步驟Next Steps

AD FS 開發AD FS Development