aspnetcore/samples/SocialSample/Startup.cs

284 lines
13 KiB
C#

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.Google;
using Microsoft.AspNet.Authentication.MicrosoftAccount;
using Microsoft.AspNet.Authentication.OAuth;
using Microsoft.AspNet.Authentication.Twitter;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Authentication;
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 void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{
loggerfactory.AddConsole(LogLevel.Information);
app.UseCookieAuthentication(options =>
{
options.AutomaticAuthenticate = true;
options.AutomaticChallenge = true;
options.LoginPath = new PathString("/login");
});
// https://developers.facebook.com/apps/
app.UseFacebookAuthentication(options =>
{
options.AppId = "569522623154478";
options.AppSecret = "a124463c4719c94b4228d9a240e5dc1a";
});
app.UseOAuthAuthentication(new OAuthOptions
{
AuthenticationScheme = "Google-AccessToken",
DisplayName = "Google-AccessToken",
ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com",
ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f",
CallbackPath = new PathString("/signin-google-token"),
AuthorizationEndpoint = GoogleDefaults.AuthorizationEndpoint,
TokenEndpoint = GoogleDefaults.TokenEndpoint,
Scope = { "openid", "profile", "email" }
});
// https://console.developers.google.com/project
app.UseGoogleAuthentication(options =>
{
options.ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com";
options.ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f";
options.Events = new OAuthEvents()
{
OnRemoteError = ctx =>
{
ctx.Response.Redirect("/error?ErrorMessage=" + UrlEncoder.Default.Encode(ctx.Error.Message));
ctx.HandleResponse();
return Task.FromResult(0);
}
};
});
// https://apps.twitter.com/
app.UseTwitterAuthentication(options =>
{
options.ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g";
options.ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI";
options.Events = new TwitterEvents()
{
OnRemoteError = ctx =>
{
ctx.Response.Redirect("/error?ErrorMessage=" + UrlEncoder.Default.Encode(ctx.Error.Message));
ctx.HandleResponse();
return Task.FromResult(0);
}
};
});
/* 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(new OAuthOptions
{
AuthenticationScheme = "Microsoft-AccessToken",
DisplayName = "MicrosoftAccount-AccessToken - Requires project changes",
ClientId = "00000000480FF62E",
ClientSecret = "bLw2JIvf8Y1TaToipPEqxTVlOeJwCUsr",
CallbackPath = new PathString("/signin-microsoft-token"),
AuthorizationEndpoint = MicrosoftAccountDefaults.AuthorizationEndpoint,
TokenEndpoint = MicrosoftAccountDefaults.TokenEndpoint,
Scope = { "wl.basic" }
});
app.UseMicrosoftAccountAuthentication(options =>
{
options.DisplayName = "MicrosoftAccount - Requires project changes";
options.ClientId = "00000000480FF62E";
options.ClientSecret = "bLw2JIvf8Y1TaToipPEqxTVlOeJwCUsr";
options.Scope.Add("wl.emails");
});
// https://github.com/settings/applications/
app.UseOAuthAuthentication(new OAuthOptions
{
AuthenticationScheme = "GitHub-AccessToken",
DisplayName = "Github-AccessToken",
ClientId = "8c0c5a572abe8fe89588",
ClientSecret = "e1d95eaf03461d27acd6f49d4fc7bf19d6ac8cda",
CallbackPath = new PathString("/signin-github-token"),
AuthorizationEndpoint = "https://github.com/login/oauth/authorize",
TokenEndpoint = "https://github.com/login/oauth/access_token"
});
app.UseOAuthAuthentication(new OAuthOptions
{
AuthenticationScheme = "GitHub",
DisplayName = "Github",
ClientId = "49e302895d8b09ea5656",
ClientSecret = "98f1bf028608901e9df91d64ee61536fe562064b",
CallbackPath = new PathString("/signin-github"),
AuthorizationEndpoint = "https://github.com/login/oauth/authorize",
TokenEndpoint = "https://github.com/login/oauth/access_token",
UserInformationEndpoint = "https://api.github.com/user",
ClaimsIssuer = "OAuth2-Github",
SaveTokensAsClaims = false,
// Retrieving user information is unique to each provider.
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<string>("id");
if (!string.IsNullOrEmpty(identifier))
{
context.Identity.AddClaim(new Claim(
ClaimTypes.NameIdentifier, identifier,
ClaimValueTypes.String, context.Options.ClaimsIssuer));
}
var userName = user.Value<string>("login");
if (!string.IsNullOrEmpty(userName))
{
context.Identity.AddClaim(new Claim(
ClaimsIdentity.DefaultNameClaimType, userName,
ClaimValueTypes.String, context.Options.ClaimsIssuer));
}
var name = user.Value<string>("name");
if (!string.IsNullOrEmpty(name))
{
context.Identity.AddClaim(new Claim(
"urn:github:name", name,
ClaimValueTypes.String, context.Options.ClaimsIssuer));
}
var link = user.Value<string>("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("<html><body>");
await context.Response.WriteAsync("Choose an authentication scheme: <br>");
foreach (var type in context.Authentication.GetAuthenticationSchemes())
{
await context.Response.WriteAsync("<a href=\"?authscheme=" + type.AuthenticationScheme + "\">" + (type.DisplayName ?? "(suppressed)") + "</a><br>");
}
await context.Response.WriteAsync("</body></html>");
});
});
// 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("<html><body>");
await context.Response.WriteAsync("You have been logged out. Goodbye " + context.User.Identity.Name + "<br>");
await context.Response.WriteAsync("<a href=\"/\">Home</a>");
await context.Response.WriteAsync("</body></html>");
});
});
// Display the remote error
app.Map("/error", errorApp =>
{
errorApp.Run(async context =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("<html><body>");
await context.Response.WriteAsync("An remote error has occured: " + context.Request.Query["ErrorMessage"] + "<br>");
await context.Response.WriteAsync("<a href=\"/\">Home</a>");
await context.Response.WriteAsync("</body></html>");
});
});
// 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("<html><body>");
await context.Response.WriteAsync("Hello " + (context.User.Identity.Name ?? "anonymous") + "<br>");
foreach (var claim in context.User.Claims)
{
await context.Response.WriteAsync(claim.Type + ": " + claim.Value + "<br>");
}
await context.Response.WriteAsync("<a href=\"/logout\">Logout</a>");
await context.Response.WriteAsync("</body></html>");
});
}
}
}