Microsoft.Identity.Web 新增擴充方法,以提供方便服務來呼叫 Microsoft Graph 或下游 Web API。 這些方法會在呼叫 Web API 的 Web 應用程式中詳細說明 :呼叫 API。 使用這些協助程式方法,您不需要手動取得令牌。
不過,如果您確實想要手動取得令牌,下列程式代碼會顯示在 主控制器中使用 Microsoft.Identity.Web 來執行此動作的範例。 它會使用 REST API 呼叫 Microsoft Graph(而不是 Microsoft Graph SDK)。 通常,您不需要取得令牌,您必須建置您新增至要求的授權標頭。 若要取得授權標頭,您可以在 IAuthorizationHeaderProvider
控制器的建構函式中插入相依性插入服務(或使用 Blazor 時的頁面建構函式),並在控制器動作中使用。 這個介面有方法可產生包含通訊協定的字串(Bearer、Pop、...) 和令牌。 若要取得代表使用者呼叫 API 的授權標頭,請使用 (CreateAuthorizationHeaderForUserAsync
)。 若要取得授權標頭來代表應用程式本身呼叫下游 API,請在精靈案例中使用 (CreateAuthorizationHeaderForAppAsync
)。
控制器方法會受到 [Authorize]
屬性的保護,該屬性可確保只有已驗證的呼叫可以使用 Web API。
[Authorize]
public class MyApiController : Controller
{
/// <summary>
/// The web API will accept only tokens 1) for users, 2) that have the `access_as_user` scope for
/// this API.
/// </summary>
static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };
static readonly string[] scopesToAccessDownstreamApi = new string[] { "api://MyTodolistService/access_as_user" };
readonly IAuthorizationHeaderProvider authorizationHeaderProvider;
public MyApiController(IAuthorizationHeaderProvider authorizationHeaderProvider)
{
this.authorizationHeaderProvider = authorizationHeaderProvider;
}
[RequiredScopes(Scopes = scopesToAccessDownstreamApi)]
public IActionResult Index()
{
// Get an authorization header.
IAuthorizationHeaderProvider authorizationHeaderProvider = this.GetAuthorizationHeaderProvider();
string[] scopes = new string[]{"user.read"};
string authorizationHeader = await authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(scopes);
return await callTodoListService(authorizationHeader);
}
}
如需方法 callTodoListService
的詳細資訊,請參閱 呼叫Web API的Web API:呼叫 API。
ASP.NET 的程式代碼類似於 ASP.NET Core 所示的程式代碼:
- 受 [Authorize] 屬性保護的控制器動作會擷取控制器成員的租用戶標識碼和使用者識別碼
ClaimsPrincipal
。 (ASP.NET 使用 HttpContext.User
。) Microsoft.Identity.Web.OWIN 會將擴充方法新增至控制器,以提供方便的服務來呼叫 Microsoft Graph 或下游 Web API,或取得授權標頭,甚至是令牌。 在呼叫 Web API 的 Web 應用程式中,會詳細說明 用來直接呼叫 API 的方法:呼叫 API。 使用這些協助程式方法,您不需要手動取得令牌。
不過,如果您確實想要手動取得令牌或建置授權標頭,下列程式代碼會示範如何在控制器中使用 Microsoft.Identity.Web 來執行此動作。 它會使用 REST API 來呼叫 API(Microsoft Graph),而不是 Microsoft Graph SDK。
若要取得授權標頭,您可以使用擴充方法GetAuthorizationHeaderProvider
從控制器取得IAuthorizationHeaderProvider
服務。 若要取得代表使用者呼叫 API 的授權標頭,請使用 (CreateAuthorizationHeaderForUserAsync
)。 若要取得授權標頭來代表應用程式本身呼叫下游 API,請在精靈案例中使用 (CreateAuthorizationHeaderForAppAsync
)。
控制器方法受到 [Authorize]
屬性的保護,該屬性可確保只有已驗證的使用者可以使用 Web 應用程式。
下列代碼段顯示 的 HomeController
動作,此動作會取得授權標頭,以呼叫 Microsoft Graph 作為 REST API:
[Authorize]
public class MyApiController : Controller
{
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Get an authorization header.
IAuthorizationHeaderProvider authorizationHeaderProvider = this.GetAuthorizationHeaderProvider();
string[] scopes = new string[]{"user.read"};
string authorizationHeader = await authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
string json = await client.GetStringAsync(url);
}
}
下列代碼段顯示 的 MyApiController
動作,此動作會取得存取令牌,以呼叫 Microsoft Graph 作為 REST API:
[Authorize]
public class HomeController : Controller
{
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Get an authorization header.
ITokenAcquirer tokenAcquirer = TokenAcquirerFactory.GetDefaultInstance().GetTokenAcquirer();
string[] scopes = new string[]{"user.read"};
string token = await await tokenAcquirer.GetTokenForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
string json = await client.GetStringAsync(url);
}
}
以下是 API 控制器動作中呼叫的程式代碼範例。 它會呼叫下游 API - Microsoft Graph。
@RestController
public class ApiController {
@Autowired
MsalAuthHelper msalAuthHelper;
@RequestMapping("/graphMeApi")
public String graphMeApi() throws MalformedURLException {
String oboAccessToken = msalAuthHelper.getOboToken("https://graph.microsoft.com/.default");
return callMicrosoftGraphMeEndpoint(oboAccessToken);
}
}
Python Web API 需要使用中間件來驗證從用戶端收到的持有人令牌。 接著,Web API 可以使用 MSAL Python 連結庫來取得下游 API 的存取令牌,方法是呼叫 acquire_token_on_behalf_of
方法。
以下是使用 acquire_token_on_behalf_of
方法和 Flask 架構取得存取令牌的程式代碼範例。 它會呼叫下游 API - Azure 管理訂用帳戶端點。
def get(self):
_scopes = ["https://management.azure.com/user_impersonation"]
_azure_management_subscriptions_uri = "https://management.azure.com/subscriptions?api-version=2020-01-01"
current_access_token = request.headers.get("Authorization", None)
#This example only uses the default memory token cache and should not be used for production
msal_client = msal.ConfidentialClientApplication(
client_id=os.environ.get("CLIENT_ID"),
authority=os.environ.get("AUTHORITY"),
client_credential=os.environ.get("CLIENT_SECRET"))
#acquire token on behalf of the user that called this API
arm_resource_access_token = msal_client.acquire_token_on_behalf_of(
user_assertion=current_access_token.split(' ')[1],
scopes=_scopes
)
headers = {'Authorization': arm_resource_access_token['token_type'] + ' ' + arm_resource_access_token['access_token']}
subscriptions_list = req.get(_azure_management_subscriptions_uri), headers=headers).json()
return jsonify(subscriptions_list)
(進階)從背景應用程式、API 和服務存取登入使用者的令牌快取
您可以使用 MSAL 的令牌快取實作,允許背景應用程式、API 和服務使用存取令牌快取繼續代表使用者不在時採取行動。 如果背景應用程式和服務在用戶結束前端 Web 應用程式之後,必須繼續代表使用者工作,則這樣做特別有用。
現今,大部分的背景進程在需要與用戶的數據搭配使用時,會使用 應用程式許可權 ,而不需要他們存在即可進行驗證或重新驗證。 因為應用程式許可權通常需要系統管理員同意,這需要提高許可權,因此開發人員不想取得使用者原本同意其應用程式的許可權,因此遇到不必要的摩擦。
GitHub 上的此程式碼範例示範如何透過從背景應用程式存取 MSAL 的令牌快取來避免這種不必要的摩擦:
從背景應用程式、API 和服務存取登入使用者的令牌快取