Description
Une application web ASP.NET MVC avec une authentification Azure AD App.
Visual Studio
- New Project → Web → ASP.NET Web Application (.NET Framework)
- Template: MVC (+ Web API)
- Authentification: No Authentification (Work or School Accounts)
Configuration projet ASP.NET
Startup.cs
|
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
|
App_Start\Startup.Auth.cs
|
public partial class Startup
{
private static string _clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string _clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"]; // password
private static string _tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static string _authority = "https://login.microsoftonline.com/" + _tenant;
private static string _postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
// For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = _clientId,
//ClientSecret = _clientSecret,
Authority = _authority,
//RedirectUri = _postLogoutRedirectUri,
PostLogoutRedirectUri = _postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/Error/message=" + context.Exception.Message);
return Task.FromResult(0);
},
AuthorizationCodeReceived = context =>
{
var code = context.Code;
var credential = new ClientCredential(_clientId, _clientSecret);
string signedInUserID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
var authContext = new AuthenticationContext(_authority);
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
code,
new Uri(_postLogoutRedirectUri),
// new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path))
credential,
"https://graph.microsoft.com"); // Graph Resource Url
var graphToken = result.AccessToken;
}
}
});
}
}
|
Web.config
|
<configuration>
<appSettings>
<add key="ida:Tenant" value="xxx.onmicrosoft.com" />
<add key="ida:Audience" value="https://xxx.onmicrosoft.com/1234abcd-1234-abcd-1234-123456abcdef" />
<add key="ida:ClientID" value="5678abcd-5678-abcd-5678-567890abcdef" />
<add key="ida:PostLogoutRedirectUri" value="https://yyy.azurewebsites.net/" />
|
Packages Nuget
Microsoft.Owin.Security.OpenIdConnect
|
Microsoft.Owin.Security.Cookies
|
Microsoft.Owin.Security
|
Owin |
IAppBuilder
|
Microsoft.IdentityModel.Clients.ActiveDirectory |
ClientCredential
|
Microsoft.Owin.Host.SystemWeb |
exécution de Startup.cs au démarrage
|
Configuration Azure AD
Azure → Azure Active Directory → App Registrations
Bouton SignIn
Views/Shared/_LoginPartial.cshtml
|
@if (Request.IsAuthenticated)
{
<ul class="nav navbar-nav navbar-right">
<li class="navbar-text">
Hello @User.Identity.Name !
</li>
<li>
@Html.ActionLink("Sign out", "SignOut", "Account")
</li>
</ul>
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>@Html.ActionLink("Sign in", "SignIn", "Account", routeValues:null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
|
Views/Shared/_Layout.cshtml
|
@Html.Partial("_LoginPartial")
|
Controllers/AccountController.cs
|
public class AccountController : Controller
{
public void SignIn()
{
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
public void SignOut()
{
HttpContext.GetOwinContext().Authentication.SignOut(
OpenIdConnectAuthenticationDefaults.AuthenticationType,
CookieAuthenticationDefaults.AuthenticationType);
}
|
Token Cache
App_Start\Startup.Auth.cs
|
AuthenticationContext authContext = new AuthenticationContext(Authority, new ADALTokenCache(signedInUserID));
|
ADALTokenCache.cs
|
public class ADALTokenCache : TokenCache
{
private ApplicationDbContext db = new ApplicationDbContext();
private string userId;
private UserTokenCache Cache;
public ADALTokenCache(string signedInUserId)
{
// associate the cache to the current user of the web app
userId = signedInUserId;
this.AfterAccess = AfterAccessNotification;
this.BeforeAccess = BeforeAccessNotification;
this.BeforeWrite = BeforeWriteNotification;
// look up the entry in the database
Cache = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
// place the entry in memory
this.Deserialize((Cache == null) ? null : MachineKey.Unprotect(Cache.cacheBits,"ADALCache"));
}
// clean up the database
public override void Clear()
{
base.Clear();
var cacheEntry = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
db.UserTokenCacheList.Remove(cacheEntry);
db.SaveChanges();
}
// Notification raised before ADAL accesses the cache.
// This is your chance to update the in-memory copy from the DB, if the in-memory version is stale
void BeforeAccessNotification(TokenCacheNotificationArgs args)
{
if (Cache == null)
{
// first time access
Cache = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
}
else
{
// retrieve last write from the DB
var status = from e in db.UserTokenCacheList
where (e.webUserUniqueId == userId)
select new
{
LastWrite = e.LastWrite
};
// if the in-memory copy is older than the persistent copy
if (status.First().LastWrite > Cache.LastWrite)
{
// read from from storage, update in-memory copy
Cache = db.UserTokenCacheList.FirstOrDefault(c => c.webUserUniqueId == userId);
}
}
this.Deserialize((Cache == null) ? null : MachineKey.Unprotect(Cache.cacheBits, "ADALCache"));
}
// Notification raised after ADAL accessed the cache.
// If the HasStateChanged flag is set, ADAL changed the content of the cache
void AfterAccessNotification(TokenCacheNotificationArgs args)
{
// if state changed
if (this.HasStateChanged)
{
if (Cache == null)
{
Cache = new UserTokenCache
{
webUserUniqueId = userId
};
}
Cache.cacheBits = MachineKey.Protect(this.Serialize(), "ADALCache");
Cache.LastWrite = DateTime.Now;
// update the DB and the lastwrite
db.Entry(Cache).State = Cache.UserTokenCacheId == 0 ? EntityState.Added : EntityState.Modified;
db.SaveChanges();
this.HasStateChanged = false;
}
}
void BeforeWriteNotification(TokenCacheNotificationArgs args)
{
// if you want to ensure that no concurrent write take place, use this notification to place a lock on the entry
}
public override void DeleteItem(TokenCacheItem item)
{
base.DeleteItem(item);
}
}
|
OLD
- New Project → Web → ASP.NET Web Application → MVC, No Authentication
- Sélectionner le projet → onglet Properties → SSL enabled → True
- Copier la SSL URL
- Clique-droit sur le projet → Properties → Web → Servers → Project Url → https://<SSL URL>
- Installer les paquets Nuget:
- Microsoft.IdentityModel.Protocol.Extensions
- System.IdentityModel.Tokens.Jwt
- Microsoft.Owin.Security.Cookies
- Microsoft.Owin.Host.SystemWeb
- Microsoft.Owin.Security.OpenIdConnect
Web.config
|
<configuration>
<appSettings>
<add key="ida:ClientId" value="" />
<add key="ida:AADInstance" value="https://login.microsoftonline.com/{0}" />
<!-- Domaine du compte Azure -->
<add key="ida:Tenant" value="xxx.onmicrosoft.com" />
<!-- Project URL -->
<add key="ida:PostLogoutRedirectUri" value="https://localhost:44350/" />
|
App_Start/Startup.cs
|
using Microsoft.Owin.Security;
// à déclarer en dehors du namespace
// exécute la méthode Configuration du type passé en paramètre
[assembly: OwinStartup(typeof(Namespace.App_Start.Startup))]
// assembly Microsoft.Owin
public class Startup
{
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
// https://login.microsoftonline.com/xxx.onmicrosoft.com
string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
public void Configuration(IAppBuilder app)
{
// assembly Microsoft.Owin.Security
// assembly Microsoft.Owin.Security.Cookies
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
// assembly Microsoft.Owin.Security.OpenIdConnect
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/Error/message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
|
Views/Shared/_LoginPartial.cshtml
|
@if (Request.IsAuthenticated)
{
<ul class="nav navbar-nav navbar-right">
<li class="navbar-text">
Hello @User.Identity.Name !
</li>
<li>
@Html.ActionLink("Sign out", "SignOut", "Account")
</li>
</ul>
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>@Html.ActionLink("Sign in", "SignIn", "Account", routeValues:null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
|
Views/Shared/_Layout.cshtml
|
@Html.Partial("_LoginPartial");
|
Controllers/AccountController.cs
|
public class AccountController : Controller
{
public void SignIn()
{
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
public void SignOut()
{
HttpContext.GetOwinContext().Authentication.SignOut(
OpenIdConnectAuthenticationDefaults.AuthenticationType,
CookieAuthenticationDefaults.AuthenticationType);
}
|
Créer une application dans Azure Active Directory
Azure → Azure Active Directory → App registration → New application registration
- Sign-on URL: https://<SSL URL>
Récupérer l'Application ID (= Client ID) et la reporter dans Web.config
- Azure → Azure Active Directory → App registration → My App → Application ID