Skip to content
This repository was archived by the owner on Dec 13, 2018. It is now read-only.

Authentication 2.0 Iteration 3 (with Names/OptionFactory) #1151

Closed
wants to merge 64 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
85c061b
First cut of Authentication.Abstractions
HaoK Feb 3, 2017
7e6ee64
Add impl package
HaoK Feb 3, 2017
5ca7293
Cleanup
HaoK Feb 3, 2017
5dee20e
Cleanup scheme to be data only
HaoK Feb 3, 2017
930e181
Switch cookies over to new stack
HaoK Feb 9, 2017
9bd97d3
Migrate twitter to new stack
HaoK Feb 9, 2017
5bb29bd
Port jwtbearer
HaoK Feb 9, 2017
4cdd751
Port OIDC
HaoK Feb 10, 2017
9c9fcdb
Port OAuth
HaoK Feb 10, 2017
dddd328
Add facebook
HaoK Feb 10, 2017
9886034
Fix test
HaoK Feb 10, 2017
4c0f0de
Add google
HaoK Feb 13, 2017
7a8eb88
Add feature to preserve old map resolve url behavior
HaoK Feb 13, 2017
8b7ee3d
PR feedback
HaoK Feb 13, 2017
a035079
PR tweaks
HaoK Feb 13, 2017
eb2a057
Switch to ReadOnlyDictionary
HaoK Feb 13, 2017
5abcc58
Cleanup cookies finish response
HaoK Feb 14, 2017
93897de
Add fb test
HaoK Feb 14, 2017
0ea81bc
Add test for fb AppId/Secret options
HaoK Feb 14, 2017
9728cfe
Fix issue with cookies renew + signout/signin
HaoK Feb 14, 2017
f854c1a
Add microsoft, cleanup test dirs
HaoK Feb 14, 2017
103a520
Reenable two skipped tests
HaoK Feb 15, 2017
6ea973b
Remove using
HaoK Feb 15, 2017
4c6d953
Support dynamic add/remove of schemes
HaoK Feb 22, 2017
43e5c58
Update samples to work with new stack
HaoK Feb 24, 2017
ea69829
Update cookie interop tests
HaoK Feb 24, 2017
504ad2b
Fix cookiepolicy test
HaoK Feb 24, 2017
a98ef6f
Opt in for schemes to handle requests
HaoK Feb 24, 2017
425b971
Opt out of request handling for JwtBearer
HaoK Feb 24, 2017
c057524
HandleRequest back to bool
HaoK Feb 27, 2017
41a0366
Schemes must register callbackPaths
HaoK Feb 27, 2017
b8624a9
Add GetAllSchemes
HaoK Feb 27, 2017
d451908
Rename Skip => Stop/None
HaoK Mar 6, 2017
15192f2
Cleanup
HaoK Mar 6, 2017
825ca71
Bring back Skip
HaoK Mar 6, 2017
901a590
Named options fork
HaoK Mar 9, 2017
de35d06
Options Factory fork
HaoK Mar 11, 2017
14c32b0
Push dataprotection up to Remote
HaoK Mar 13, 2017
9033f08
Remove AddRemoteScheme
HaoK Mar 13, 2017
9552ed4
Fix null ref
HaoK Mar 13, 2017
4d76bc1
Add options factory tests
HaoK Mar 13, 2017
520116a
Add default behavior
HaoK Mar 15, 2017
a1400ad
Update sln
HaoK Mar 15, 2017
d86b0d0
Fix merge issues
HaoK Mar 15, 2017
3d0dbcf
Drop Default prefix
HaoK Mar 15, 2017
4b7ad77
PR feedback + fix SocialSample
HaoK Mar 15, 2017
2d6de68
Remove clears
HaoK Mar 15, 2017
d3b0aca
Move IOptionsFactory to Options repo
HaoK Mar 16, 2017
2e4e176
React to options rename
HaoK Mar 17, 2017
2fca4b2
Takeover Authentication (nuke .Impl)
HaoK Mar 17, 2017
633f187
Cleanup
HaoK Mar 20, 2017
47eda07
Move stuff into HttpAbstractions
HaoK Mar 22, 2017
80a32ad
Cleanup
HaoK Mar 22, 2017
2555eda
Refactor into HttpAbstracionts: Core/Abstractions
HaoK Mar 23, 2017
35659d3
PR cleanup
HaoK Mar 23, 2017
5cec0e1
Cleanup
HaoK Mar 23, 2017
59ced83
Add back UseXyz as obslete/throw
HaoK Mar 23, 2017
75d757d
Add google back
HaoK Mar 23, 2017
523548d
Update to real fwlink
HaoK Mar 23, 2017
5650eec
Update obsolete to include fwlink
HaoK Mar 23, 2017
1397e05
Update obsolete to error
HaoK Mar 23, 2017
da921ba
Fix formatting
HaoK Mar 23, 2017
7804858
React to options
HaoK Mar 29, 2017
06871dd
Update to latest options/http
HaoK Mar 31, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 205 additions & 16 deletions Security.sln

Large diffs are not rendered by default.

10 changes: 4 additions & 6 deletions samples/CookieSample/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
Expand All @@ -13,24 +14,21 @@ public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
services.AddCookieAuthentication();
}

public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{
loggerfactory.AddConsole(LogLevel.Information);

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true
});
app.UseAuthentication();

app.Run(async context =>
{
if (!context.User.Identities.Any(identity => identity.IsAuthenticated))
{
var user = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "bob") }, CookieAuthenticationDefaults.AuthenticationScheme));
await context.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user);
await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, user);

context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Hello First timer");
Expand Down
11 changes: 4 additions & 7 deletions samples/CookieSessionSample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
Expand All @@ -14,18 +15,14 @@ public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
services.AddCookieAuthentication(o => o.SessionStore = new MemoryCacheTicketStore());
}

public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{
loggerfactory.AddConsole(LogLevel.Information);

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
SessionStore = new MemoryCacheTicketStore()
});
app.UseAuthentication();

app.Run(async context =>
{
Expand All @@ -39,7 +36,7 @@ public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
claims.Add(new Claim(ClaimTypes.Role, "SomeRandomGroup" + i, ClaimValueTypes.String, "IssuedByBob", "OriginalIssuerJoe"));
}

await context.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
await context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme)));

context.Response.ContentType = "text/plain";
Expand Down
54 changes: 27 additions & 27 deletions samples/JwtBearerSample/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
Expand Down Expand Up @@ -42,7 +43,28 @@ public Startup(IHostingEnvironment env)
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication();
services.AddJwtBearerAuthentication(o =>
{
// You also need to update /wwwroot/app/scripts/app.js
o.Authority = Configuration["jwt:authority"];
o.Audience = Configuration["jwt:audience"];
o.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.HandleResponse();

c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";
if (Environment.IsDevelopment())
{
// Debug only, in production do not share exceptions with the remote host.
return c.Response.WriteAsync(c.Exception.ToString());
}
return c.Response.WriteAsync("An error occurred processing your authentication.");
}
};
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand All @@ -69,44 +91,22 @@ public void Configure(IApplicationBuilder app)
app.UseDefaultFiles();
app.UseStaticFiles();

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
// You also need to update /wwwroot/app/scripts/app.js
Authority = Configuration["jwt:authority"],
Audience = Configuration["jwt:audience"],
Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.HandleResponse();

c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";
if (Environment.IsDevelopment())
{
// Debug only, in production do not share exceptions with the remote host.
return c.Response.WriteAsync(c.Exception.ToString());
}
return c.Response.WriteAsync("An error occurred processing your authentication.");
}
}
});
app.UseAuthentication();

// [Authorize] would usually handle this
app.Use(async (context, next) =>
{
// Use this if options.AutomaticAuthenticate = false
// Use this if there are multiple authentication schemes
// var user = await context.Authentication.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);

var user = context.User; // We can do this because of options.AutomaticAuthenticate = true;
var user = context.User; // We can do this because of there's only a single authentication scheme
if (user?.Identity?.IsAuthenticated ?? false)
{
await next();
}
else
{
// We can do this because of options.AutomaticChallenge = true;
await context.Authentication.ChallengeAsync();
await context.ChallengeAsync(JwtBearerDefaults.AuthenticationScheme);
}
});

Expand Down
12 changes: 5 additions & 7 deletions samples/OpenIdConnect.AzureAdSample/AuthPropertiesTokenCache.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Http.Features.Authentication;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

namespace OpenIdConnect.AzureAdSample
Expand Down Expand Up @@ -58,10 +57,9 @@ private void BeforeAccessNotificationWithProperties(TokenCacheNotificationArgs a
private void BeforeAccessNotificationWithContext(TokenCacheNotificationArgs args)
{
// Retrieve the auth session with the cached tokens
var authenticateContext = new AuthenticateContext(_signInScheme);
_httpContext.Authentication.AuthenticateAsync(authenticateContext).Wait();
_authProperties = new AuthenticationProperties(authenticateContext.Properties);
_principal = authenticateContext.Principal;
var result = _httpContext.AuthenticateAsync(_signInScheme).Result;
_authProperties = result.Ticket.Properties;
_principal = result.Ticket.Principal;

BeforeAccessNotificationWithProperties(args);
}
Expand All @@ -87,7 +85,7 @@ private void AfterAccessNotificationWithContext(TokenCacheNotificationArgs args)
var cachedTokens = Serialize();
var cachedTokensText = Convert.ToBase64String(cachedTokens);
_authProperties.Items[TokenCacheKey] = cachedTokensText;
_httpContext.Authentication.SignInAsync(_signInScheme, _principal, _authProperties).Wait();
_httpContext.SignInAsync(_signInScheme, _principal, _authProperties).Wait();
}
}

Expand Down
85 changes: 44 additions & 41 deletions samples/OpenIdConnect.AzureAdSample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
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.Authentication;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -37,10 +37,42 @@ public Startup(IHostingEnvironment env)

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.AddCookieAuthentication();

services.AddOpenIdConnectAuthentication(o =>
{
o.ClientId = ClientId;
o.ClientSecret = ClientSecret; // for code flow
o.Authority = Authority;
o.ResponseType = OpenIdConnectResponseType.CodeIdToken;
o.PostLogoutRedirectUri = "/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);
}
};
});

services.AddAuthentication(sharedOptions =>
sharedOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
sharedOptions.DefaultAuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme);
}

public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
Expand Down Expand Up @@ -69,36 +101,7 @@ public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
}
});

app.UseCookieAuthentication(new CookieAuthenticationOptions());

var clientId = Configuration["oidc:clientid"];
var clientSecret = Configuration["oidc:clientsecret"];
var authority = Configuration["oidc:authority"];
var resource = "https://graph.windows.net";
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = clientId,
ClientSecret = clientSecret, // for code flow
Authority = authority,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
PostLogoutRedirectUri = "/signed-out",
// GetClaimsFromUserInfoEndpoint = true,
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);
}
}
});
app.UseAuthentication();

app.Run(async context =>
{
Expand All @@ -111,13 +114,13 @@ public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
return;
}

await context.Authentication.ChallengeAsync(
await context.ChallengeAsync(
OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties { RedirectUri = "/" });
}
else if (context.Request.Path.Equals("/signout"))
{
await context.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await WriteHtmlAsync(context.Response,
async response =>
{
Expand All @@ -127,8 +130,8 @@ await WriteHtmlAsync(context.Response,
}
else if (context.Request.Path.Equals("/signout-remote"))
{
await context.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await context.Authentication.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await context.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
}
else if (context.Request.Path.Equals("/signed-out"))
{
Expand All @@ -141,7 +144,7 @@ await WriteHtmlAsync(context.Response,
}
else if (context.Request.Path.Equals("/remote-signedout"))
{
await context.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await WriteHtmlAsync(context.Response,
async response =>
{
Expand All @@ -153,7 +156,7 @@ await WriteHtmlAsync(context.Response,
{
if (!context.User.Identities.Any(identity => identity.IsAuthenticated))
{
await context.Authentication.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties { RedirectUri = "/" });
await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties { RedirectUri = "/" });
return;
}

Expand All @@ -170,10 +173,10 @@ await WriteHtmlAsync(context.Response, async response =>
try
{
// Use ADAL to get the right token
var authContext = new AuthenticationContext(authority, AuthPropertiesTokenCache.ForApiCalls(context, CookieAuthenticationDefaults.AuthenticationScheme));
var credential = new ClientCredential(clientId, clientSecret);
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));
var result = await authContext.AcquireTokenSilentAsync(Resource, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

await response.WriteAsync($"<h3>access_token</h3><code>{HtmlEncode(result.AccessToken)}</code><br>");
}
Expand Down
Loading