diff --git a/samples/CookieSample/Startup.cs b/samples/CookieSample/Startup.cs index cff155a787..3f09191900 100644 --- a/samples/CookieSample/Startup.cs +++ b/samples/CookieSample/Startup.cs @@ -11,8 +11,7 @@ namespace CookieSample { public void ConfigureServices(IServiceCollection services) { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); } public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) diff --git a/samples/CookieSessionSample/Startup.cs b/samples/CookieSessionSample/Startup.cs index 314ff37825..0f962caeda 100644 --- a/samples/CookieSessionSample/Startup.cs +++ b/samples/CookieSessionSample/Startup.cs @@ -12,8 +12,7 @@ namespace CookieSessionSample { public void ConfigureServices(IServiceCollection services) { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); } public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) diff --git a/samples/OpenIdConnectSample/Startup.cs b/samples/OpenIdConnectSample/Startup.cs index 29b89c8240..7c1969d3bc 100644 --- a/samples/OpenIdConnectSample/Startup.cs +++ b/samples/OpenIdConnectSample/Startup.cs @@ -13,8 +13,7 @@ namespace OpenIdConnectSample { public void ConfigureServices(IServiceCollection services) { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); services.Configure(options => { options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; diff --git a/samples/SocialSample/Startup.cs b/samples/SocialSample/Startup.cs index aea458e1ad..4bfc7b6594 100644 --- a/samples/SocialSample/Startup.cs +++ b/samples/SocialSample/Startup.cs @@ -19,8 +19,7 @@ namespace CookieSample { public void ConfigureServices(IServiceCollection services) { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); services.Configure(options => { options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; @@ -139,13 +138,13 @@ namespace CookieSample OnGetUserInformationAsync = async (context) => { // Get the GitHub user - HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint); + var userRequest = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint); userRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken); userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - HttpResponseMessage userResponse = await context.Backchannel.SendAsync(userRequest, context.HttpContext.RequestAborted); + var userResponse = await context.Backchannel.SendAsync(userRequest, context.HttpContext.RequestAborted); userResponse.EnsureSuccessStatusCode(); var text = await userResponse.Content.ReadAsStringAsync(); - JObject user = JObject.Parse(text); + var user = JObject.Parse(text); var identity = new ClaimsIdentity( context.Options.AuthenticationScheme, @@ -184,7 +183,7 @@ namespace CookieSample { signoutApp.Run(async context => { - string authType = context.Request.Query["authscheme"]; + 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), diff --git a/src/Microsoft.AspNet.Authentication.Cookies/CookieAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.Cookies/CookieAuthenticationMiddleware.cs index 0a5789f7c2..2c77439320 100644 --- a/src/Microsoft.AspNet.Authentication.Cookies/CookieAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.Cookies/CookieAuthenticationMiddleware.cs @@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Authentication.Cookies [NotNull] IUrlEncoder urlEncoder, [NotNull] IOptions options, ConfigureOptions configureOptions) - : base(next, options, loggerFactory, configureOptions) + : base(next, options, loggerFactory, urlEncoder, configureOptions) { if (Options.Notifications == null) { diff --git a/src/Microsoft.AspNet.Authentication.Cookies/CookieServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Authentication.Cookies/CookieServiceCollectionExtensions.cs index c0e188eca6..af6d4d3773 100644 --- a/src/Microsoft.AspNet.Authentication.Cookies/CookieServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNet.Authentication.Cookies/CookieServiceCollectionExtensions.cs @@ -20,7 +20,6 @@ namespace Microsoft.Framework.DependencyInjection public static IServiceCollection ConfigureCookieAuthentication([NotNull] this IServiceCollection services, [NotNull] Action configure, string optionsName) { - services.AddWebEncoders(); return services.Configure(configure, optionsName); } @@ -31,7 +30,6 @@ namespace Microsoft.Framework.DependencyInjection public static IServiceCollection ConfigureCookieAuthentication([NotNull] this IServiceCollection services, [NotNull] IConfiguration config, string optionsName) { - services.AddWebEncoders(); return services.Configure(config, optionsName); } } diff --git a/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationHandler.cs b/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationHandler.cs index 246a5328ec..3f5766e50c 100644 --- a/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationHandler.cs +++ b/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationHandler.cs @@ -8,13 +8,12 @@ using System.Security.Claims; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; -using Microsoft.AspNet.Http; +using Microsoft.AspNet.Authentication.OAuth; +using Microsoft.AspNet.Http.Authentication; using Microsoft.AspNet.Http.Collections; using Microsoft.AspNet.Http.Extensions; -using Microsoft.AspNet.Http.Authentication; -using Microsoft.AspNet.Authentication.OAuth; using Microsoft.AspNet.WebUtilities; -using Microsoft.Framework.Logging; +using Microsoft.Framework.WebEncoders; using Newtonsoft.Json.Linq; namespace Microsoft.AspNet.Authentication.Facebook @@ -53,7 +52,7 @@ namespace Microsoft.AspNet.Authentication.Facebook protected override async Task GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens) { - var graphAddress = Options.UserInformationEndpoint + "?access_token=" + Uri.EscapeDataString(tokens.AccessToken); + var graphAddress = Options.UserInformationEndpoint + "?access_token=" + UrlEncoder.UrlEncode(tokens.AccessToken); if (Options.SendAppSecretProof) { graphAddress += "&appsecret_proof=" + GenerateAppSecretProof(tokens.AccessToken); diff --git a/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationMiddleware.cs index 39b0e87eae..4fa9224c9a 100644 --- a/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.Facebook/FacebookAuthenticationMiddleware.cs @@ -9,6 +9,7 @@ using Microsoft.AspNet.DataProtection; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication.Facebook { @@ -28,10 +29,11 @@ namespace Microsoft.AspNet.Authentication.Facebook [NotNull] RequestDelegate next, [NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, [NotNull] IOptions externalOptions, [NotNull] IOptions options, ConfigureOptions configureOptions = null) - : base(next, dataProtectionProvider, loggerFactory, externalOptions, options, configureOptions) + : base(next, dataProtectionProvider, loggerFactory, encoder, externalOptions, options, configureOptions) { if (string.IsNullOrWhiteSpace(Options.AppId)) { diff --git a/src/Microsoft.AspNet.Authentication.Google/GoogleAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.Google/GoogleAuthenticationMiddleware.cs index f98d659d2f..3f0bd745d7 100644 --- a/src/Microsoft.AspNet.Authentication.Google/GoogleAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.Google/GoogleAuthenticationMiddleware.cs @@ -9,6 +9,7 @@ using Microsoft.AspNet.DataProtection; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication.Google { @@ -29,10 +30,11 @@ namespace Microsoft.AspNet.Authentication.Google [NotNull] RequestDelegate next, [NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, [NotNull] IOptions externalOptions, [NotNull] IOptions options, ConfigureOptions configureOptions = null) - : base(next, dataProtectionProvider, loggerFactory, externalOptions, options, configureOptions) + : base(next, dataProtectionProvider, loggerFactory, encoder, externalOptions, options, configureOptions) { if (Options.Notifications == null) { diff --git a/src/Microsoft.AspNet.Authentication.MicrosoftAccount/MicrosoftAccountAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.MicrosoftAccount/MicrosoftAccountAuthenticationMiddleware.cs index 8978c4d1d5..06001f1830 100644 --- a/src/Microsoft.AspNet.Authentication.MicrosoftAccount/MicrosoftAccountAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.MicrosoftAccount/MicrosoftAccountAuthenticationMiddleware.cs @@ -7,6 +7,7 @@ using Microsoft.AspNet.DataProtection; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication.MicrosoftAccount { @@ -26,10 +27,11 @@ namespace Microsoft.AspNet.Authentication.MicrosoftAccount [NotNull] RequestDelegate next, [NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, [NotNull] IOptions externalOptions, [NotNull] IOptions options, ConfigureOptions configureOptions = null) - : base(next, dataProtectionProvider, loggerFactory, externalOptions, options, configureOptions) + : base(next, dataProtectionProvider, loggerFactory, encoder, externalOptions, options, configureOptions) { if (Options.Notifications == null) { diff --git a/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs index 9a211ef242..3188a1bd90 100644 --- a/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs @@ -11,6 +11,7 @@ using Microsoft.AspNet.DataProtection; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication.OAuth { @@ -33,10 +34,11 @@ namespace Microsoft.AspNet.Authentication.OAuth [NotNull] RequestDelegate next, [NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, [NotNull] IOptions externalOptions, [NotNull] IOptions options, ConfigureOptions configureOptions = null) - : base(next, options, loggerFactory, configureOptions) + : base(next, options, loggerFactory, encoder, configureOptions) { // todo: review error handling if (string.IsNullOrWhiteSpace(Options.AuthenticationScheme)) diff --git a/src/Microsoft.AspNet.Authentication.OAuthBearer/OAuthBearerAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.OAuthBearer/OAuthBearerAuthenticationMiddleware.cs index a18bbee935..1bde86c83a 100644 --- a/src/Microsoft.AspNet.Authentication.OAuthBearer/OAuthBearerAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.OAuthBearer/OAuthBearerAuthenticationMiddleware.cs @@ -11,6 +11,7 @@ using Microsoft.AspNet.Builder; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; using Microsoft.IdentityModel.Protocols; namespace Microsoft.AspNet.Authentication.OAuthBearer @@ -32,9 +33,10 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer public OAuthBearerAuthenticationMiddleware( [NotNull] RequestDelegate next, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, [NotNull] IOptions options, ConfigureOptions configureOptions) - : base(next, options, loggerFactory, configureOptions) + : base(next, options, loggerFactory, encoder, configureOptions) { if (Options.Notifications == null) { diff --git a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationHandler.cs b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationHandler.cs index 75914cc7bb..25af5a4a0c 100644 --- a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationHandler.cs +++ b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationHandler.cs @@ -180,7 +180,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect ResponseMode = Options.ResponseMode, ResponseType = Options.ResponseType, Scope = Options.Scope, - State = OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey + "=" + Uri.EscapeDataString(Options.StateDataFormat.Protect(properties)) + State = OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey + "=" + UrlEncoder.UrlEncode(Options.StateDataFormat.Protect(properties)) }; if (Options.ProtocolValidator.RequireNonce) diff --git a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs index 46524c17ce..70e45d0c2d 100644 --- a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs @@ -17,6 +17,7 @@ using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; using Microsoft.IdentityModel.Protocols; using Microsoft.Framework.Internal; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication.OpenIdConnect { @@ -40,10 +41,11 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect [NotNull] RequestDelegate next, [NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, [NotNull] IOptions externalOptions, [NotNull] IOptions options, ConfigureOptions configureOptions = null) - : base(next, options, loggerFactory, configureOptions) + : base(next, options, loggerFactory, encoder, configureOptions) { if (string.IsNullOrEmpty(Options.SignInScheme) && !string.IsNullOrEmpty(externalOptions.Options.SignInScheme)) { diff --git a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationHandler.cs b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationHandler.cs index cbc48910c3..6df6fc1a80 100644 --- a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationHandler.cs +++ b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationHandler.cs @@ -244,7 +244,7 @@ namespace Microsoft.AspNet.Authentication.Twitter var parameterBuilder = new StringBuilder(); foreach (var authorizationKey in authorizationParts) { - parameterBuilder.AppendFormat("{0}={1}&", Uri.EscapeDataString(authorizationKey.Key), Uri.EscapeDataString(authorizationKey.Value)); + parameterBuilder.AppendFormat("{0}={1}&", UrlEncoder.UrlEncode(authorizationKey.Key), UrlEncoder.UrlEncode(authorizationKey.Value)); } parameterBuilder.Length--; var parameterString = parameterBuilder.ToString(); @@ -252,9 +252,9 @@ namespace Microsoft.AspNet.Authentication.Twitter var canonicalizedRequestBuilder = new StringBuilder(); canonicalizedRequestBuilder.Append(HttpMethod.Post.Method); canonicalizedRequestBuilder.Append("&"); - canonicalizedRequestBuilder.Append(Uri.EscapeDataString(RequestTokenEndpoint)); + canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(RequestTokenEndpoint)); canonicalizedRequestBuilder.Append("&"); - canonicalizedRequestBuilder.Append(Uri.EscapeDataString(parameterString)); + canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(parameterString)); var signature = ComputeSignature(consumerSecret, null, canonicalizedRequestBuilder.ToString()); authorizationParts.Add("oauth_signature", signature); @@ -264,7 +264,7 @@ namespace Microsoft.AspNet.Authentication.Twitter foreach (var authorizationPart in authorizationParts) { authorizationHeaderBuilder.AppendFormat( - "{0}=\"{1}\", ", authorizationPart.Key, Uri.EscapeDataString(authorizationPart.Value)); + "{0}=\"{1}\", ", authorizationPart.Key, UrlEncoder.UrlEncode(authorizationPart.Value)); } authorizationHeaderBuilder.Length = authorizationHeaderBuilder.Length - 2; @@ -306,7 +306,7 @@ namespace Microsoft.AspNet.Authentication.Twitter var parameterBuilder = new StringBuilder(); foreach (var authorizationKey in authorizationParts) { - parameterBuilder.AppendFormat("{0}={1}&", Uri.EscapeDataString(authorizationKey.Key), Uri.EscapeDataString(authorizationKey.Value)); + parameterBuilder.AppendFormat("{0}={1}&", UrlEncoder.UrlEncode(authorizationKey.Key), UrlEncoder.UrlEncode(authorizationKey.Value)); } parameterBuilder.Length--; var parameterString = parameterBuilder.ToString(); @@ -314,9 +314,9 @@ namespace Microsoft.AspNet.Authentication.Twitter var canonicalizedRequestBuilder = new StringBuilder(); canonicalizedRequestBuilder.Append(HttpMethod.Post.Method); canonicalizedRequestBuilder.Append("&"); - canonicalizedRequestBuilder.Append(Uri.EscapeDataString(AccessTokenEndpoint)); + canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(AccessTokenEndpoint)); canonicalizedRequestBuilder.Append("&"); - canonicalizedRequestBuilder.Append(Uri.EscapeDataString(parameterString)); + canonicalizedRequestBuilder.Append(UrlEncoder.UrlEncode(parameterString)); var signature = ComputeSignature(consumerSecret, token.TokenSecret, canonicalizedRequestBuilder.ToString()); authorizationParts.Add("oauth_signature", signature); @@ -327,7 +327,7 @@ namespace Microsoft.AspNet.Authentication.Twitter foreach (var authorizationPart in authorizationParts) { authorizationHeaderBuilder.AppendFormat( - "{0}=\"{1}\", ", authorizationPart.Key, Uri.EscapeDataString(authorizationPart.Value)); + "{0}=\"{1}\", ", authorizationPart.Key, UrlEncoder.UrlEncode(authorizationPart.Value)); } authorizationHeaderBuilder.Length = authorizationHeaderBuilder.Length - 2; @@ -367,15 +367,15 @@ namespace Microsoft.AspNet.Authentication.Twitter return Convert.ToInt64(secondsSinceUnixEpocStart.TotalSeconds).ToString(CultureInfo.InvariantCulture); } - private static string ComputeSignature(string consumerSecret, string tokenSecret, string signatureData) + private string ComputeSignature(string consumerSecret, string tokenSecret, string signatureData) { using (var algorithm = new HMACSHA1()) { algorithm.Key = Encoding.ASCII.GetBytes( string.Format(CultureInfo.InvariantCulture, "{0}&{1}", - Uri.EscapeDataString(consumerSecret), - string.IsNullOrEmpty(tokenSecret) ? string.Empty : Uri.EscapeDataString(tokenSecret))); + UrlEncoder.UrlEncode(consumerSecret), + string.IsNullOrEmpty(tokenSecret) ? string.Empty : UrlEncoder.UrlEncode(tokenSecret))); var hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(signatureData)); return Convert.ToBase64String(hash); } diff --git a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs index 145cf4cad9..c1d2661635 100644 --- a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs @@ -13,6 +13,7 @@ using Microsoft.AspNet.DataProtection; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication.Twitter { @@ -36,10 +37,11 @@ namespace Microsoft.AspNet.Authentication.Twitter [NotNull] RequestDelegate next, [NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, [NotNull] IOptions externalOptions, [NotNull] IOptions options, ConfigureOptions configureOptions = null) - : base(next, options, loggerFactory, configureOptions) + : base(next, options, loggerFactory, encoder, configureOptions) { if (string.IsNullOrWhiteSpace(Options.ConsumerSecret)) { diff --git a/src/Microsoft.AspNet.Authentication/AuthenticationHandler.cs b/src/Microsoft.AspNet.Authentication/AuthenticationHandler.cs index 7d412d28ae..fed4778780 100644 --- a/src/Microsoft.AspNet.Authentication/AuthenticationHandler.cs +++ b/src/Microsoft.AspNet.Authentication/AuthenticationHandler.cs @@ -10,6 +10,7 @@ using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Authentication; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication { @@ -50,6 +51,8 @@ namespace Microsoft.AspNet.Authentication protected ILogger Logger { get; private set; } + protected IUrlEncoder UrlEncoder { get; private set; } + internal AuthenticationOptions BaseOptions { get { return _baseOptions; } @@ -61,12 +64,13 @@ namespace Microsoft.AspNet.Authentication public bool Faulted { get; set; } - protected async Task BaseInitializeAsync([NotNull] AuthenticationOptions options, [NotNull] HttpContext context, [NotNull] ILogger logger) + protected async Task BaseInitializeAsync([NotNull] AuthenticationOptions options, [NotNull] HttpContext context, [NotNull] ILogger logger, [NotNull] IUrlEncoder encoder) { _baseOptions = options; Context = context; RequestPathBase = Request.PathBase; Logger = logger; + UrlEncoder = encoder; RegisterAuthenticationHandler(); diff --git a/src/Microsoft.AspNet.Authentication/AuthenticationHandler`1.cs b/src/Microsoft.AspNet.Authentication/AuthenticationHandler`1.cs index 973f9f00fa..1c59b3573d 100644 --- a/src/Microsoft.AspNet.Authentication/AuthenticationHandler`1.cs +++ b/src/Microsoft.AspNet.Authentication/AuthenticationHandler`1.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.Framework.Logging; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication { @@ -22,10 +23,10 @@ namespace Microsoft.AspNet.Authentication /// The utility object to observe the current request and response /// The logging factory used to create loggers /// async completion - public Task Initialize(TOptions options, HttpContext context, ILogger logger) + public Task Initialize(TOptions options, HttpContext context, ILogger logger, IUrlEncoder encoder) { Options = options; - return BaseInitializeAsync(options, context, logger); + return BaseInitializeAsync(options, context, logger, encoder); } } } diff --git a/src/Microsoft.AspNet.Authentication/AuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication/AuthenticationMiddleware.cs index cdb6fbdf8a..a70927f504 100644 --- a/src/Microsoft.AspNet.Authentication/AuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication/AuthenticationMiddleware.cs @@ -8,6 +8,7 @@ using Microsoft.AspNet.Http; using Microsoft.Framework.Internal; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; namespace Microsoft.AspNet.Authentication { @@ -19,6 +20,7 @@ namespace Microsoft.AspNet.Authentication [NotNull] RequestDelegate next, [NotNull] IOptions options, [NotNull] ILoggerFactory loggerFactory, + [NotNull] IUrlEncoder encoder, ConfigureOptions configureOptions) { if (configureOptions != null) @@ -31,6 +33,7 @@ namespace Microsoft.AspNet.Authentication Options = options.Options; } Logger = loggerFactory.CreateLogger(this.GetType().FullName); + UrlEncoder = encoder; _next = next; } @@ -41,10 +44,12 @@ namespace Microsoft.AspNet.Authentication public ILogger Logger { get; set; } + public IUrlEncoder UrlEncoder { get; set; } + public async Task Invoke(HttpContext context) { var handler = CreateHandler(); - await handler.Initialize(Options, context, Logger); + await handler.Initialize(Options, context, Logger, UrlEncoder); try { if (!await handler.InvokeAsync()) diff --git a/src/Microsoft.AspNet.Authentication/AuthenticationServiceCollectionExtensions.cs b/src/Microsoft.AspNet.Authentication/AuthenticationServiceCollectionExtensions.cs index 43c0a7426b..705ae6227e 100644 --- a/src/Microsoft.AspNet.Authentication/AuthenticationServiceCollectionExtensions.cs +++ b/src/Microsoft.AspNet.Authentication/AuthenticationServiceCollectionExtensions.cs @@ -3,7 +3,6 @@ using System; using System.Security.Claims; -using System.Threading.Tasks; using Microsoft.AspNet.Authentication; using Microsoft.Framework.Internal; @@ -11,6 +10,13 @@ namespace Microsoft.Framework.DependencyInjection { public static class AuthenticationServiceCollectionExtensions { + public static IServiceCollection AddAuthentication([NotNull] this IServiceCollection services) + { + services.AddWebEncoders(); + services.AddDataProtection(); + return services; + } + public static IServiceCollection ConfigureClaimsTransformation([NotNull] this IServiceCollection services, [NotNull] Action configure) { return services.Configure(configure); diff --git a/src/Microsoft.AspNet.Authentication/project.json b/src/Microsoft.AspNet.Authentication/project.json index a28d27e07a..31f0338615 100644 --- a/src/Microsoft.AspNet.Authentication/project.json +++ b/src/Microsoft.AspNet.Authentication/project.json @@ -2,12 +2,13 @@ "version": "1.0.0-*", "description": "ASP.NET 5 common types used by the various authentication middleware.", "dependencies": { - "Microsoft.AspNet.DataProtection.Interfaces": "1.0.0-*", + "Microsoft.AspNet.DataProtection": "1.0.0-*", "Microsoft.AspNet.Http": "1.0.0-*", "Microsoft.AspNet.Http.Extensions": "1.0.0-*", "Microsoft.Framework.Logging.Interfaces": "1.0.0-*", "Microsoft.Framework.NotNullAttribute.Internal": { "type": "build", "version": "1.0.0-*" }, - "Microsoft.Framework.OptionsModel": "1.0.0-*" + "Microsoft.Framework.OptionsModel": "1.0.0-*", + "Microsoft.Framework.WebEncoders": "1.0.0-*" }, "frameworks": { "dnx451": { }, diff --git a/test/Microsoft.AspNet.Authentication.Test/AuthenticationHandlerFacts.cs b/test/Microsoft.AspNet.Authentication.Test/AuthenticationHandlerFacts.cs index cf628db547..f5428f1a36 100644 --- a/test/Microsoft.AspNet.Authentication.Test/AuthenticationHandlerFacts.cs +++ b/test/Microsoft.AspNet.Authentication.Test/AuthenticationHandlerFacts.cs @@ -55,7 +55,7 @@ namespace Microsoft.AspNet.Authentication { public TestHandler(string scheme) { - Initialize(new TestOptions(), new DefaultHttpContext(), new LoggerFactory().CreateLogger("TestHandler")); + Initialize(new TestOptions(), new DefaultHttpContext(), new LoggerFactory().CreateLogger("TestHandler"), Framework.WebEncoders.UrlEncoder.Default); Options.AuthenticationScheme = scheme; } @@ -89,7 +89,7 @@ namespace Microsoft.AspNet.Authentication { public TestAutoHandler(string scheme, bool auto) { - Initialize(new TestAutoOptions(), new DefaultHttpContext(), new LoggerFactory().CreateLogger("TestHandler")); + Initialize(new TestAutoOptions(), new DefaultHttpContext(), new LoggerFactory().CreateLogger("TestHandler"), Framework.WebEncoders.UrlEncoder.Default); Options.AuthenticationScheme = scheme; Options.AutomaticAuthentication = auto; } diff --git a/test/Microsoft.AspNet.Authentication.Test/Cookies/CookieMiddlewareTests.cs b/test/Microsoft.AspNet.Authentication.Test/Cookies/CookieMiddlewareTests.cs index cd2483119f..9c1ac2fdd6 100644 --- a/test/Microsoft.AspNet.Authentication.Test/Cookies/CookieMiddlewareTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/Cookies/CookieMiddlewareTests.cs @@ -573,8 +573,7 @@ namespace Microsoft.AspNet.Authentication.Cookies }, services => { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); if (claimsTransform != null) { services.ConfigureClaimsTransformation(claimsTransform); diff --git a/test/Microsoft.AspNet.Authentication.Test/Google/GoogleMiddlewareTests.cs b/test/Microsoft.AspNet.Authentication.Test/Google/GoogleMiddlewareTests.cs index 76db1debbd..6ed8a1734b 100644 --- a/test/Microsoft.AspNet.Authentication.Test/Google/GoogleMiddlewareTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/Google/GoogleMiddlewareTests.cs @@ -109,7 +109,7 @@ namespace Microsoft.AspNet.Authentication.Google var transaction = await SendAsync(server, "https://example.com/challenge"); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); var query = transaction.Response.Headers.Location.Query; - query.ShouldContain("&scope=" + Uri.EscapeDataString("openid profile email")); + query.ShouldContain("&scope=" + UrlEncoder.Default.UrlEncode("openid profile email")); } [Fact] @@ -124,7 +124,7 @@ namespace Microsoft.AspNet.Authentication.Google var transaction = await SendAsync(server, "https://example.com/401"); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); var query = transaction.Response.Headers.Location.Query; - query.ShouldContain("&scope=" + Uri.EscapeDataString("openid profile email")); + query.ShouldContain("&scope=" + UrlEncoder.Default.UrlEncode("openid profile email")); } [Fact] @@ -231,7 +231,7 @@ namespace Microsoft.AspNet.Authentication.Google [Fact] public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState() { - ISecureDataFormat stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); + var stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); var server = CreateServer(options => { options.ClientId = "Test Id"; @@ -284,7 +284,7 @@ namespace Microsoft.AspNet.Authentication.Google properties.RedirectUri = "/me"; var state = stateFormat.Protect(properties); var transaction = await SendAsync(server, - "https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state), + "https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state), correlationKey + "=" + correlationValue); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); transaction.Response.Headers.Location.ToString().ShouldBe("/me"); @@ -308,7 +308,7 @@ namespace Microsoft.AspNet.Authentication.Google [Fact] public async Task ReplyPathWillRejectIfCodeIsInvalid() { - ISecureDataFormat stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); + var stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); var server = CreateServer(options => { options.ClientId = "Test Id"; @@ -329,7 +329,7 @@ namespace Microsoft.AspNet.Authentication.Google properties.RedirectUri = "/me"; var state = stateFormat.Protect(properties); var transaction = await SendAsync(server, - "https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state), + "https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state), correlationKey + "=" + correlationValue); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); transaction.Response.Headers.Location.ToString().ShouldContain("error=access_denied"); @@ -338,7 +338,7 @@ namespace Microsoft.AspNet.Authentication.Google [Fact] public async Task ReplyPathWillRejectIfAccessTokenIsMissing() { - ISecureDataFormat stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); + var stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); var server = CreateServer(options => { options.ClientId = "Test Id"; @@ -359,7 +359,7 @@ namespace Microsoft.AspNet.Authentication.Google properties.RedirectUri = "/me"; var state = stateFormat.Protect(properties); var transaction = await SendAsync(server, - "https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state), + "https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state), correlationKey + "=" + correlationValue); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); transaction.Response.Headers.Location.ToString().ShouldContain("error=access_denied"); @@ -368,7 +368,7 @@ namespace Microsoft.AspNet.Authentication.Google [Fact] public async Task AuthenticatedEventCanGetRefreshToken() { - ISecureDataFormat stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); + var stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest")); var server = CreateServer(options => { options.ClientId = "Test Id"; @@ -431,7 +431,7 @@ namespace Microsoft.AspNet.Authentication.Google properties.RedirectUri = "/me"; var state = stateFormat.Protect(properties); var transaction = await SendAsync(server, - "https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state), + "https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state), correlationKey + "=" + correlationValue); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); transaction.Response.Headers.Location.ToString().ShouldBe("/me"); @@ -532,8 +532,7 @@ namespace Microsoft.AspNet.Authentication.Google }, services => { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); services.Configure(options => { options.SignInScheme = CookieAuthenticationScheme; @@ -614,7 +613,7 @@ namespace Microsoft.AspNet.Authentication.Google public string FindClaimValue(string claimType) { - XElement claim = ResponseElement.Elements("claim").SingleOrDefault(elt => elt.Attribute("type").Value == claimType); + var claim = ResponseElement.Elements("claim").SingleOrDefault(elt => elt.Attribute("type").Value == claimType); if (claim == null) { return null; diff --git a/test/Microsoft.AspNet.Authentication.Test/Microsoft.AspNet.Authentication.Test.xproj b/test/Microsoft.AspNet.Authentication.Test/Microsoft.AspNet.Authentication.Test.xproj index 3bcf72482b..aaf23b99e3 100644 --- a/test/Microsoft.AspNet.Authentication.Test/Microsoft.AspNet.Authentication.Test.xproj +++ b/test/Microsoft.AspNet.Authentication.Test/Microsoft.AspNet.Authentication.Test.xproj @@ -13,5 +13,8 @@ 2.0 + + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs b/test/Microsoft.AspNet.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs index 7ea8482072..28ca0ecc94 100644 --- a/test/Microsoft.AspNet.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs @@ -19,6 +19,7 @@ using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Authentication; using Microsoft.AspNet.TestHost; using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.WebEncoders; using Newtonsoft.Json; using Shouldly; using Xunit; @@ -143,7 +144,7 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount properties.RedirectUri = "/me"; var state = stateFormat.Protect(properties); var transaction = await SendAsync(server, - "https://example.com/signin-microsoft?code=TestCode&state=" + Uri.EscapeDataString(state), + "https://example.com/signin-microsoft?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state), correlationKey + "=" + correlationValue); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); transaction.Response.Headers.Location.ToString().ShouldBe("/me"); @@ -177,8 +178,7 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount }, services => { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); services.Configure(options => { options.SignInScheme = "External"; diff --git a/test/Microsoft.AspNet.Authentication.Test/OAuthBearer/OAuthBearerMiddlewareTests.cs b/test/Microsoft.AspNet.Authentication.Test/OAuthBearer/OAuthBearerMiddlewareTests.cs index e688497d9e..2fd8bb4226 100644 --- a/test/Microsoft.AspNet.Authentication.Test/OAuthBearer/OAuthBearerMiddlewareTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/OAuthBearer/OAuthBearerMiddlewareTests.cs @@ -336,7 +336,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer } }); }, - services => services.AddDataProtection()); + services => services.AddAuthentication()); } private static async Task SendAsync(TestServer server, string uri, string authorizationHeader = null) diff --git a/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectHandlerTests.cs b/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectHandlerTests.cs index c3dbece13b..1974373470 100644 --- a/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectHandlerTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectHandlerTests.cs @@ -20,6 +20,7 @@ using Microsoft.AspNet.TestHost; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Logging; using Microsoft.Framework.OptionsModel; +using Microsoft.Framework.WebEncoders; using Microsoft.IdentityModel.Protocols; using Shouldly; using Xunit; @@ -115,7 +116,7 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect var propertiesFormatter = new AuthenticationPropertiesFormater(); var protectedProperties = propertiesFormatter.Protect(new AuthenticationProperties()); - var state = OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey + "=" + Uri.EscapeDataString(protectedProperties); + var state = OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey + "=" + UrlEncoder.Default.UrlEncode(protectedProperties); var code = Guid.NewGuid().ToString(); var message = new OpenIdConnectMessage @@ -565,9 +566,9 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect /// public class CustomOpenIdConnectAuthenticationHandler : OpenIdConnectAuthenticationHandler { - public async Task BaseInitializeAsyncPublic(AuthenticationOptions options, HttpContext context, ILogger logger) + public async Task BaseInitializeAsyncPublic(AuthenticationOptions options, HttpContext context, ILogger logger, IUrlEncoder encoder) { - await base.BaseInitializeAsync(options, context, logger); + await base.BaseInitializeAsync(options, context, logger, encoder); } public override bool ShouldHandleScheme(string authenticationScheme) @@ -603,11 +604,12 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, + IUrlEncoder encoder, IOptions externalOptions, IOptions options, ConfigureOptions configureOptions = null ) - : base(next, dataProtectionProvider, loggerFactory, externalOptions, options, configureOptions) + : base(next, dataProtectionProvider, loggerFactory, encoder, externalOptions, options, configureOptions) { Logger = (loggerFactory as CustomLoggerFactory).Logger; } diff --git a/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectMiddlewareTests.cs b/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectMiddlewareTests.cs index 6abc8aa946..85e74e19a5 100644 --- a/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectMiddlewareTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/OpenIdConnect/OpenIdConnectMiddlewareTests.cs @@ -22,6 +22,7 @@ using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Authentication; using Microsoft.AspNet.TestHost; using Microsoft.Framework.DependencyInjection; +using Microsoft.Framework.WebEncoders; using Newtonsoft.Json; using Shouldly; using Xunit; @@ -75,7 +76,7 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect }); var transaction = await SendAsync(server, "https://example.com/challenge"); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); - transaction.Response.Headers.Location.Query.ShouldContain("&scope=" + Uri.EscapeDataString("openid profile")); + transaction.Response.Headers.Location.Query.ShouldContain("&scope=" + UrlEncoder.Default.UrlEncode("openid profile")); } [Fact] @@ -92,8 +93,8 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect var transaction = await SendAsync(server, "https://example.com/challenge"); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); var query = transaction.Response.Headers.Location.Query; - query.ShouldContain("scope=" + Uri.EscapeDataString("https://www.googleapis.com/auth/plus.login")); - query.ShouldContain("response_type=" + Uri.EscapeDataString("id_token")); + query.ShouldContain("scope=" + UrlEncoder.Default.UrlEncode("https://www.googleapis.com/auth/plus.login")); + query.ShouldContain("response_type=" + UrlEncoder.Default.UrlEncode("id_token")); } [Fact] @@ -148,7 +149,7 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect var transaction = await SendAsync(server, "https://example.com/signout"); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); - transaction.Response.Headers.Location.AbsoluteUri.ShouldContain(Uri.EscapeDataString("https://example.com/logout")); + transaction.Response.Headers.Location.AbsoluteUri.ShouldContain(UrlEncoder.Default.UrlEncode("https://example.com/logout")); } [Fact] @@ -163,7 +164,7 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect var transaction = await SendAsync(server, "https://example.com/signout_with_specific_redirect_uri"); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect); - transaction.Response.Headers.Location.AbsoluteUri.ShouldContain(Uri.EscapeDataString("http://www.example.com/specific_redirect_uri")); + transaction.Response.Headers.Location.AbsoluteUri.ShouldContain(UrlEncoder.Default.UrlEncode("http://www.example.com/specific_redirect_uri")); } [Fact] @@ -234,8 +235,7 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect }, services => { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); services.Configure(options => { options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; diff --git a/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs b/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs index d4f6fd24a7..bca10fbf44 100644 --- a/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs @@ -123,8 +123,7 @@ namespace Microsoft.AspNet.Authentication.Twitter }, services => { - services.AddWebEncoders(); - services.AddDataProtection(); + services.AddAuthentication(); services.Configure(options => { options.SignInScheme = "External";