using System; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNet.Authentication.Cookies; using Microsoft.AspNet.Authentication.Facebook; using Microsoft.AspNet.Authentication.Google; using Microsoft.AspNet.Authentication.MicrosoftAccount; using Microsoft.AspNet.Authentication.OAuth; using Microsoft.AspNet.Authentication.Twitter; using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Authentication; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; namespace CookieSample { /* Note all servers must use the same address and port because these are pre-registered with the various providers. */ public class Startup { public Startup() { Configuration = new ConfigurationBuilder() .AddEnvironmentVariables() .AddJsonFile("config.json") .AddUserSecrets() .Build(); } public IConfiguration Configuration { get; set; } public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme); } public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) { loggerfactory.AddConsole(LogLevel.Information); // Simple error page to avoid a repo dependency. app.Use(async (context, next) => { try { await next(); } catch (Exception ex) { if (context.Response.HasStarted) { throw; } context.Response.StatusCode = 500; await context.Response.WriteAsync(ex.ToString()); } }); app.UseCookieAuthentication(options => { options.AutomaticAuthenticate = true; options.AutomaticChallenge = true; options.LoginPath = new PathString("/login"); }); // You must first create an app with facebook and add it's ID and Secret to your config.json or user-secrets. // https://developers.facebook.com/apps/ app.UseFacebookAuthentication(options => { options.AppId = Configuration["facebook:appid"]; options.AppSecret = Configuration["facebook:appsecret"]; options.Scope.Add("email"); options.Fields.Add("name"); options.Fields.Add("email"); }); // See config.json app.UseOAuthAuthentication(options => { options.AuthenticationScheme = "Google-AccessToken"; options.DisplayName = "Google-AccessToken"; options.ClientId = Configuration["google:clientid"]; options.ClientSecret = Configuration["google:clientsecret"]; options.CallbackPath = new PathString("/signin-google-token"); options.AuthorizationEndpoint = GoogleDefaults.AuthorizationEndpoint; options.TokenEndpoint = GoogleDefaults.TokenEndpoint; options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); options.SaveTokensAsClaims = true; }); // See config.json // https://console.developers.google.com/project app.UseGoogleAuthentication(options => { options.ClientId = Configuration["google:clientid"]; options.ClientSecret = Configuration["google:clientsecret"]; options.Events = new OAuthEvents() { OnRemoteFailure = ctx => { ctx.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(ctx.Failure.Message)); ctx.HandleResponse(); return Task.FromResult(0); } }; }); // See config.json // https://apps.twitter.com/ app.UseTwitterAuthentication(options => { options.ConsumerKey = Configuration["twitter:consumerkey"]; options.ConsumerSecret = Configuration["twitter:consumersecret"]; options.Events = new TwitterEvents() { OnRemoteFailure = ctx => { ctx.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(ctx.Failure.Message)); ctx.HandleResponse(); return Task.FromResult(0); } }; }); // You must first create an app with live.com and add it's ID and Secret to your config.json or user-secrets. /* https://account.live.com/developers/applications The MicrosoftAccount service has restrictions that prevent the use of http://localhost:54540/ for test applications. As such, here is how to change this sample to uses http://mssecsample.localhost.this:54540/ instead. Edit the Project.json file and replace http://localhost:54540/ with http://mssecsample.localhost.this:54540/. From an admin command console first enter: notepad C:\Windows\System32\drivers\etc\hosts and add this to the file, save, and exit (and reboot?): 127.0.0.1 MsSecSample.localhost.this Then you can choose to run the app as admin (see below) or add the following ACL as admin: netsh http add urlacl url=http://mssecsample.localhost.this:54540/ user=[domain\user] The sample app can then be run via: dnx . web */ app.UseOAuthAuthentication(options => { options.AuthenticationScheme = "Microsoft-AccessToken"; options.DisplayName = "MicrosoftAccount-AccessToken - Requires project changes"; options.ClientId = Configuration["msa:clientid"]; options.ClientSecret = Configuration["msa:clientsecret"]; options.CallbackPath = new PathString("/signin-microsoft-token"); options.AuthorizationEndpoint = MicrosoftAccountDefaults.AuthorizationEndpoint; options.TokenEndpoint = MicrosoftAccountDefaults.TokenEndpoint; options.Scope.Add("wl.basic"); options.SaveTokensAsClaims = true; }); //// You must first create an app with live.com and add it's ID and Secret to your config.json or user-secrets. app.UseMicrosoftAccountAuthentication(options => { options.DisplayName = "MicrosoftAccount - Requires project changes"; options.ClientId = Configuration["msa:clientid"]; options.ClientSecret = Configuration["msa:clientsecret"]; options.Scope.Add("wl.emails"); }); // See config.json // https://github.com/settings/applications/ app.UseOAuthAuthentication(options => { options.AuthenticationScheme = "GitHub-AccessToken"; options.DisplayName = "Github-AccessToken"; options.ClientId = Configuration["github-token:clientid"]; options.ClientSecret = Configuration["github-token:clientsecret"]; options.CallbackPath = new PathString("/signin-github-token"); options.AuthorizationEndpoint = "https://github.com/login/oauth/authorize"; options.TokenEndpoint = "https://github.com/login/oauth/access_token"; options.SaveTokensAsClaims = true; }); // See config.json app.UseOAuthAuthentication(options => { options.AuthenticationScheme = "GitHub"; options.DisplayName = "Github"; options.ClientId = Configuration["github:clientid"]; options.ClientSecret = Configuration["github:clientsecret"]; options.CallbackPath = new PathString("/signin-github"); options.AuthorizationEndpoint = "https://github.com/login/oauth/authorize"; options.TokenEndpoint = "https://github.com/login/oauth/access_token"; options.UserInformationEndpoint = "https://api.github.com/user"; options.ClaimsIssuer = "OAuth2-Github"; // Retrieving user information is unique to each provider. options.Events = new OAuthEvents { OnCreatingTicket = async context => { // Get the GitHub user var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted); response.EnsureSuccessStatusCode(); var user = JObject.Parse(await response.Content.ReadAsStringAsync()); var identifier = user.Value("id"); if (!string.IsNullOrEmpty(identifier)) { context.Identity.AddClaim(new Claim( ClaimTypes.NameIdentifier, identifier, ClaimValueTypes.String, context.Options.ClaimsIssuer)); } var userName = user.Value("login"); if (!string.IsNullOrEmpty(userName)) { context.Identity.AddClaim(new Claim( ClaimsIdentity.DefaultNameClaimType, userName, ClaimValueTypes.String, context.Options.ClaimsIssuer)); } var name = user.Value("name"); if (!string.IsNullOrEmpty(name)) { context.Identity.AddClaim(new Claim( "urn:github:name", name, ClaimValueTypes.String, context.Options.ClaimsIssuer)); } var link = user.Value("url"); if (!string.IsNullOrEmpty(link)) { context.Identity.AddClaim(new Claim( "urn:github:url", link, ClaimValueTypes.String, context.Options.ClaimsIssuer)); } } }; }); // Choose an authentication type app.Map("/login", signoutApp => { signoutApp.Run(async context => { var authType = context.Request.Query["authscheme"]; if (!string.IsNullOrEmpty(authType)) { // By default the client will be redirect back to the URL that issued the challenge (/login?authtype=foo), // send them to the home page instead (/). await context.Authentication.ChallengeAsync(authType, new AuthenticationProperties() { RedirectUri = "/" }); return; } context.Response.ContentType = "text/html"; await context.Response.WriteAsync(""); await context.Response.WriteAsync("Choose an authentication scheme:
"); foreach (var type in context.Authentication.GetAuthenticationSchemes()) { await context.Response.WriteAsync("" + (type.DisplayName ?? "(suppressed)") + "
"); } await context.Response.WriteAsync(""); }); }); // Sign-out to remove the user cookie. app.Map("/logout", signoutApp => { signoutApp.Run(async context => { context.Response.ContentType = "text/html"; await context.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); await context.Response.WriteAsync(""); await context.Response.WriteAsync("You have been logged out. Goodbye " + context.User.Identity.Name + "
"); await context.Response.WriteAsync("Home"); await context.Response.WriteAsync(""); }); }); // Display the remote error app.Map("/error", errorApp => { errorApp.Run(async context => { context.Response.ContentType = "text/html"; await context.Response.WriteAsync(""); await context.Response.WriteAsync("An remote failure has occurred: " + context.Request.Query["FailureMessage"] + "
"); await context.Response.WriteAsync("Home"); await context.Response.WriteAsync(""); }); }); // Deny anonymous request beyond this point. app.Use(async (context, next) => { if (!context.User.Identities.Any(identity => identity.IsAuthenticated)) { // The cookie middleware will intercept this 401 and redirect to /login await context.Authentication.ChallengeAsync(); return; } await next(); }); // Display user information app.Run(async context => { context.Response.ContentType = "text/html"; await context.Response.WriteAsync(""); await context.Response.WriteAsync("Hello " + (context.User.Identity.Name ?? "anonymous") + "
"); foreach (var claim in context.User.Claims) { await context.Response.WriteAsync(claim.Type + ": " + claim.Value + "
"); } await context.Response.WriteAsync("Logout"); await context.Response.WriteAsync(""); }); } public static void Main(string[] args) { var application = new WebApplicationBuilder() .UseConfiguration(WebApplicationConfiguration.GetDefault(args)) .UseStartup() .Build(); application.Run(); } } }