In ASP.NET Core, per le applicazioni Microsoft Identity Platform, il pulsante Accedi viene esposto in Views\Shared\_LoginPartial.cshtml (per un'app MVC) o Pages\Shared\_LoginPartial.cshtm (per un'app Razor). Viene visualizzato solo quando l'utente non è autenticato. Ovvero, viene visualizzato quando l'utente non ha ancora eseguito l'accesso o si è disconnesso. Al contrario, il pulsante Disconnetti viene visualizzato quando l'utente è già connesso. Si noti che il controller account è definito nel pacchetto NuGet Microsoft.Identity.Web.UI, nell'area denominata MicrosoftIdentity
In ASP.NET MVC il pulsante Accedi viene esposto in Views\Shared\_LoginPartial.cshtml. Viene visualizzato solo quando l'utente non è autenticato. Ovvero, viene visualizzato quando l'utente non ha ancora eseguito l'accesso o si è disconnesso.
Quando un utente non autenticato visita la home page, la route index in app.py reindirizza l'utente alla route login.
@app.route("/")
def index():
if not (app.config["CLIENT_ID"] and app.config["CLIENT_SECRET"]):
# This check is not strictly necessary.
# You can remove this check from your production code.
return render_template('config_error.html')
if not auth.get_user():
return redirect(url_for("login"))
return render_template('index.html', user=auth.get_user(), version=identity.__version__)
La route login individua il modello appropriato auth_uri ed esegue il rendering del modello login.html.
@app.route("/login")
def login():
return render_template("login.html", version=identity.__version__, **auth.log_in(
scopes=app_config.SCOPE, # Have user consent to scopes during log-in
redirect_uri=url_for("auth_response", _external=True), # Optional. If present, this absolute URL must match your app's redirect_uri registered in Azure Portal
))
In ASP.NET la selezione del pulsante Accedi nell'app Web attiva l'azione SignIn nel controller AccountController. Nelle versioni precedenti dei modelli ASP.NET Core, il controller Account è stato incorporato con l'app Web. Questo non è più il caso perché il controller fa ora parte del pacchetto NuGet Microsoft.Identity.Web.UI. Per informazioni dettagliate, vedere AccountController.cs.
Questo controller gestisce anche le applicazioni Azure AD B2C.
In ASP.NET l'accesso viene attivato dal metodo SignIn() in un controller (ad esempio AccountController.cs#L16-L23). Questo metodo non fa parte di .NET Framework (contrariamente a ciò che accade in ASP.NET Core). Invia un test di accesso OpenID dopo aver proposto un URI di reindirizzamento.
public void SignIn()
{
// Send an OpenID Connect sign-in request.
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
In Java la disconnessione viene gestita chiamando direttamente l'endpoint logout di Microsoft Identity Platform e fornendo il valore post_logout_redirect_uri. Per informazioni dettagliate, vedere AuthPageController.java#L30-L48.
@Controller
public class AuthPageController {
@Autowired
AuthHelper authHelper;
@RequestMapping("/msal4jsample")
public String homepage(){
return "index";
}
@RequestMapping("/msal4jsample/secure/aad")
public ModelAndView securePage(HttpServletRequest httpRequest) throws ParseException {
ModelAndView mav = new ModelAndView("auth_page");
setAccountInfo(mav, httpRequest);
return mav;
}
// More code omitted for simplicity
Quando l'utente seleziona il link Accedi, che attiva la route /auth/signin, il controller di accesso assume il controllo per autenticare l'utente con Microsoft Identity Platform.
login(options = {}) {
return async (req, res, next) => {
/**
* MSAL Node library allows you to pass your custom state as state parameter in the Request object.
* The state parameter can also be used to encode information of the app's state before redirect.
* You can pass the user's state in the app, such as the page or view they were on, as input to this parameter.
*/
const state = this.cryptoProvider.base64Encode(
JSON.stringify({
successRedirect: options.successRedirect || '/',
})
);
const authCodeUrlRequestParams = {
state: state,
/**
* By default, MSAL Node will add OIDC scopes to the auth code url request. For more information, visit:
* https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
*/
scopes: options.scopes || [],
redirectUri: options.redirectUri,
};
const authCodeRequestParams = {
state: state,
/**
* By default, MSAL Node will add OIDC scopes to the auth code request. For more information, visit:
* https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
*/
scopes: options.scopes || [],
redirectUri: options.redirectUri,
};
/**
* If the current msal configuration does not have cloudDiscoveryMetadata or authorityMetadata, we will
* make a request to the relevant endpoints to retrieve the metadata. This allows MSAL to avoid making
* metadata discovery calls, thereby improving performance of token acquisition process. For more, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/performance.md
*/
if (!this.msalConfig.auth.cloudDiscoveryMetadata || !this.msalConfig.auth.authorityMetadata) {
const [cloudDiscoveryMetadata, authorityMetadata] = await Promise.all([
this.getCloudDiscoveryMetadata(this.msalConfig.auth.authority),
this.getAuthorityMetadata(this.msalConfig.auth.authority)
]);
this.msalConfig.auth.cloudDiscoveryMetadata = JSON.stringify(cloudDiscoveryMetadata);
this.msalConfig.auth.authorityMetadata = JSON.stringify(authorityMetadata);
}
const msalInstance = this.getMsalInstance(this.msalConfig);
// trigger the first leg of auth code flow
return this.redirectToAuthCodeUrl(
authCodeUrlRequestParams,
authCodeRequestParams,
msalInstance
)(req, res, next);
};
}
redirectToAuthCodeUrl(authCodeUrlRequestParams, authCodeRequestParams, msalInstance) {
return async (req, res, next) => {
// Generate PKCE Codes before starting the authorization flow
const { verifier, challenge } = await this.cryptoProvider.generatePkceCodes();
// Set generated PKCE codes and method as session vars
req.session.pkceCodes = {
challengeMethod: 'S256',
verifier: verifier,
challenge: challenge,
};
/**
* By manipulating the request objects below before each request, we can obtain
* auth artifacts with desired claims. For more information, visit:
* https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_node.html#authorizationurlrequest
* https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_node.html#authorizationcoderequest
**/
req.session.authCodeUrlRequest = {
...authCodeUrlRequestParams,
responseMode: msal.ResponseMode.FORM_POST, // recommended for confidential clients
codeChallenge: req.session.pkceCodes.challenge,
codeChallengeMethod: req.session.pkceCodes.challengeMethod,
};
req.session.authCodeRequest = {
...authCodeRequestParams,
code: '',
};
try {
const authCodeUrlResponse = await msalInstance.getAuthCodeUrl(req.session.authCodeUrlRequest);
res.redirect(authCodeUrlResponse);
} catch (error) {
next(error);
}
};
}
/**
* Retrieves cloud discovery metadata from the /discovery/instance endpoint
* @returns
*/
async getCloudDiscoveryMetadata(authority) {
const endpoint = 'https://login.microsoftonline.com/common/discovery/instance';
try {
const response = await axios.get(endpoint, {
params: {
'api-version': '1.1',
'authorization_endpoint': `${authority}/oauth2/v2.0/authorize`
}
});
return await response.data;
} catch (error) {
throw error;
}
}
Quando l'utente seleziona il link Accedi, viene portato all'endpoint di autorizzazione di Microsoft Identity Platform.
Un accesso riuscito reindirizza l'utente alla route auth_response, che completa il processo di accesso usando auth.complete_login, esegue il rendering degli errori se presenti e reindirizza l'utente ora autenticato alla home page.
@app.route(app_config.REDIRECT_PATH)
def auth_response():
result = auth.complete_log_in(request.args)
if "error" in result:
return render_template("auth_error.html", result=result)
return redirect(url_for("index"))
Dopo che l'utente ha eseguito l'accesso all'app, è necessario abilitarli per disconnettersi.
Disconnessione
La disconnessione da un'app Web comporta più che rimuovere le informazioni sull'account connesso dallo stato dell'app Web.
Inoltre, l’app web deve reindirizzare l'utente all'endpoint logout Microsoft Identity Platform per la disconnessione.
Quando l'app Web reindirizza l'utente all'endpoint logout, l’endpoint cancella la sessione dell'utente dal browser. Se l'app non è andata all'endpoint logout, l'utente eseguirà nuovamente l’autenticazione all'app senza immetterne di nuovo le credenziali. Il motivo è che avranno una sessione di accesso Single Sign-In valida con Microsoft Identity Platform.
Durante la registrazione dell'applicazione, si registra un URL di disconnessione del canale anteriore. Nell'esercitazione è stata eseguita la registrazione di https://localhost:44321/signout-oidc nel campo URL di disconnessione del canale frontale nella pagina Autenticazione. Per informazioni dettagliate, vedere Registrare l'app WebApp.
Durante la registrazione dell'applicazione, non è necessario registrare un URL di disconnessione del canale anteriore aggiuntivo. L'app verrà richiamata nell'URL principale.
Nella registrazione dell'applicazione non è necessario alcun URL di disconnessione del canale anteriore.
Nella registrazione dell'applicazione non è necessario alcun URL di disconnessione del canale anteriore.
Durante la registrazione dell'applicazione, non è necessario registrare un URL di disconnessione del canale anteriore aggiuntivo. L'app verrà richiamata nell'URL principale.
In ASP.NET MVC il pulsante Disconnetti viene esposto in Views\Shared\_LoginPartial.cshtml. Viene visualizzato solo quando è presente un account autenticato. Ovvero, viene visualizzato quando l'utente ha eseguito l'accesso in precedenza.
Nelle versioni precedenti dei modelli ASP.NET Core, il controller Account è stato incorporato con l'app Web. Questo non è più il caso perché il controller fa ora parte del pacchetto NuGet Microsoft.Identity.Web.UI. Per informazioni dettagliate, vedere AccountController.cs.
Imposta un URI di reindirizzamento OpenID su /Account/SignedOut in modo che il controller venga richiamato quando Microsoft Entra ID ha completato la disconnessione.
Chiama Signout(), che consente al middleware OpenID Connect di contattare l'endpoint di Microsoft Identity Platform logout. L'endpoint quindi:
Cancella il cookie di sessione dal browser.
Richiama l'URI di reindirizzamento post-disconnessione. Per impostazione predefinita, l'URI di reindirizzamento post-disconnessione visualizza la pagina di visualizzazione disconnessa SignedOut.cshtml.cs. Questa pagina viene fornita anche come parte di Microsoft.Identity.Web.
In ASP.NET la disconnessione viene attivata dal metodo SignOut() in un controller (ad esempio AccountController.cs#L25-L31). Questo metodo non fa parte di .NET Framework, contrariamente a ciò che accade in ASP.NET Core. IT:
Invia un test di disconnesso OpenID.
Cancella la cache.
Reindirizza alla pagina desiderata.
/// <summary>
/// Send an OpenID Connect sign-out request.
/// </summary>
public void SignOut()
{
HttpContext.GetOwinContext()
.Authentication
.SignOut(CookieAuthenticationDefaults.AuthenticationType);
Response.Redirect("/");
}
In Java la disconnessione viene gestita chiamando direttamente l'endpoint logout di Microsoft Identity Platform e fornendo il valore post_logout_redirect_uri. Per informazioni dettagliate, vedere AuthPageController.java#L50-L60.
Quando l'utente seleziona il pulsante Disconnetti, l'app attiva la route /auth/signout, che elimina la sessione e reindirizza il browser all'endpoint di disconnessione di Microsoft Identity Platform.
logout(options = {}) {
return (req, res, next) => {
/**
* Construct a logout URI and redirect the user to end the
* session with Azure AD. For more information, visit:
* https://docs.microsoft.com/azure/active-directory/develop/v2-protocols-oidc#send-a-sign-out-request
*/
let logoutUri = `${this.msalConfig.auth.authority}/oauth2/v2.0/`;
if (options.postLogoutRedirectUri) {
logoutUri += `logout?post_logout_redirect_uri=${options.postLogoutRedirectUri}`;
}
req.session.destroy(() => {
res.redirect(logoutUri);
});
}
}
Quando l'utente seleziona Disconnetti, l'app attiva la route logout, che reindirizza il browser all'endpoint di disconnessione di Microsoft Identity Platform.
Il middleware ASP.NET Core OpenID Connect consente all'app di intercettare la chiamata all'endpoint logout di Microsoft Identity Platform fornendo un evento OpenID Connect denominato OnRedirectToIdentityProviderForSignOut. Questo viene gestito automaticamente da Microsoft.Identity.Web (che cancella gli account nel caso in cui l'app Web chiama api Web)
In ASP.NET si delega al middleware per eseguire la disconnessa, cancellando il cookie di sessione:
public class AccountController : Controller
{
...
public void EndSession()
{
Request.GetOwinContext().Authentication.SignOut();
Request.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie);
this.HttpContext.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
}
}
Nell'avvio rapido di Java l'URI di reindirizzamento post-disconnessione visualizza solo la pagina index.html.
Nell’avvio rapido a Node, l'URI di reindirizzamento post-disconnessione viene usato per reindirizzare il browser alla home page di esempio dopo che l'utente ha completato il processo di disconnessione con Microsoft Identity Platform.
Nell'avvio rapido di Python l'URI di reindirizzamento post-disconnessione visualizza solo la pagina index.html.
Protocollo
Per altre informazioni sulla disconnessione, leggere la documentazione del protocollo disponibile in OpenID Connect.
Passaggi successivi
Per ulteriori informazioni, creare un'app Web ASP.NET Core che effettua l’accesso degli utenti nella serie di esercitazioni in più parti seguenti