Anda telah membangun objek aplikasi klien Anda. Sekarang, Anda menggunakannya untuk memperoleh token untuk memanggil API web. Pada ASP.NET atau ASP.NET Core, memanggil API web dilakukan di pengontrol:
Microsoft.Identity.Web menambahkan metode ekstensi yang menyediakan layanan kemudahan untuk memanggil Microsoft Graph atau API web downstream. Metode ini dijelaskan secara terperinci di Aplikasi web yang memanggil API web: Panggil API. Dengan metode pembantu ini, Anda tidak perlu memperoleh token secara manual.
Namun, jika Anda ingin memperoleh token secara manual, kode berikut menunjukkan contoh penggunaan Microsoft.Identity.Web untuk melakukannya di pengontrol rumah. Ini memanggil Microsoft Graph menggunakan REST API (bukan Microsoft Graph SDK). Biasanya, Anda tidak perlu mendapatkan token, Anda perlu membuat header Otorisasi yang Anda tambahkan ke permintaan Anda. Untuk mendapatkan header otorisasi, Anda menyuntikkan IAuthorizationHeaderProvider
layanan dengan injeksi dependensi di konstruktor pengontrol Anda (atau konstruktor halaman Anda jika Anda menggunakan Blazor), dan Anda menggunakannya dalam tindakan pengontrol Anda. Antarmuka ini memiliki metode yang menghasilkan string yang berisi protokol (Pembawa, Pop, ...) dan token. Untuk mendapatkan header otorisasi untuk memanggil API atas nama pengguna, gunakan (CreateAuthorizationHeaderForUserAsync
). Untuk mendapatkan header otorisasi untuk memanggil API hilir atas nama aplikasi itu sendiri, dalam skenario daemon, gunakan (CreateAuthorizationHeaderForAppAsync
).
Metode pengontrol dilindungi oleh atribut [Authorize]
yang memastikan hanya pengguna terautentikasi yang dapat menggunakan aplikasi web.
[Authorize]
public class HomeController : Controller
{
readonly IAuthorizationHeaderProvider authorizationHeaderProvider;
public HomeController(IAuthorizationHeaderProvider authorizationHeaderProvider)
{
this.authorizationHeaderProvider = authorizationHeaderProvider;
}
// Code for the controller actions (see code below)
}
ASP.NET Core IAuthorizationHeaderProvider
tersedia dengan injeksi dependensi.
Berikut ini adalah kode yang disederhanakan untuk tindakan HomeController
, yang mendapat token untuk memanggil Microsoft Graph:
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Acquire the access token.
string[] scopes = new string[]{"user.read"};
string accessToken = await authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", accessToken);
string json = await client.GetStringAsync(url);
}
Untuk lebih memahami kode yang diperlukan untuk skenario ini, lihat langkah fase 2 (2-1-Web app Calls Microsoft Graph) dari tutorial ms-identity-aspnetcore-webapp-tutorial.
Atribut AuthorizeForScopes
di atas tindakan pengontrol (atau halaman Razor jika Anda menggunakan templat Razor) disediakan oleh Microsoft.Identity.Web. Ini memastikan bahwa pengguna dimintai persetujuan jika diperlukan, dan secara bertahap.
Ada variasi kompleks lainnya, seperti:
- Memanggil beberapa API.
- Memproses persetujuan inkremental dan Akses Bersyar.
Langkah-langkah lanjutan ini dibahas dalam bab 3 dari tutorial 3-WebApp-multi-API.
Kode untuk ASP.NET mirip dengan kode yang ditampilkan untuk ASP.NET Core:
- Tindakan pengontrol, yang dilindungi oleh
[Authorize]
atribut, mengekstrak ID penyewa dan ID pengguna anggota ClaimsPrincipal
pengontrol (ASP.NET menggunakan HttpContext.User
). Ini memastikan bahwa hanya pengguna yang diautentikasi yang dapat menggunakan aplikasi.
Microsoft.Identity.Web menambahkan metode ekstensi ke Pengontrol yang menyediakan layanan kenyamanan untuk memanggil Microsoft Graph atau API web hilir, atau untuk mendapatkan header otorisasi, atau bahkan token. Metode yang digunakan untuk memanggil API secara langsung dijelaskan secara rinci di aplikasi web yang memanggil API web: Memanggil API. Dengan metode pembantu ini, Anda tidak perlu memperoleh token secara manual.
Namun, jika Anda ingin memperoleh token atau membangun header otorisasi secara manual, kode berikut menunjukkan cara menggunakan Microsoft.Identity.Web untuk melakukannya di pengontrol. Ini memanggil API (Microsoft Graph) menggunakan REST API alih-alih Microsoft Graph SDK.
Untuk mendapatkan header otorisasi, Anda mendapatkan IAuthorizationHeaderProvider
layanan dari pengontrol menggunakan metode GetAuthorizationHeaderProvider
ekstensi . Untuk mendapatkan header otorisasi untuk memanggil API atas nama pengguna, gunakan CreateAuthorizationHeaderForUserAsync
. Untuk mendapatkan header otorisasi untuk memanggil API hilir atas nama aplikasi itu sendiri, dalam skenario daemon, gunakan CreateAuthorizationHeaderForAppAsync
.
Cuplikan berikut menunjukkan tindakan HomeController
, yang mendapatkan header otorisasi untuk memanggil Microsoft Graph sebagai REST API:
[Authorize]
public class HomeController : 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);
}
}
Cuplikan berikut menunjukkan tindakan HomeController
, yang mendapatkan token akses untuk memanggil Microsoft Graph sebagai 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 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);
}
}
Dalam sampel Java, kode yang memanggil API ada dalam getUsersFromGraph
metode di AuthPageController.java#L62.
Metode ini mencoba memanggil getAuthResultBySilentFlow
. Jika pengguna perlu menyetujui lebih banyak cakupan, kode memproses objek MsalInteractionRequiredException
untuk menantang pengguna.
@RequestMapping("/msal4jsample/graph/me")
public ModelAndView getUserFromGraph(HttpServletRequest httpRequest, HttpServletResponse response)
throws Throwable {
IAuthenticationResult result;
ModelAndView mav;
try {
result = authHelper.getAuthResultBySilentFlow(httpRequest, response);
} catch (ExecutionException e) {
if (e.getCause() instanceof MsalInteractionRequiredException) {
// If the silent call returns MsalInteractionRequired, redirect to authorization endpoint
// so user can consent to new scopes.
String state = UUID.randomUUID().toString();
String nonce = UUID.randomUUID().toString();
SessionManagementHelper.storeStateAndNonceInSession(httpRequest.getSession(), state, nonce);
String authorizationCodeUrl = authHelper.getAuthorizationCodeUrl(
httpRequest.getParameter("claims"),
"User.Read",
authHelper.getRedirectUriGraph(),
state,
nonce);
return new ModelAndView("redirect:" + authorizationCodeUrl);
} else {
mav = new ModelAndView("error");
mav.addObject("error", e);
return mav;
}
}
if (result == null) {
mav = new ModelAndView("error");
mav.addObject("error", new Exception("AuthenticationResult not found in session."));
} else {
mav = new ModelAndView("auth_page");
setAccountInfo(mav, httpRequest);
try {
mav.addObject("userInfo", getUserInfoFromGraph(result.accessToken()));
return mav;
} catch (Exception e) {
mav = new ModelAndView("error");
mav.addObject("error", e);
}
}
return mav;
}
// Code omitted here
Dalam sampel Node.js, kode yang memperoleh token berada dalam acquireToken
metode AuthProvider
kelas .
acquireToken(options = {}) {
return async (req, res, next) => {
try {
const msalInstance = this.getMsalInstance(this.msalConfig);
/**
* If a token cache exists in the session, deserialize it and set it as the
* cache for the new MSAL CCA instance. For more, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
*/
if (req.session.tokenCache) {
msalInstance.getTokenCache().deserialize(req.session.tokenCache);
}
const tokenResponse = await msalInstance.acquireTokenSilent({
account: req.session.account,
scopes: options.scopes || [],
});
/**
* On successful token acquisition, write the updated token
* cache back to the session. For more, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
*/
req.session.tokenCache = msalInstance.getTokenCache().serialize();
req.session.accessToken = tokenResponse.accessToken;
req.session.idToken = tokenResponse.idToken;
req.session.account = tokenResponse.account;
res.redirect(options.successRedirect);
} catch (error) {
if (error instanceof msal.InteractionRequiredAuthError) {
return this.login({
scopes: options.scopes || [],
redirectUri: options.redirectUri,
successRedirect: options.successRedirect || '/',
})(req, res, next);
}
next(error);
}
};
}
Token akses ini kemudian digunakan untuk menangani permintaan ke /profile
titik akhir:
router.get('/profile',
isAuthenticated, // check if user is authenticated
async function (req, res, next) {
try {
const graphResponse = await fetch(GRAPH_ME_ENDPOINT, req.session.accessToken);
res.render('profile', { profile: graphResponse });
} catch (error) {
next(error);
}
}
);
Dalam sampel Python, kode yang memanggil API berada dalam app.py.
Kode ini mencoba mendapat token dari cache token. Jika tidak bisa mendapatkan token, token akan mengalihkan pengguna ke rute masuk. Jika tidak, api dapat dilanjutkan untuk memanggil API.
@app.route("/call_downstream_api")
def call_downstream_api():
token = auth.get_token_for_user(app_config.SCOPE)
if "error" in token:
return redirect(url_for("login"))
# Use access token to call downstream api
api_result = requests.get(
app_config.ENDPOINT,
headers={'Authorization': 'Bearer ' + token['access_token']},
timeout=30,
).json()
return render_template('display.html', result=api_result)