using System; using System.Collections.Generic; using System.Linq; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Clients.ActiveDirectory; using Microsoft.IdentityModel.Protocols.OpenIdConnect; namespace OpenIdConnect.AzureAdSample { public class Startup { public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath); if (env.IsDevelopment()) { // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 builder.AddUserSecrets(); } builder.AddEnvironmentVariables(); Configuration = builder.Build(); } public IConfiguration Configuration { get; set; } private string ClientId => Configuration["oidc:clientid"]; private string ClientSecret => Configuration["oidc:clientsecret"]; private string Authority => Configuration["oidc:authority"]; private string Resource => "https://graph.windows.net"; public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(sharedOptions => { sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, "AAD", o => { o.ClientId = ClientId; o.ClientSecret = ClientSecret; // for code flow o.Authority = Authority; o.ResponseType = OpenIdConnectResponseType.CodeIdToken; o.SignedOutRedirectUri = "/signed-out"; // GetClaimsFromUserInfoEndpoint = true, o.Events = new OpenIdConnectEvents() { OnAuthorizationCodeReceived = async context => { var request = context.HttpContext.Request; var currentUri = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path); var credential = new ClientCredential(ClientId, ClientSecret); var authContext = new AuthenticationContext(Authority, AuthPropertiesTokenCache.ForCodeRedemption(context.Properties)); var result = await authContext.AcquireTokenByAuthorizationCodeAsync( context.ProtocolMessage.Code, new Uri(currentUri), credential, Resource); context.HandleCodeRedemption(result.AccessToken, result.IdToken); } }; }); } public void Configure(IApplicationBuilder app) { app.UseDeveloperExceptionPage(); app.UseAuthentication(); app.Run(async context => { if (context.Request.Path.Equals("/signin")) { if (context.User.Identities.Any(identity => identity.IsAuthenticated)) { // User has already signed in context.Response.Redirect("/"); return; } await context.ChallengeAsync(new AuthenticationProperties { RedirectUri = "/" }); } else if (context.Request.Path.Equals("/signout")) { await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); await WriteHtmlAsync(context.Response, async response => { await response.WriteAsync($"

Signed out locally: {HtmlEncode(context.User.Identity.Name)}

"); await response.WriteAsync("Sign In"); }); } else if (context.Request.Path.Equals("/signout-remote")) { await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); } else if (context.Request.Path.Equals("/signed-out")) { await WriteHtmlAsync(context.Response, async response => { await response.WriteAsync($"

You have been signed out.

"); await response.WriteAsync("Sign In"); }); } else if (context.Request.Path.Equals("/remote-signedout")) { await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); await WriteHtmlAsync(context.Response, async response => { await response.WriteAsync($"

Signed out remotely: {HtmlEncode(context.User.Identity.Name)}

"); await response.WriteAsync("Sign In"); }); } else { if (!context.User.Identities.Any(identity => identity.IsAuthenticated)) { await context.ChallengeAsync(new AuthenticationProperties { RedirectUri = "/" }); return; } await WriteHtmlAsync(context.Response, async response => { await response.WriteAsync($"

Hello Authenticated User {HtmlEncode(context.User.Identity.Name)}

"); await response.WriteAsync("Sign Out Locally"); await response.WriteAsync("Sign Out Remotely"); await response.WriteAsync("

Claims:

"); await WriteTableHeader(response, new string[] { "Claim Type", "Value" }, context.User.Claims.Select(c => new string[] { c.Type, c.Value })); await response.WriteAsync("

Tokens:

"); try { // Use ADAL to get the right token var authContext = new AuthenticationContext(Authority, AuthPropertiesTokenCache.ForApiCalls(context, CookieAuthenticationDefaults.AuthenticationScheme)); var credential = new ClientCredential(ClientId, ClientSecret); string userObjectID = context.User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value; var result = await authContext.AcquireTokenSilentAsync(Resource, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId)); await response.WriteAsync($"

access_token

{HtmlEncode(result.AccessToken)}
"); } catch (Exception ex) { await response.WriteAsync($"AquireToken error: {ex.Message}"); } }); } }); } private static async Task WriteHtmlAsync(HttpResponse response, Func writeContent) { var bootstrap = ""; response.ContentType = "text/html"; await response.WriteAsync($"{bootstrap}
"); await writeContent(response); await response.WriteAsync("
"); } private static async Task WriteTableHeader(HttpResponse response, IEnumerable columns, IEnumerable> data) { await response.WriteAsync(""); await response.WriteAsync(""); foreach (var column in columns) { await response.WriteAsync($""); } await response.WriteAsync(""); foreach (var row in data) { await response.WriteAsync(""); foreach (var column in row) { await response.WriteAsync($""); } await response.WriteAsync(""); } await response.WriteAsync("
{HtmlEncode(column)}
{HtmlEncode(column)}
"); } private static string HtmlEncode(string content) => string.IsNullOrEmpty(content) ? string.Empty : HtmlEncoder.Default.Encode(content); } }