Use DI activated options for auth middlewares

UseXXX() now use DI activated options
Use ExternalAuthenticationOptions instead of DefaultSignInAs
This commit is contained in:
Hao Kung 2014-10-08 13:02:08 -07:00
parent 23c024ef41
commit 3426034bcb
41 changed files with 606 additions and 577 deletions

View File

@ -9,9 +9,9 @@ namespace CookieSample
{
public void Configure(IApplicationBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
app.UseServices(services => { });
app.UseCookieAuthentication(options =>
{
});
app.Run(async context =>

View File

@ -10,9 +10,10 @@ namespace CookieSessionSample
{
public void Configure(IApplicationBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
app.UseServices(services => { });
app.UseCookieAuthentication(options =>
{
SessionStore = new MemoryCacheSessionStore(),
options.SessionStore = new MemoryCacheSessionStore();
});
app.Run(async context =>

View File

@ -7,7 +7,7 @@
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>8c73d216-332d-41d8-bfd0-45bc4bc36552</ProjectGuid>
<OutputType>Library</OutputType>
<OutputType>Web</OutputType>
</PropertyGroup>
<PropertyGroup Condition="$(OutputType) == 'Console'">
<DebuggerFlavor>ConsoleDebugger</DebuggerFlavor>
@ -21,6 +21,7 @@
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<DevelopmentServerPort>50113</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -14,6 +14,7 @@ using Microsoft.AspNet.Security.MicrosoftAccount;
using Microsoft.AspNet.Security.OAuth;
using Microsoft.AspNet.Security.Twitter;
using Newtonsoft.Json.Linq;
using Microsoft.Framework.DependencyInjection;
namespace CookieSample
{
@ -23,39 +24,48 @@ namespace CookieSample
{
app.UseErrorPage();
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
app.UseServices(services =>
{
LoginPath = new PathString("/login"),
services.ConfigureOptions<ExternalAuthenticationOptions>(options =>
{
options.SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType;
});
});
app.UseFacebookAuthentication(new FacebookAuthenticationOptions()
app.UseCookieAuthentication(options =>
{
options.LoginPath = new PathString("/login");
});
app.UseFacebookAuthentication(options =>
{
AppId = "569522623154478",
AppSecret = "a124463c4719c94b4228d9a240e5dc1a",
options.AppId = "569522623154478";
options.AppSecret = "a124463c4719c94b4228d9a240e5dc1a";
});
app.UseOAuthAuthentication(new OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>("Google-AccessToken")
app.UseOAuthAuthentication("Google-AccessToken", options =>
{
ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com",
ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f",
CallbackPath = new PathString("/signin-google-token"),
AuthorizationEndpoint = GoogleAuthenticationDefaults.AuthorizationEndpoint,
TokenEndpoint = GoogleAuthenticationDefaults.TokenEndpoint,
Scope = { "openid", "profile", "email" },
options.ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com";
options.ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f";
options.CallbackPath = new PathString("/signin-google-token");
options.AuthorizationEndpoint = GoogleAuthenticationDefaults.AuthorizationEndpoint;
options.TokenEndpoint = GoogleAuthenticationDefaults.TokenEndpoint;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
});
app.UseGoogleAuthentication(new GoogleAuthenticationOptions()
app.UseGoogleAuthentication(options =>
{
ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com",
ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f",
options.ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com";
options.ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f";
});
app.UseTwitterAuthentication(new TwitterAuthenticationOptions()
app.UseTwitterAuthentication(options =>
{
ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g",
ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI",
options.ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g";
options.ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI";
});
/*
@ -75,43 +85,43 @@ namespace CookieSample
The sample app can then be run via:
k web
*/
app.UseOAuthAuthentication(new OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>("Microsoft-AccessToken")
app.UseOAuthAuthentication("Microsoft-AccessToken", options =>
{
Caption = "MicrosoftAccount-AccessToken - Requires project changes",
ClientId = "00000000480FF62E",
ClientSecret = "bLw2JIvf8Y1TaToipPEqxTVlOeJwCUsr",
CallbackPath = new PathString("/signin-microsoft-token"),
AuthorizationEndpoint = MicrosoftAccountAuthenticationDefaults.AuthorizationEndpoint,
TokenEndpoint = MicrosoftAccountAuthenticationDefaults.TokenEndpoint,
Scope = { "wl.basic" },
options.Caption = "MicrosoftAccount-AccessToken - Requires project changes";
options.ClientId = "00000000480FF62E";
options.ClientSecret = "bLw2JIvf8Y1TaToipPEqxTVlOeJwCUsr";
options.CallbackPath = new PathString("/signin-microsoft-token");
options.AuthorizationEndpoint = MicrosoftAccountAuthenticationDefaults.AuthorizationEndpoint;
options.TokenEndpoint = MicrosoftAccountAuthenticationDefaults.TokenEndpoint;
options.Scope.Add("wl.basic");
});
app.UseMicrosoftAccountAuthentication(new MicrosoftAccountAuthenticationOptions()
app.UseMicrosoftAccountAuthentication(options =>
{
Caption = "MicrosoftAccount - Requires project changes",
ClientId = "00000000480FF62E",
ClientSecret = "bLw2JIvf8Y1TaToipPEqxTVlOeJwCUsr",
options.Caption = "MicrosoftAccount - Requires project changes";
options.ClientId = "00000000480FF62E";
options.ClientSecret = "bLw2JIvf8Y1TaToipPEqxTVlOeJwCUsr";
});
app.UseOAuthAuthentication(new OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>("GitHub-AccessToken")
app.UseOAuthAuthentication("GitHub-AccessToken", options =>
{
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",
options.ClientId = "8c0c5a572abe8fe89588";
options.ClientSecret = "e1d95eaf03461d27acd6f49d4fc7bf19d6ac8cda";
options.CallbackPath = new PathString("/signin-github-token");
options.AuthorizationEndpoint = "https://github.com/login/oauth/authorize";
options.TokenEndpoint = "https://github.com/login/oauth/access_token";
});
app.UseOAuthAuthentication(new OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>("GitHub")
app.UseOAuthAuthentication("GitHub", options =>
{
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",
options.ClientId = "49e302895d8b09ea5656";
options.ClientSecret = "98f1bf028608901e9df91d64ee61536fe562064b";
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";
// Retrieving user information is unique to each provider.
Notifications = new OAuthAuthenticationNotifications()
options.Notifications = new OAuthAuthenticationNotifications()
{
OnGetUserInformationAsync = async (context) =>
{
@ -153,7 +163,7 @@ namespace CookieSample
context.Identity = identity;
},
},
};
});
// Choose an authentication type

View File

@ -8,7 +8,8 @@
"Microsoft.AspNet.Security.MicrosoftAccount": "1.0.0-*",
"Microsoft.AspNet.Security.Twitter": "1.0.0-*",
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
"Microsoft.Framework.DependencyInjection": "1.0.0-*"
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*"
},
"commands": { "web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:12345" },
"frameworks": {

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Security.Cookies;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using System;
namespace Microsoft.AspNet.Builder
{
@ -10,15 +13,25 @@ namespace Microsoft.AspNet.Builder
/// </summary>
public static class CookieAuthenticationExtensions
{
public static IServiceCollection ConfigureCookieAuthentication([NotNull] this IServiceCollection services, [NotNull] Action<CookieAuthenticationOptions> configure)
{
return services.ConfigureOptions(configure);
}
/// <summary>
/// Adds a cookie-based authentication middleware to your web application pipeline.
/// </summary>
/// <param name="app">The IApplicationBuilder passed to your configuration method</param>
/// <param name="options">An options class that controls the middleware behavior</param>
/// <param name="configureOptions">Used to configure the options for the middleware</param>
/// <param name="optionsName">The name of the options class that controls the middleware behavior, null will use the default options</param>
/// <returns>The original app parameter</returns>
public static IApplicationBuilder UseCookieAuthentication([NotNull] this IApplicationBuilder app, [NotNull] CookieAuthenticationOptions options)
public static IApplicationBuilder UseCookieAuthentication([NotNull] this IApplicationBuilder app, Action<CookieAuthenticationOptions> configureOptions = null, string optionsName = "")
{
return app.UseMiddleware<CookieAuthenticationMiddleware>(options);
return app.UseMiddleware<CookieAuthenticationMiddleware>(
new OptionsAction<CookieAuthenticationOptions>(configureOptions ?? (o => { }))
{
Name = optionsName
});
}
}
}

View File

@ -9,6 +9,7 @@ using Microsoft.AspNet.Security.DataHandler;
using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Security.Cookies
{
@ -16,8 +17,12 @@ namespace Microsoft.AspNet.Security.Cookies
{
private readonly ILogger _logger;
public CookieAuthenticationMiddleware(RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, CookieAuthenticationOptions options)
: base(next, options)
public CookieAuthenticationMiddleware(RequestDelegate next,
IDataProtectionProvider dataProtectionProvider,
ILoggerFactory loggerFactory,
IOptionsAccessor<CookieAuthenticationOptions> options,
IOptionsAction<CookieAuthenticationOptions> configureOptions)
: base(next, options, configureOptions)
{
if (Options.Notifications == null)
{
@ -27,11 +32,11 @@ namespace Microsoft.AspNet.Security.Cookies
{
Options.CookieName = CookieAuthenticationDefaults.CookiePrefix + Options.AuthenticationType;
}
if (options.TicketDataFormat == null)
if (Options.TicketDataFormat == null)
{
IDataProtector dataProtector = DataProtectionHelpers.CreateDataProtector(dataProtectionProvider,
typeof(CookieAuthenticationMiddleware).FullName, options.AuthenticationType, "v1");
options.TicketDataFormat = new TicketDataFormat(dataProtector);
typeof(CookieAuthenticationMiddleware).FullName, Options.AuthenticationType, "v1");
Options.TicketDataFormat = new TicketDataFormat(dataProtector);
}
if (Options.CookieManager == null)
{

View File

@ -21,8 +21,8 @@ namespace Microsoft.AspNet.Security.Cookies
/// Create an instance of the options initialized with the default values
/// </summary>
public CookieAuthenticationOptions()
: base(CookieAuthenticationDefaults.AuthenticationType)
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType;
ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
CookiePath = "/";
ExpireTimeSpan = TimeSpan.FromDays(14);

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Security.Facebook;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using System;
namespace Microsoft.AspNet.Builder
{
@ -10,35 +13,23 @@ namespace Microsoft.AspNet.Builder
/// </summary>
public static class FacebookAuthenticationExtensions
{
/// <summary>
/// Authenticate users using Facebook.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method.</param>
/// <param name="appId">The appId assigned by Facebook.</param>
/// <param name="appSecret">The appSecret assigned by Facebook.</param>
/// <returns>The updated <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseFacebookAuthentication([NotNull] this IApplicationBuilder app, [NotNull] string appId, [NotNull] string appSecret)
public static IServiceCollection ConfigureFacebookAuthentication([NotNull] this IServiceCollection services, [NotNull] Action<FacebookAuthenticationOptions> configure)
{
return app.UseFacebookAuthentication(new FacebookAuthenticationOptions()
{
AppId = appId,
AppSecret = appSecret,
});
return services.ConfigureOptions(configure);
}
/// <summary>
/// Authenticate users using Facebook.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method.</param>
/// <param name="options">The middleware configuration options.</param>
/// <returns>The updated <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseFacebookAuthentication([NotNull] this IApplicationBuilder app, [NotNull] FacebookAuthenticationOptions options)
public static IApplicationBuilder UseFacebookAuthentication([NotNull] this IApplicationBuilder app, Action<FacebookAuthenticationOptions> configureOptions = null, string optionsName = "")
{
if (string.IsNullOrEmpty(options.SignInAsAuthenticationType))
{
options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
return app.UseMiddleware<FacebookAuthenticationMiddleware>(options);
return app.UseMiddleware<FacebookAuthenticationMiddleware>(
new OptionsAction<FacebookAuthenticationOptions>(configureOptions ?? (o => { }))
{
Name = optionsName
});
}
}
}

View File

@ -8,6 +8,7 @@ using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.AspNet.Security.OAuth;
using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Security.Facebook
{
@ -27,8 +28,10 @@ namespace Microsoft.AspNet.Security.Facebook
RequestDelegate next,
IDataProtectionProvider dataProtectionProvider,
ILoggerFactory loggerFactory,
FacebookAuthenticationOptions options)
: base(next, dataProtectionProvider, loggerFactory, options)
IOptionsAccessor<ExternalAuthenticationOptions> externalOptions,
IOptionsAccessor<FacebookAuthenticationOptions> options,
IOptionsAction<FacebookAuthenticationOptions> configureOptions = null)
: base(next, dataProtectionProvider, loggerFactory, externalOptions, options, configureOptions)
{
if (string.IsNullOrWhiteSpace(Options.AppId))
{

View File

@ -15,8 +15,9 @@ namespace Microsoft.AspNet.Security.Facebook
/// Initializes a new <see cref="FacebookAuthenticationOptions"/>.
/// </summary>
public FacebookAuthenticationOptions()
: base(FacebookAuthenticationDefaults.AuthenticationType)
{
AuthenticationType = FacebookAuthenticationDefaults.AuthenticationType;
Caption = AuthenticationType;
CallbackPath = new PathString("/signin-facebook");
SendAppSecretProof = true;
AuthorizationEndpoint = FacebookAuthenticationDefaults.AuthorizationEndpoint;

View File

@ -7,6 +7,7 @@
"Microsoft.AspNet.Security.OAuth": "1.0.0-*",
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
"Microsoft.Framework.Logging": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*",
"Newtonsoft.Json": "6.0.4"
},
"frameworks": {

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Security.Google;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using System;
namespace Microsoft.AspNet.Builder
{
@ -10,36 +13,25 @@ namespace Microsoft.AspNet.Builder
/// </summary>
public static class GoogleAuthenticationExtensions
{
/// <summary>
/// Authenticate users using Google OAuth 2.0.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method.</param>
/// <param name="clientId">The google assigned client id.</param>
/// <param name="clientSecret">The google assigned client secret.</param>
/// <returns>The updated <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseGoogleAuthentication([NotNull] this IApplicationBuilder app, [NotNull] string clientId, [NotNull] string clientSecret)
public static IServiceCollection ConfigureGoogleAuthentication([NotNull] this IServiceCollection services, [NotNull] Action<GoogleAuthenticationOptions> configure)
{
return app.UseGoogleAuthentication(
new GoogleAuthenticationOptions
{
ClientId = clientId,
ClientSecret = clientSecret
});
return services.ConfigureOptions(configure);
}
/// <summary>
/// Authenticate users using Google OAuth 2.0.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method.</param>
/// <param name="options">Middleware configuration options.</param>
/// <param name="configureOptions">Used to configure Middleware options.</param>
/// <param name="optionsName">Name of the options instance to be used</param>
/// <returns>The updated <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseGoogleAuthentication([NotNull] this IApplicationBuilder app, [NotNull] GoogleAuthenticationOptions options)
public static IApplicationBuilder UseGoogleAuthentication([NotNull] this IApplicationBuilder app, Action<GoogleAuthenticationOptions> configureOptions = null, string optionsName = "")
{
if (string.IsNullOrEmpty(options.SignInAsAuthenticationType))
{
options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
return app.UseMiddleware<GoogleAuthenticationMiddleware>(options);
return app.UseMiddleware<GoogleAuthenticationMiddleware>(
new OptionsAction<GoogleAuthenticationOptions>(configureOptions ?? (o => { }))
{
Name = optionsName
});
}
}
}

View File

@ -11,6 +11,7 @@ using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.AspNet.Security.OAuth;
using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Security.Google
{
@ -31,8 +32,10 @@ namespace Microsoft.AspNet.Security.Google
RequestDelegate next,
IDataProtectionProvider dataProtectionProvider,
ILoggerFactory loggerFactory,
GoogleAuthenticationOptions options)
: base(next, dataProtectionProvider, loggerFactory, options)
IOptionsAccessor<ExternalAuthenticationOptions> externalOptions,
IOptionsAccessor<GoogleAuthenticationOptions> options,
IOptionsAction<GoogleAuthenticationOptions> configureOptions = null)
: base(next, dataProtectionProvider, loggerFactory, externalOptions, options, configureOptions)
{
if (Options.Notifications == null)
{

View File

@ -19,8 +19,9 @@ namespace Microsoft.AspNet.Security.Google
/// Initializes a new <see cref="GoogleAuthenticationOptions"/>.
/// </summary>
public GoogleAuthenticationOptions()
: base(GoogleAuthenticationDefaults.AuthenticationType)
{
AuthenticationType = GoogleAuthenticationDefaults.AuthenticationType;
Caption = AuthenticationType;
CallbackPath = new PathString("/signin-google");
AuthorizationEndpoint = GoogleAuthenticationDefaults.AuthorizationEndpoint;
TokenEndpoint = GoogleAuthenticationDefaults.TokenEndpoint;

View File

@ -7,7 +7,8 @@
"Microsoft.AspNet.Security.OAuth": "1.0.0-*",
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
"Microsoft.Framework.Logging": "1.0.0-*",
"Newtonsoft.Json": "6.0.4"
"Microsoft.Framework.OptionsModel": "1.0.0-*",
"Newtonsoft.Json": "6.0.4",
},
"frameworks": {
"aspnet50": {

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Security.MicrosoftAccount;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using System;
namespace Microsoft.AspNet.Builder
{
@ -10,36 +13,18 @@ namespace Microsoft.AspNet.Builder
/// </summary>
public static class MicrosoftAccountAuthenticationExtensions
{
/// <summary>
/// Authenticate users using Microsoft Account.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method.</param>
/// <param name="clientId">The application client ID assigned by the Microsoft authentication service.</param>
/// <param name="clientSecret">The application client secret assigned by the Microsoft authentication service.</param>
/// <returns>The updated <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseMicrosoftAccountAuthentication([NotNull] this IApplicationBuilder app, [NotNull] string clientId, [NotNull] string clientSecret)
public static IServiceCollection ConfigureMicrosoftAccountAuthentication([NotNull] this IServiceCollection services, [NotNull] Action<MicrosoftAccountAuthenticationOptions> configure)
{
return app.UseMicrosoftAccountAuthentication(
new MicrosoftAccountAuthenticationOptions
{
ClientId = clientId,
ClientSecret = clientSecret,
});
return services.ConfigureOptions(configure);
}
/// <summary>
/// Authenticate users using Microsoft Account.
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method.</param>
/// <param name="options">The middleware configuration options.</param>
/// <returns>The updated <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseMicrosoftAccountAuthentication([NotNull] this IApplicationBuilder app, [NotNull] MicrosoftAccountAuthenticationOptions options)
public static IApplicationBuilder UseMicrosoftAccountAuthentication([NotNull] this IApplicationBuilder app, Action<MicrosoftAccountAuthenticationOptions> configureOptions = null, string optionsName = "")
{
if (string.IsNullOrEmpty(options.SignInAsAuthenticationType))
{
options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
return app.UseMiddleware<MicrosoftAccountAuthenticationMiddleware>(options);
return app.UseMiddleware<MicrosoftAccountAuthenticationMiddleware>(
new OptionsAction<MicrosoftAccountAuthenticationOptions>(configureOptions ?? (o => { }))
{
Name = optionsName
});
}
}
}

View File

@ -8,6 +8,7 @@ using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.AspNet.Security.OAuth;
using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Security.MicrosoftAccount
{
@ -27,8 +28,10 @@ namespace Microsoft.AspNet.Security.MicrosoftAccount
RequestDelegate next,
IDataProtectionProvider dataProtectionProvider,
ILoggerFactory loggerFactory,
MicrosoftAccountAuthenticationOptions options)
: base(next, dataProtectionProvider, loggerFactory, options)
IOptionsAccessor<ExternalAuthenticationOptions> externalOptions,
IOptionsAccessor<MicrosoftAccountAuthenticationOptions> options,
IOptionsAction<MicrosoftAccountAuthenticationOptions> configureOptions = null)
: base(next, dataProtectionProvider, loggerFactory, externalOptions, options, configureOptions)
{
if (Options.Notifications == null)
{

View File

@ -15,8 +15,9 @@ namespace Microsoft.AspNet.Security.MicrosoftAccount
/// Initializes a new <see cref="MicrosoftAccountAuthenticationOptions"/>.
/// </summary>
public MicrosoftAccountAuthenticationOptions()
: base(MicrosoftAccountAuthenticationDefaults.AuthenticationType)
{
AuthenticationType = MicrosoftAccountAuthenticationDefaults.AuthenticationType;
Caption = AuthenticationType;
CallbackPath = new PathString("/signin-microsoft");
AuthorizationEndpoint = MicrosoftAccountAuthenticationDefaults.AuthorizationEndpoint;
TokenEndpoint = MicrosoftAccountAuthenticationDefaults.TokenEndpoint;

View File

@ -7,6 +7,7 @@
"Microsoft.AspNet.Security.OAuth": "1.0.0-*",
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
"Microsoft.Framework.Logging": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*",
"Newtonsoft.Json": "6.0.4"
},
"frameworks": {

View File

@ -4,6 +4,8 @@
using System;
using System.Globalization;
using Microsoft.AspNet.Security.OAuth;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Builder
{
@ -18,17 +20,21 @@ namespace Microsoft.AspNet.Builder
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method.</param>
/// <param name="options">The middleware configuration options.</param>
/// <returns>The updated <see cref="IApplicationBuilder"/>.</returns>
public static IApplicationBuilder UseOAuthAuthentication([NotNull] this IApplicationBuilder app, [NotNull] OAuthAuthenticationOptions<IOAuthAuthenticationNotifications> options)
public static IApplicationBuilder UseOAuthAuthentication([NotNull] this IApplicationBuilder app, [NotNull] string authenticationType, Action<OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>> configureOptions = null)
{
if (string.IsNullOrEmpty(options.SignInAsAuthenticationType))
{
options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
if (options.Notifications == null)
{
options.Notifications = new OAuthAuthenticationNotifications();
}
return app.UseMiddleware<OAuthAuthenticationMiddleware<OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>, IOAuthAuthenticationNotifications>>(options);
return app.UseMiddleware<OAuthAuthenticationMiddleware<OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>, IOAuthAuthenticationNotifications>>(
new OptionsAction<OAuthAuthenticationOptions<IOAuthAuthenticationNotifications>>(options =>
{
options.AuthenticationType = authenticationType;
options.Caption = authenticationType;
if (configureOptions != null)
{
configureOptions(options);
}
})
{
Name = authenticationType,
});
}
}
}

View File

@ -10,6 +10,7 @@ using Microsoft.AspNet.Security.DataHandler;
using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Security.OAuth
{
@ -18,7 +19,7 @@ namespace Microsoft.AspNet.Security.OAuth
/// </summary>
[SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Middleware are not disposable.")]
public class OAuthAuthenticationMiddleware<TOptions, TNotifications> : AuthenticationMiddleware<TOptions>
where TOptions : OAuthAuthenticationOptions<TNotifications>
where TOptions : OAuthAuthenticationOptions<TNotifications>, new()
where TNotifications : IOAuthAuthenticationNotifications
{
/// <summary>
@ -32,9 +33,16 @@ namespace Microsoft.AspNet.Security.OAuth
RequestDelegate next,
IDataProtectionProvider dataProtectionProvider,
ILoggerFactory loggerFactory,
TOptions options)
: base(next, options)
IOptionsAccessor<ExternalAuthenticationOptions> externalOptions,
IOptionsAccessor<TOptions> options,
IOptionsAction<TOptions> configureOptions = null)
: base(next, options, configureOptions)
{
// todo: review error handling
if (string.IsNullOrWhiteSpace(Options.AuthenticationType))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "AuthenticationType"));
}
if (string.IsNullOrWhiteSpace(Options.ClientId))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ClientId"));
@ -57,7 +65,7 @@ namespace Microsoft.AspNet.Security.OAuth
if (Options.StateDataFormat == null)
{
IDataProtector dataProtector = DataProtectionHelpers.CreateDataProtector(dataProtectionProvider,
this.GetType().FullName, options.AuthenticationType, "v1");
this.GetType().FullName, Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
@ -65,6 +73,15 @@ namespace Microsoft.AspNet.Security.OAuth
Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET OAuth middleware");
Backchannel.Timeout = Options.BackchannelTimeout;
Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
{
Options.SignInAsAuthenticationType = externalOptions.Options.SignInAsAuthenticationType;
}
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "SignInAsAuthenticationType"));
}
}
protected HttpClient Backchannel { get; private set; }

View File

@ -18,10 +18,8 @@ namespace Microsoft.AspNet.Security.OAuth
/// <summary>
/// Initializes a new <see cref="OAuthAuthenticationOptions"/>.
/// </summary>
public OAuthAuthenticationOptions([NotNull] string authenticationType)
: base(authenticationType)
public OAuthAuthenticationOptions()
{
Caption = authenticationType;
AuthenticationMode = AuthenticationMode.Passive;
Scope = new List<string>();
BackchannelTimeout = TimeSpan.FromSeconds(60);
@ -69,9 +67,6 @@ namespace Microsoft.AspNet.Security.OAuth
/// <summary>
/// Get or sets the text that the user can display on a sign in user interface.
/// </summary>
/// <remarks>
/// The default value is the authentication type.
/// </remarks>
public string Caption
{
get { return Description.Caption; }

View File

@ -8,14 +8,6 @@ namespace Microsoft.AspNet.Security.OAuth
/// </summary>
public class OAuthAuthenticationOptions<TNotifications> : OAuthAuthenticationOptions where TNotifications : IOAuthAuthenticationNotifications
{
/// <summary>
/// Initializes a new <see cref="OAuthAuthenticationOptions"/>.
/// </summary>
public OAuthAuthenticationOptions([NotNull] string authenticationType)
: base(authenticationType)
{
}
/// <summary>
/// Gets or sets the <see cref="IOAuthAuthenticationNotifications"/> used to handle authentication events.
/// </summary>

View File

@ -1,7 +1,11 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.AspNet.Security.Twitter;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using System;
namespace Microsoft.AspNet.Builder
{
@ -10,36 +14,18 @@ namespace Microsoft.AspNet.Builder
/// </summary>
public static class TwitterAuthenticationExtensions
{
/// <summary>
/// Authenticate users using Twitter
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method</param>
/// <param name="consumerKey">The Twitter-issued consumer key</param>
/// <param name="consumerSecret">The Twitter-issued consumer secret</param>
/// <returns>The updated <see cref="IApplicationBuilder"/></returns>
public static IApplicationBuilder UseTwitterAuthentication([NotNull] this IApplicationBuilder app, [NotNull] string consumerKey, [NotNull] string consumerSecret)
public static IServiceCollection ConfigureTwitterAuthentication([NotNull] this IServiceCollection services, [NotNull] Action<TwitterAuthenticationOptions> configure)
{
return app.UseTwitterAuthentication(
new TwitterAuthenticationOptions
{
ConsumerKey = consumerKey,
ConsumerSecret = consumerSecret,
});
return services.ConfigureOptions(configure);
}
/// <summary>
/// Authenticate users using Twitter
/// </summary>
/// <param name="app">The <see cref="IApplicationBuilder"/> passed to the configure method</param>
/// <param name="options">Middleware configuration options</param>
/// <returns>The updated <see cref="IApplicationBuilder"/></returns>
public static IApplicationBuilder UseTwitterAuthentication([NotNull] this IApplicationBuilder app, [NotNull] TwitterAuthenticationOptions options)
public static IApplicationBuilder UseTwitterAuthentication([NotNull] this IApplicationBuilder app, Action<TwitterAuthenticationOptions> configureOptions = null, string optionsName = "")
{
if (string.IsNullOrEmpty(options.SignInAsAuthenticationType))
{
options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
return app.UseMiddleware<TwitterAuthenticationMiddleware>(options);
return app.UseMiddleware<TwitterAuthenticationMiddleware>(
new OptionsAction<TwitterAuthenticationOptions>(configureOptions ?? (o => { }))
{
Name = optionsName
});
}
}
}

View File

@ -12,6 +12,7 @@ using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.Infrastructure;
using Microsoft.AspNet.Security.Twitter.Messages;
using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Security.Twitter
{
@ -35,8 +36,10 @@ namespace Microsoft.AspNet.Security.Twitter
RequestDelegate next,
IDataProtectionProvider dataProtectionProvider,
ILoggerFactory loggerFactory,
TwitterAuthenticationOptions options)
: base(next, options)
IOptionsAccessor<ExternalAuthenticationOptions> externalOptions,
IOptionsAccessor<TwitterAuthenticationOptions> options,
IOptionsAction<TwitterAuthenticationOptions> configureOptions = null)
: base(next, options, configureOptions)
{
if (string.IsNullOrWhiteSpace(Options.ConsumerSecret))
{
@ -56,13 +59,22 @@ namespace Microsoft.AspNet.Security.Twitter
if (Options.StateDataFormat == null)
{
IDataProtector dataProtector = DataProtectionHelpers.CreateDataProtector(dataProtectionProvider,
typeof(TwitterAuthenticationMiddleware).FullName, options.AuthenticationType, "v1");
typeof(TwitterAuthenticationMiddleware).FullName, Options.AuthenticationType, "v1");
Options.StateDataFormat = new SecureDataFormat<RequestToken>(
Serializers.RequestToken,
dataProtector,
TextEncodings.Base64Url);
}
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
{
Options.SignInAsAuthenticationType = externalOptions.Options.SignInAsAuthenticationType;
}
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "SignInAsAuthenticationType"));
}
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options));
_httpClient.Timeout = Options.BackchannelTimeout;
_httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB

View File

@ -17,9 +17,9 @@ namespace Microsoft.AspNet.Security.Twitter
/// Initializes a new instance of the <see cref="TwitterAuthenticationOptions"/> class.
/// </summary>
public TwitterAuthenticationOptions()
: base(TwitterAuthenticationDefaults.AuthenticationType)
{
Caption = TwitterAuthenticationDefaults.AuthenticationType;
AuthenticationType = TwitterAuthenticationDefaults.AuthenticationType;
Caption = AuthenticationType;
CallbackPath = new PathString("/signin-twitter");
AuthenticationMode = AuthenticationMode.Passive;
BackchannelTimeout = TimeSpan.FromSeconds(60);

View File

@ -6,6 +6,7 @@
"Microsoft.AspNet.Security.DataProtection": "1.0.0-*",
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
"Microsoft.Framework.Logging": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*",
"Newtonsoft.Json": "6.0.4"
},
"frameworks": {

View File

@ -17,17 +17,6 @@ namespace Microsoft.AspNet.Security
{
private string _authenticationType;
/// <summary>
/// Initialize properties of AuthenticationOptions base class
/// </summary>
/// <param name="authenticationType">Assigned to the AuthenticationType property</param>
protected AuthenticationOptions(string authenticationType)
{
Description = new AuthenticationDescription();
AuthenticationType = authenticationType;
AuthenticationMode = AuthenticationMode.Active;
}
/// <summary>
/// The AuthenticationType in the options corresponds to the IIdentity AuthenticationType property. A different
/// value may be assigned in order to use the same authentication middleware type more than once in a pipeline.
@ -47,11 +36,11 @@ namespace Microsoft.AspNet.Security
/// alter 401 Unauthorized responses going out. If Passive the authentication middleware will only provide
/// identity and alter responses when explicitly indicated by the AuthenticationType.
/// </summary>
public AuthenticationMode AuthenticationMode { get; set; }
public AuthenticationMode AuthenticationMode { get; set; } = AuthenticationMode.Active;
/// <summary>
/// Additional information about the authentication type which is made available to the application.
/// </summary>
public AuthenticationDescription Description { get; set; }
public AuthenticationDescription Description { get; set; } = new AuthenticationDescription();
}
}

View File

@ -1,45 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Security;
namespace Microsoft.AspNet.Builder
{
/// <summary>
/// Provides extensions methods for app.Property values that are only needed by implementations of authentication middleware.
/// </summary>
public static class BuilderSecurityExtensions
{
/// <summary>
/// Returns the previously set AuthenticationType that external sign in middleware should use when the
/// browser navigates back to their return url.
/// </summary>
/// <param name="app">App builder passed to the application startup code</param>
/// <returns></returns>
public static string GetDefaultSignInAsAuthenticationType([NotNull] this IApplicationBuilder app)
{
object value;
if (app.Properties.TryGetValue(Constants.DefaultSignInAsAuthenticationType, out value))
{
var authenticationType = value as string;
if (!string.IsNullOrEmpty(authenticationType))
{
return authenticationType;
}
}
throw new InvalidOperationException(Resources.Exception_MissingDefaultSignInAsAuthenticationType);
}
/// <summary>
/// Called by middleware to change the name of the AuthenticationType that external middleware should use
/// when the browser navigates back to their return url.
/// </summary>
/// <param name="app">App builder passed to the application startup code</param>
/// <param name="authenticationType">AuthenticationType that external middleware should sign in as.</param>
public static void SetDefaultSignInAsAuthenticationType([NotNull] this IApplicationBuilder app, [NotNull] string authenticationType)
{
app.Properties[Constants.DefaultSignInAsAuthenticationType] = authenticationType;
}
}
}

View File

@ -1,17 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNet.Security
{
/// <summary>
/// String constants used only by the Security assembly
/// </summary>
internal static class Constants
{
/// <summary>
/// Used by middleware extension methods to coordinate the default value Options property SignInAsAuthenticationType
/// </summary>
internal const string DefaultSignInAsAuthenticationType = "Microsoft.AspNet.Security.DefaultSignInAsAuthenticationType";
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.AspNet.Security
{
public class ExternalAuthenticationOptions
{
public string SignInAsAuthenticationType { get; set; }
}
}

View File

@ -6,19 +6,30 @@ using System;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Security.Infrastructure
{
public abstract class AuthenticationMiddleware<TOptions> where TOptions : AuthenticationOptions
public abstract class AuthenticationMiddleware<TOptions> where TOptions : AuthenticationOptions, new()
{
private readonly RequestDelegate _next;
protected AuthenticationMiddleware([NotNull] RequestDelegate next, [NotNull] TOptions options)
protected AuthenticationMiddleware([NotNull] RequestDelegate next, [NotNull] IOptionsAccessor<TOptions> options, IOptionsAction<TOptions> configureOptions)
{
Options = options;
if (configureOptions != null)
{
Options = options.GetNamedOptions(configureOptions.Name);
configureOptions.Invoke(Options);
}
else
{
Options = options.Options;
}
_next = next;
}
public string AuthenticationType { get; set; }
public TOptions Options { get; set; }
public async Task Invoke(HttpContext context)

View File

@ -123,9 +123,6 @@
<data name="Exception_UnhookAuthenticationStateType" xml:space="preserve">
<value>The state passed to UnhookAuthentication may only be the return value from HookAuthentication.</value>
</data>
<data name="Exception_MissingDefaultSignInAsAuthenticationType" xml:space="preserve">
<value>A default value for SignInAsAuthenticationType was not found in IApplicationBuilder Properties. This can happen if your authentication middleware are added in the wrong order, or if one is missing.</value>
</data>
<data name="Exception_AuthenticationTokenDoesNotProvideSyncMethods" xml:space="preserve">
<value>The AuthenticationTokenProvider's required synchronous events have not been registered.</value>
</data>

View File

@ -5,7 +5,8 @@
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
"Microsoft.AspNet.Security.DataProtection": "1.0.0-*",
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
"Microsoft.Framework.Logging": "1.0.0-*"
"Microsoft.Framework.Logging": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*"
},
"frameworks": {
"aspnet50": { },

View File

@ -18,6 +18,8 @@ using Microsoft.AspNet.Http.Security;
using Microsoft.AspNet.TestHost;
using Shouldly;
using Xunit;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Security.Cookies
{
@ -26,7 +28,7 @@ namespace Microsoft.AspNet.Security.Cookies
[Fact]
public async Task NormalRequestPassesThrough()
{
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
});
HttpResponseMessage response = await server.CreateClient().GetAsync("http://example.com/normal");
@ -36,9 +38,9 @@ namespace Microsoft.AspNet.Security.Cookies
[Fact]
public async Task ProtectedRequestShouldRedirectToLogin()
{
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
LoginPath = new PathString("/login")
options.LoginPath = new PathString("/login");
});
Transaction transaction = await SendAsync(server, "http://example.com/protected");
@ -53,9 +55,9 @@ namespace Microsoft.AspNet.Security.Cookies
[Fact]
public async Task ProtectedCustomRequestShouldRedirectToCustomLogin()
{
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
LoginPath = new PathString("/login")
options.LoginPath = new PathString("/login");
});
Transaction transaction = await SendAsync(server, "http://example.com/protected/CustomRedirect");
@ -77,10 +79,10 @@ namespace Microsoft.AspNet.Security.Cookies
[Fact]
public async Task SignInCausesDefaultCookieToBeCreated()
{
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
LoginPath = new PathString("/login"),
CookieName = "TestCookie",
options.LoginPath = new PathString("/login");
options.CookieName = "TestCookie";
}, SignInAsAlice);
Transaction transaction = await SendAsync(server, "http://example.com/testpath");
@ -106,11 +108,11 @@ namespace Microsoft.AspNet.Security.Cookies
string requestUri,
bool shouldBeSecureOnly)
{
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
LoginPath = new PathString("/login"),
CookieName = "TestCookie",
CookieSecure = cookieSecureOption
options.LoginPath = new PathString("/login");
options.CookieName = "TestCookie";
options.CookieSecure = cookieSecureOption;
}, SignInAsAlice);
Transaction transaction = await SendAsync(server, requestUri);
@ -129,22 +131,22 @@ namespace Microsoft.AspNet.Security.Cookies
[Fact]
public async Task CookieOptionsAlterSetCookieHeader()
{
TestServer server1 = CreateServer(new CookieAuthenticationOptions
TestServer server1 = CreateServer(options =>
{
CookieName = "TestCookie",
CookiePath = "/foo",
CookieDomain = "another.com",
CookieSecure = CookieSecureOption.Always,
CookieHttpOnly = true,
options.CookieName = "TestCookie";
options.CookiePath = "/foo";
options.CookieDomain = "another.com";
options.CookieSecure = CookieSecureOption.Always;
options.CookieHttpOnly = true;
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server1, "http://example.com/testpath");
TestServer server2 = CreateServer(new CookieAuthenticationOptions
TestServer server2 = CreateServer(options =>
{
CookieName = "SecondCookie",
CookieSecure = CookieSecureOption.Never,
CookieHttpOnly = false,
options.CookieName = "SecondCookie";
options.CookieSecure = CookieSecureOption.Never;
options.CookieHttpOnly = false;
}, SignInAsAlice);
Transaction transaction2 = await SendAsync(server2, "http://example.com/testpath");
@ -168,9 +170,9 @@ namespace Microsoft.AspNet.Security.Cookies
public async Task CookieContainsIdentity()
{
var clock = new TestClock();
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
SystemClock = clock
options.SystemClock = clock;
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
@ -184,11 +186,11 @@ namespace Microsoft.AspNet.Security.Cookies
public async Task CookieStopsWorkingAfterExpiration()
{
var clock = new TestClock();
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
SystemClock = clock,
ExpireTimeSpan = TimeSpan.FromMinutes(10),
SlidingExpiration = false,
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
options.SlidingExpiration = false;
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
@ -215,11 +217,11 @@ namespace Microsoft.AspNet.Security.Cookies
public async Task CookieExpirationCanBeOverridenInSignin()
{
var clock = new TestClock();
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
SystemClock = clock,
ExpireTimeSpan = TimeSpan.FromMinutes(10),
SlidingExpiration = false,
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
options.SlidingExpiration = false;
},
context =>
{
@ -253,18 +255,18 @@ namespace Microsoft.AspNet.Security.Cookies
public async Task CookieExpirationCanBeOverridenInEvent()
{
var clock = new TestClock();
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
SystemClock = clock,
ExpireTimeSpan = TimeSpan.FromMinutes(10),
SlidingExpiration = false,
Notifications = new CookieAuthenticationNotifications()
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
options.SlidingExpiration = false;
options.Notifications = new CookieAuthenticationNotifications()
{
OnResponseSignIn = context =>
{
context.Properties.ExpiresUtc = clock.UtcNow.Add(TimeSpan.FromMinutes(5));
}
}
};
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
@ -291,11 +293,11 @@ namespace Microsoft.AspNet.Security.Cookies
public async Task CookieIsRenewedWithSlidingExpiration()
{
var clock = new TestClock();
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
SystemClock = clock,
ExpireTimeSpan = TimeSpan.FromMinutes(10),
SlidingExpiration = true,
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
options.SlidingExpiration = true;
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
@ -328,9 +330,9 @@ namespace Microsoft.AspNet.Security.Cookies
[Fact]
public async Task AjaxRedirectsAsExtraHeaderOnTwoHundred()
{
TestServer server = CreateServer(new CookieAuthenticationOptions
TestServer server = CreateServer(options =>
{
LoginPath = new PathString("/login")
options.LoginPath = new PathString("/login");
});
Transaction transaction = await SendAsync(server, "http://example.com/protected", ajaxRequest: true);
@ -363,11 +365,12 @@ namespace Microsoft.AspNet.Security.Cookies
return me;
}
private static TestServer CreateServer(CookieAuthenticationOptions options, Func<HttpContext, Task> testpath = null)
private static TestServer CreateServer(Action<CookieAuthenticationOptions> configureOptions, Func<HttpContext, Task> testpath = null)
{
return TestServer.Create(app =>
{
app.UseCookieAuthentication(options);
app.UseServices(services => { });
app.UseCookieAuthentication(configureOptions);
app.Use(async (context, next) =>
{
var req = context.Request;

View File

@ -13,6 +13,7 @@ using Microsoft.AspNet.Http.Security;
using Microsoft.AspNet.Security.Cookies;
using Microsoft.AspNet.TestHost;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.OptionsModel;
using Shouldly;
using Xunit;
@ -23,20 +24,35 @@ namespace Microsoft.AspNet.Security.Facebook
[Fact]
public async Task ChallengeWillTriggerApplyRedirectEvent()
{
var options = new FacebookAuthenticationOptions()
{
AppId = "Test App Id",
AppSecret = "Test App Secret",
Notifications = new FacebookAuthenticationNotifications
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
}
};
var server = CreateServer(
app => app.UseFacebookAuthentication(options),
app =>
{
app.UseServices(services =>
{
services.ConfigureFacebookAuthentication(options =>
{
options.AppId = "Test App Id";
options.AppSecret = "Test App Secret";
options.Notifications = new FacebookAuthenticationNotifications
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
};
});
services.ConfigureCookieAuthentication(options =>
{
options.AuthenticationType = "External";
});
services.ConfigureOptions<ExternalAuthenticationOptions>(options =>
{
options.SignInAsAuthenticationType = "External";
});
});
app.UseFacebookAuthentication();
app.UseCookieAuthentication();
},
context =>
{
context.Response.Challenge("Facebook");
@ -52,7 +68,27 @@ namespace Microsoft.AspNet.Security.Facebook
public async Task ChallengeWillTriggerRedirection()
{
var server = CreateServer(
app => app.UseFacebookAuthentication("Test App Id", "Test App Secret"),
app =>
{
app.UseServices(services =>
{
services.ConfigureFacebookAuthentication(options =>
{
options.AppId = "Test App Id";
options.AppSecret = "Test App Secret";
});
services.ConfigureCookieAuthentication(options =>
{
options.AuthenticationType = "External";
});
services.ConfigureOptions<ExternalAuthenticationOptions>(options =>
{
options.SignInAsAuthenticationType = "External";
});
});
app.UseFacebookAuthentication();
app.UseCookieAuthentication();
},
context =>
{
context.Response.Challenge("Facebook");
@ -73,11 +109,6 @@ namespace Microsoft.AspNet.Security.Facebook
{
return TestServer.Create(app =>
{
app.SetDefaultSignInAsAuthenticationType("External");
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = "External"
});
if (configure != null)
{
configure(app);

View File

@ -19,6 +19,10 @@ using Microsoft.AspNet.TestHost;
using Newtonsoft.Json;
using Shouldly;
using Xunit;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.Security.DataProtection;
using Microsoft.AspNet.Security.DataHandler;
namespace Microsoft.AspNet.Security.Google
{
@ -29,10 +33,10 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ChallengeWillTriggerRedirection()
{
var server = CreateServer(new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret"
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
});
var transaction = await SendAsync(server, "https://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
@ -51,11 +55,11 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task Challenge401WillTriggerRedirection()
{
var server = CreateServer(new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
AuthenticationMode = AuthenticationMode.Active,
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.AuthenticationMode = AuthenticationMode.Active;
});
var transaction = await SendAsync(server, "https://example.com/401");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
@ -70,10 +74,10 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ChallengeWillSetCorrelationCookie()
{
var server = CreateServer(new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret"
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
});
var transaction = await SendAsync(server, "https://example.com/challenge");
Console.WriteLine(transaction.SetCookie);
@ -83,11 +87,11 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task Challenge401WillSetCorrelationCookie()
{
var server = CreateServer(new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
AuthenticationMode = AuthenticationMode.Active,
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.AuthenticationMode = AuthenticationMode.Active;
});
var transaction = await SendAsync(server, "https://example.com/401");
Console.WriteLine(transaction.SetCookie);
@ -97,10 +101,11 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ChallengeWillSetDefaultScope()
{
var server = CreateServer(new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret"
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.AuthenticationMode = AuthenticationMode.Active;
});
var transaction = await SendAsync(server, "https://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
@ -111,11 +116,11 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task Challenge401WillSetDefaultScope()
{
var server = CreateServer(new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
AuthenticationMode = AuthenticationMode.Active,
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.AuthenticationMode = AuthenticationMode.Active;
});
var transaction = await SendAsync(server, "https://example.com/401");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
@ -126,13 +131,12 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ChallengeWillUseOptionsScope()
{
var options = new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
};
options.Scope.Add("https://www.googleapis.com/auth/plus.login");
var server = CreateServer(options);
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.Scope.Add("https://www.googleapis.com/auth/plus.login");
});
var transaction = await SendAsync(server, "https://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
@ -142,13 +146,12 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ChallengeWillUseAuthenticationPropertiesAsParameters()
{
var options = new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret"
};
var server = CreateServer(options,
context =>
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
},
context =>
{
var req = context.Request;
var res = context.Response;
@ -179,19 +182,18 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ChallengeWillTriggerApplyRedirectEvent()
{
var options = new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
Notifications = new GoogleAuthenticationNotifications
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.Notifications = new GoogleAuthenticationNotifications
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
}
};
var server = CreateServer(options);
};
});
var transaction = await SendAsync(server, "https://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
@ -201,12 +203,11 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ReplyPathWithoutStateQueryStringWillBeRejected()
{
var options = new GoogleAuthenticationOptions()
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret"
};
var server = CreateServer(options);
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
});
var transaction = await SendAsync(server, "https://example.com/signin-google?code=TestCode");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
}
@ -214,57 +215,58 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState()
{
var options = new GoogleAuthenticationOptions()
ISecureDataFormat<AuthenticationProperties> stateFormat = new PropertiesDataFormat(DataProtectionProvider.CreateNew().CreateProtector("GoogleTest"));
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
BackchannelHttpHandler = new TestHttpMessageHandler
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.StateDataFormat = stateFormat;
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = async req =>
{
if (req.RequestUri.AbsoluteUri == "https://accounts.google.com/o/oauth2/token")
{
if (req.RequestUri.AbsoluteUri == "https://accounts.google.com/o/oauth2/token")
return await ReturnJsonResponse(new
{
return await ReturnJsonResponse(new
{
access_token = "Test Access Token",
expire_in = 3600,
token_type = "Bearer"
});
}
else if (req.RequestUri.GetLeftPart(UriPartial.Path) == "https://www.googleapis.com/plus/v1/people/me")
{
return await ReturnJsonResponse(new
{
id = "Test User ID",
displayName = "Test Name",
name = new
{
familyName = "Test Family Name",
givenName = "Test Given Name"
},
url = "Profile link",
emails = new[]
{
new
{
value = "Test email",
type = "account"
}
}
});
}
return null;
access_token = "Test Access Token",
expire_in = 3600,
token_type = "Bearer"
});
}
}
};
var server = CreateServer(options);
else if (req.RequestUri.GetLeftPart(UriPartial.Path) == "https://www.googleapis.com/plus/v1/people/me")
{
return await ReturnJsonResponse(new
{
id = "Test User ID",
displayName = "Test Name",
name = new
{
familyName = "Test Family Name",
givenName = "Test Given Name"
},
url = "Profile link",
emails = new[]
{
new
{
value = "Test email",
type = "account"
}
}
});
}
return null;
}
};
});
var properties = new AuthenticationProperties();
var correlationKey = ".AspNet.Correlation.Google";
var correlationValue = "TestCorrelationId";
properties.Dictionary.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = options.StateDataFormat.Protect(properties);
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
"https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state),
correlationKey + "=" + correlationValue);
@ -287,25 +289,26 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ReplyPathWillRejectIfCodeIsInvalid()
{
var options = new GoogleAuthenticationOptions()
ISecureDataFormat<AuthenticationProperties> stateFormat = new PropertiesDataFormat(DataProtectionProvider.CreateNew().CreateProtector("GoogleTest"));
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
BackchannelHttpHandler = new TestHttpMessageHandler
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.StateDataFormat = stateFormat;
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = req =>
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest));
}
}
};
var server = CreateServer(options);
};
});
var properties = new AuthenticationProperties();
var correlationKey = ".AspNet.Correlation.Google";
var correlationValue = "TestCorrelationId";
properties.Dictionary.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = options.StateDataFormat.Protect(properties);
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
"https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state),
correlationKey + "=" + correlationValue);
@ -316,25 +319,26 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task ReplyPathWillRejectIfAccessTokenIsMissing()
{
var options = new GoogleAuthenticationOptions()
ISecureDataFormat<AuthenticationProperties> stateFormat = new PropertiesDataFormat(DataProtectionProvider.CreateNew().CreateProtector("GoogleTest"));
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
BackchannelHttpHandler = new TestHttpMessageHandler
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.StateDataFormat = stateFormat;
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = async req =>
Sender = req =>
{
return await ReturnJsonResponse(new object());
return ReturnJsonResponse(new object());
}
}
};
var server = CreateServer(options);
};
});
var properties = new AuthenticationProperties();
var correlationKey = ".AspNet.Correlation.Google";
var correlationValue = "TestCorrelationId";
properties.Dictionary.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = options.StateDataFormat.Protect(properties);
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
"https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state),
correlationKey + "=" + correlationValue);
@ -345,11 +349,13 @@ namespace Microsoft.AspNet.Security.Google
[Fact]
public async Task AuthenticatedEventCanGetRefreshToken()
{
var options = new GoogleAuthenticationOptions()
ISecureDataFormat<AuthenticationProperties> stateFormat = new PropertiesDataFormat(DataProtectionProvider.CreateNew().CreateProtector("GoogleTest"));
var server = CreateServer(options =>
{
ClientId = "Test Id",
ClientSecret = "Test Secret",
BackchannelHttpHandler = new TestHttpMessageHandler
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.StateDataFormat = stateFormat;
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = async req =>
{
@ -388,8 +394,8 @@ namespace Microsoft.AspNet.Security.Google
return null;
}
},
Notifications = new GoogleAuthenticationNotifications()
};
options.Notifications = new GoogleAuthenticationNotifications()
{
OnAuthenticated = context =>
{
@ -397,15 +403,14 @@ namespace Microsoft.AspNet.Security.Google
context.Identity.AddClaim(new Claim("RefreshToken", refreshToken));
return Task.FromResult<object>(null);
}
}
};
var server = CreateServer(options);
};
});
var properties = new AuthenticationProperties();
var correlationKey = ".AspNet.Correlation.Google";
var correlationValue = "TestCorrelationId";
properties.Dictionary.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = options.StateDataFormat.Protect(properties);
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
"https://example.com/signin-google?code=TestCode&state=" + Uri.EscapeDataString(state),
correlationKey + "=" + correlationValue);
@ -456,16 +461,19 @@ namespace Microsoft.AspNet.Security.Google
return transaction;
}
private static TestServer CreateServer(GoogleAuthenticationOptions options, Func<HttpContext, Task> testpath = null)
private static TestServer CreateServer(Action<GoogleAuthenticationOptions> configureOptions, Func<HttpContext, Task> testpath = null)
{
return TestServer.Create(app =>
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
app.UseServices(services =>
{
services.ConfigureOptions<ExternalAuthenticationOptions>(options =>
{
AuthenticationType = CookieAuthenticationType
options.SignInAsAuthenticationType = CookieAuthenticationType;
});
app.UseGoogleAuthentication(options);
});
app.UseCookieAuthentication(options => options.AuthenticationType = CookieAuthenticationType);
app.UseGoogleAuthentication(configureOptions);
app.Use(async (context, next) =>
{
var req = context.Request;

View File

@ -20,6 +20,10 @@ using Microsoft.AspNet.TestHost;
using Newtonsoft.Json;
using Shouldly;
using Xunit;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.DependencyInjection;
using Microsoft.AspNet.Security.DataHandler;
using Microsoft.AspNet.Security.DataProtection;
namespace Microsoft.AspNet.Security.Tests.MicrosoftAccount
{
@ -28,20 +32,19 @@ namespace Microsoft.AspNet.Security.Tests.MicrosoftAccount
[Fact]
public async Task ChallengeWillTriggerApplyRedirectEvent()
{
var options = new MicrosoftAccountAuthenticationOptions()
{
ClientId = "Test Client Id",
ClientSecret = "Test Client Secret",
Notifications = new MicrosoftAccountAuthenticationNotifications
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
}
};
var server = CreateServer(
app => app.UseMicrosoftAccountAuthentication(options),
options =>
{
options.ClientId = "Test Client Id";
options.ClientSecret = "Test Client Secret";
options.Notifications = new MicrosoftAccountAuthenticationNotifications
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
};
},
context =>
{
context.Response.Challenge("Microsoft");
@ -57,7 +60,11 @@ namespace Microsoft.AspNet.Security.Tests.MicrosoftAccount
public async Task ChallengeWillTriggerRedirection()
{
var server = CreateServer(
app => app.UseMicrosoftAccountAuthentication("Test Client Id", "Test Client Secret"),
options =>
{
options.ClientId = "Test Client Id";
options.ClientSecret = "Test Client Secret";
},
context =>
{
context.Response.Challenge("Microsoft");
@ -77,54 +84,55 @@ namespace Microsoft.AspNet.Security.Tests.MicrosoftAccount
[Fact]
public async Task AuthenticatedEventCanGetRefreshToken()
{
var options = new MicrosoftAccountAuthenticationOptions()
{
ClientId = "Test Client Id",
ClientSecret = "Test Client Secret",
BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = async req =>
{
if (req.RequestUri.AbsoluteUri == "https://login.live.com/oauth20_token.srf")
{
return await ReturnJsonResponse(new
{
access_token = "Test Access Token",
expire_in = 3600,
token_type = "Bearer",
refresh_token = "Test Refresh Token"
});
}
else if (req.RequestUri.GetLeftPart(UriPartial.Path) == "https://apis.live.net/v5.0/me")
{
return await ReturnJsonResponse(new
{
id = "Test User ID",
name = "Test Name",
first_name = "Test Given Name",
last_name = "Test Family Name",
emails = new
{
preferred = "Test email"
}
});
}
return null;
}
},
Notifications = new MicrosoftAccountAuthenticationNotifications
{
OnAuthenticated = context =>
{
var refreshToken = context.RefreshToken;
context.Identity.AddClaim(new Claim("RefreshToken", refreshToken));
return Task.FromResult<object>(null);
}
}
};
ISecureDataFormat<AuthenticationProperties> stateFormat = new PropertiesDataFormat(DataProtectionProvider.CreateNew().CreateProtector("MsftTest"));
var server = CreateServer(
app => app.UseMicrosoftAccountAuthentication(options),
options =>
{
options.ClientId = "Test Client Id";
options.ClientSecret = "Test Client Secret";
options.StateDataFormat = stateFormat;
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = async req =>
{
if (req.RequestUri.AbsoluteUri == "https://login.live.com/oauth20_token.srf")
{
return await ReturnJsonResponse(new
{
access_token = "Test Access Token",
expire_in = 3600,
token_type = "Bearer",
refresh_token = "Test Refresh Token"
});
}
else if (req.RequestUri.GetLeftPart(UriPartial.Path) == "https://apis.live.net/v5.0/me")
{
return await ReturnJsonResponse(new
{
id = "Test User ID",
name = "Test Name",
first_name = "Test Given Name",
last_name = "Test Family Name",
emails = new
{
preferred = "Test email"
}
});
}
return null;
}
};
options.Notifications = new MicrosoftAccountAuthenticationNotifications
{
OnAuthenticated = context =>
{
var refreshToken = context.RefreshToken;
context.Identity.AddClaim(new Claim("RefreshToken", refreshToken));
return Task.FromResult<object>(null);
}
};
},
context =>
{
Describe(context.Response, (ClaimsIdentity)context.User.Identity);
@ -135,7 +143,7 @@ namespace Microsoft.AspNet.Security.Tests.MicrosoftAccount
var correlationValue = "TestCorrelationId";
properties.Dictionary.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = options.StateDataFormat.Protect(properties);
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
"https://example.com/signin-microsoft?code=TestCode&state=" + Uri.EscapeDataString(state),
correlationKey + "=" + correlationValue);
@ -151,19 +159,19 @@ namespace Microsoft.AspNet.Security.Tests.MicrosoftAccount
transaction.FindClaimValue("RefreshToken").ShouldBe("Test Refresh Token");
}
private static TestServer CreateServer(Action<IApplicationBuilder> configure, Func<HttpContext, bool> handler)
private static TestServer CreateServer(Action<MicrosoftAccountAuthenticationOptions> configureOptions, Func<HttpContext, bool> handler)
{
return TestServer.Create(app =>
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
app.UseServices(services =>
{
AuthenticationType = "External"
services.ConfigureOptions<ExternalAuthenticationOptions>(options =>
{
options.SignInAsAuthenticationType = "External";
});
});
app.SetDefaultSignInAsAuthenticationType("External");
if (configure != null)
{
configure(app);
}
app.UseCookieAuthentication(options => options.AuthenticationType = "External");
app.UseMicrosoftAccountAuthentication(configureOptions);
app.Use(async (context, next) =>
{
if (handler == null || !handler(context))

View File

@ -15,6 +15,8 @@ using Microsoft.AspNet.TestHost;
using Newtonsoft.Json;
using Shouldly;
using Xunit;
using Microsoft.Framework.OptionsModel;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Security.Twitter
{
@ -23,20 +25,21 @@ namespace Microsoft.AspNet.Security.Twitter
[Fact]
public async Task ChallengeWillTriggerApplyRedirectEvent()
{
var options = new TwitterAuthenticationOptions()
{
ConsumerKey = "Test Consumer Key",
ConsumerSecret = "Test Consumer Secret",
Notifications = new TwitterAuthenticationNotifications
var server = CreateServer(
app => app.UseTwitterAuthentication(options =>
{
OnApplyRedirect = context =>
options.ConsumerKey = "Test Consumer Key";
options.ConsumerSecret = "Test Consumer Secret";
options.Notifications = new TwitterAuthenticationNotifications
{
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
},
BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = req =>
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
};
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = req =>
{
if (req.RequestUri.AbsoluteUri == "https://api.twitter.com/oauth/request_token")
{
@ -50,11 +53,9 @@ namespace Microsoft.AspNet.Security.Twitter
}
return Task.FromResult<HttpResponseMessage>(null);
}
},
BackchannelCertificateValidator = null
};
var server = CreateServer(
app => app.UseTwitterAuthentication(options),
};
options.BackchannelCertificateValidator = null;
}),
context =>
{
context.Response.Challenge("Twitter");
@ -69,31 +70,30 @@ namespace Microsoft.AspNet.Security.Twitter
[Fact]
public async Task ChallengeWillTriggerRedirection()
{
var options = new TwitterAuthenticationOptions()
{
ConsumerKey = "Test Consumer Key",
ConsumerSecret = "Test Consumer Secret",
BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = req =>
{
if (req.RequestUri.AbsoluteUri == "https://api.twitter.com/oauth/request_token")
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content =
new StringContent("oauth_callback_confirmed=true&oauth_token=test_oauth_token&oauth_token_secret=test_oauth_token_secret",
Encoding.UTF8,
"application/x-www-form-urlencoded")
});
}
return Task.FromResult<HttpResponseMessage>(null);
}
},
BackchannelCertificateValidator = null
};
var server = CreateServer(
app => app.UseTwitterAuthentication(options),
app => app.UseTwitterAuthentication(options =>
{
options.ConsumerKey = "Test Consumer Key";
options.ConsumerSecret = "Test Consumer Secret";
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = req =>
{
if (req.RequestUri.AbsoluteUri == "https://api.twitter.com/oauth/request_token")
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content =
new StringContent("oauth_callback_confirmed=true&oauth_token=test_oauth_token&oauth_token_secret=test_oauth_token_secret",
Encoding.UTF8,
"application/x-www-form-urlencoded")
});
}
return Task.FromResult<HttpResponseMessage>(null);
}
};
options.BackchannelCertificateValidator = null;
}),
context =>
{
context.Response.Challenge("Twitter");
@ -109,10 +109,16 @@ namespace Microsoft.AspNet.Security.Twitter
{
return TestServer.Create(app =>
{
app.SetDefaultSignInAsAuthenticationType("External");
app.UseCookieAuthentication(new CookieAuthenticationOptions
app.UseServices(services =>
{
AuthenticationType = "External"
services.ConfigureOptions<ExternalAuthenticationOptions>(options =>
{
options.SignInAsAuthenticationType = "External";
});
});
app.UseCookieAuthentication(options =>
{
options.AuthenticationType = "External";
});
if (configure != null)
{

View File

@ -12,6 +12,7 @@
"Microsoft.AspNet.Security.Twitter": "1.0.0-*",
"Microsoft.AspNet.TestHost": "1.0.0-*",
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
"Microsoft.Framework.OptionsModel": "1.0.0-*",
"Moq": "4.2.1312.1622",
"Xunit.KRunner": "1.0.0-*"
},