Move logger to base handler and moar var

This commit is contained in:
Hao Kung 2015-04-22 12:23:54 -07:00
parent 6072e3b1b8
commit 30d350da26
27 changed files with 169 additions and 227 deletions

View File

@ -22,18 +22,11 @@ namespace Microsoft.AspNet.Authentication.Cookies
private const string HeaderValueMinusOne = "-1"; private const string HeaderValueMinusOne = "-1";
private const string SessionIdClaim = "Microsoft.AspNet.Authentication.Cookies-SessionId"; private const string SessionIdClaim = "Microsoft.AspNet.Authentication.Cookies-SessionId";
private readonly ILogger _logger;
private bool _shouldRenew; private bool _shouldRenew;
private DateTimeOffset _renewIssuedUtc; private DateTimeOffset _renewIssuedUtc;
private DateTimeOffset _renewExpiresUtc; private DateTimeOffset _renewExpiresUtc;
private string _sessionKey; private string _sessionKey;
public CookieAuthenticationHandler([NotNull] ILogger logger)
{
_logger = logger;
}
protected override AuthenticationTicket AuthenticateCore() protected override AuthenticationTicket AuthenticateCore()
{ {
return AuthenticateCoreAsync().GetAwaiter().GetResult(); return AuthenticateCoreAsync().GetAwaiter().GetResult();
@ -54,7 +47,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
if (ticket == null) if (ticket == null)
{ {
_logger.LogWarning(@"Unprotect ticket failed"); Logger.LogWarning(@"Unprotect ticket failed");
return null; return null;
} }
@ -63,14 +56,14 @@ namespace Microsoft.AspNet.Authentication.Cookies
Claim claim = ticket.Principal.Claims.FirstOrDefault(c => c.Type.Equals(SessionIdClaim)); Claim claim = ticket.Principal.Claims.FirstOrDefault(c => c.Type.Equals(SessionIdClaim));
if (claim == null) if (claim == null)
{ {
_logger.LogWarning(@"SessionId missing"); Logger.LogWarning(@"SessionId missing");
return null; return null;
} }
_sessionKey = claim.Value; _sessionKey = claim.Value;
ticket = await Options.SessionStore.RetrieveAsync(_sessionKey); ticket = await Options.SessionStore.RetrieveAsync(_sessionKey);
if (ticket == null) if (ticket == null)
{ {
_logger.LogWarning(@"Identity missing in session store"); Logger.LogWarning(@"Identity missing in session store");
return null; return null;
} }
} }

View File

@ -15,8 +15,6 @@ namespace Microsoft.AspNet.Authentication.Cookies
{ {
public class CookieAuthenticationMiddleware : AuthenticationMiddleware<CookieAuthenticationOptions> public class CookieAuthenticationMiddleware : AuthenticationMiddleware<CookieAuthenticationOptions>
{ {
private readonly ILogger _logger;
public CookieAuthenticationMiddleware( public CookieAuthenticationMiddleware(
[NotNull] RequestDelegate next, [NotNull] RequestDelegate next,
[NotNull] IDataProtectionProvider dataProtectionProvider, [NotNull] IDataProtectionProvider dataProtectionProvider,
@ -24,7 +22,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
[NotNull] IUrlEncoder urlEncoder, [NotNull] IUrlEncoder urlEncoder,
[NotNull] IOptions<CookieAuthenticationOptions> options, [NotNull] IOptions<CookieAuthenticationOptions> options,
ConfigureOptions<CookieAuthenticationOptions> configureOptions) ConfigureOptions<CookieAuthenticationOptions> configureOptions)
: base(next, options, configureOptions) : base(next, options, loggerFactory, configureOptions)
{ {
if (Options.Notifications == null) if (Options.Notifications == null)
{ {
@ -36,7 +34,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
} }
if (Options.TicketDataFormat == null) if (Options.TicketDataFormat == null)
{ {
IDataProtector dataProtector = dataProtectionProvider.CreateProtector( var dataProtector = dataProtectionProvider.CreateProtector(
typeof(CookieAuthenticationMiddleware).FullName, Options.AuthenticationScheme, "v2"); typeof(CookieAuthenticationMiddleware).FullName, Options.AuthenticationScheme, "v2");
Options.TicketDataFormat = new TicketDataFormat(dataProtector); Options.TicketDataFormat = new TicketDataFormat(dataProtector);
} }
@ -44,13 +42,11 @@ namespace Microsoft.AspNet.Authentication.Cookies
{ {
Options.CookieManager = new ChunkingCookieManager(urlEncoder); Options.CookieManager = new ChunkingCookieManager(urlEncoder);
} }
_logger = loggerFactory.CreateLogger(typeof(CookieAuthenticationMiddleware).FullName);
} }
protected override AuthenticationHandler<CookieAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<CookieAuthenticationOptions> CreateHandler()
{ {
return new CookieAuthenticationHandler(_logger); return new CookieAuthenticationHandler();
} }
} }
} }

View File

@ -21,8 +21,8 @@ namespace Microsoft.AspNet.Authentication.Facebook
{ {
internal class FacebookAuthenticationHandler : OAuthAuthenticationHandler<FacebookAuthenticationOptions, IFacebookAuthenticationNotifications> internal class FacebookAuthenticationHandler : OAuthAuthenticationHandler<FacebookAuthenticationOptions, IFacebookAuthenticationNotifications>
{ {
public FacebookAuthenticationHandler(HttpClient httpClient, ILogger logger) public FacebookAuthenticationHandler(HttpClient httpClient)
: base(httpClient, logger) : base(httpClient)
{ {
} }
@ -39,9 +39,9 @@ namespace Microsoft.AspNet.Authentication.Facebook
var tokenResponse = await Backchannel.GetAsync(Options.TokenEndpoint + queryBuilder.ToString(), Context.RequestAborted); var tokenResponse = await Backchannel.GetAsync(Options.TokenEndpoint + queryBuilder.ToString(), Context.RequestAborted);
tokenResponse.EnsureSuccessStatusCode(); tokenResponse.EnsureSuccessStatusCode();
string oauthTokenResponse = await tokenResponse.Content.ReadAsStringAsync(); var oauthTokenResponse = await tokenResponse.Content.ReadAsStringAsync();
IFormCollection form = new FormCollection(FormReader.ReadForm(oauthTokenResponse)); var form = new FormCollection(FormReader.ReadForm(oauthTokenResponse));
var response = new JObject(); var response = new JObject();
foreach (string key in form.Keys) foreach (string key in form.Keys)
{ {
@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Authentication.Facebook
protected override async Task<AuthenticationTicket> GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens) protected override async Task<AuthenticationTicket> GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens)
{ {
string graphAddress = Options.UserInformationEndpoint + "?access_token=" + Uri.EscapeDataString(tokens.AccessToken); var graphAddress = Options.UserInformationEndpoint + "?access_token=" + Uri.EscapeDataString(tokens.AccessToken);
if (Options.SendAppSecretProof) if (Options.SendAppSecretProof)
{ {
graphAddress += "&appsecret_proof=" + GenerateAppSecretProof(tokens.AccessToken); graphAddress += "&appsecret_proof=" + GenerateAppSecretProof(tokens.AccessToken);
@ -61,8 +61,8 @@ namespace Microsoft.AspNet.Authentication.Facebook
var graphResponse = await Backchannel.GetAsync(graphAddress, Context.RequestAborted); var graphResponse = await Backchannel.GetAsync(graphAddress, Context.RequestAborted);
graphResponse.EnsureSuccessStatusCode(); graphResponse.EnsureSuccessStatusCode();
string text = await graphResponse.Content.ReadAsStringAsync(); var text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text); var user = JObject.Parse(text);
var context = new FacebookAuthenticatedContext(Context, Options, user, tokens); var context = new FacebookAuthenticatedContext(Context, Options, user, tokens);
var identity = new ClaimsIdentity( var identity = new ClaimsIdentity(
@ -107,8 +107,8 @@ namespace Microsoft.AspNet.Authentication.Facebook
{ {
using (HMACSHA256 algorithm = new HMACSHA256(Encoding.ASCII.GetBytes(Options.AppSecret))) using (HMACSHA256 algorithm = new HMACSHA256(Encoding.ASCII.GetBytes(Options.AppSecret)))
{ {
byte[] hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(accessToken)); var hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(accessToken));
StringBuilder builder = new StringBuilder(); var builder = new StringBuilder();
for (int i = 0; i < hash.Length; i++) for (int i = 0; i < hash.Length; i++)
{ {
builder.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture)); builder.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));

View File

@ -54,7 +54,7 @@ namespace Microsoft.AspNet.Authentication.Facebook
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="FacebookAuthenticationOptions"/> supplied to the constructor.</returns> /// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="FacebookAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<FacebookAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<FacebookAuthenticationOptions> CreateHandler()
{ {
return new FacebookAuthenticationHandler(Backchannel, Logger); return new FacebookAuthenticationHandler(Backchannel);
} }
} }
} }

View File

@ -33,4 +33,4 @@ namespace Microsoft.Framework.DependencyInjection
return services.Configure<FacebookAuthenticationOptions>(config, optionsName); return services.Configure<FacebookAuthenticationOptions>(config, optionsName);
} }
} }
} }

View File

@ -10,27 +10,26 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http.Authentication; using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Authentication.OAuth; using Microsoft.AspNet.Authentication.OAuth;
using Microsoft.AspNet.WebUtilities; using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.Logging;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace Microsoft.AspNet.Authentication.Google namespace Microsoft.AspNet.Authentication.Google
{ {
internal class GoogleAuthenticationHandler : OAuthAuthenticationHandler<GoogleAuthenticationOptions, IGoogleAuthenticationNotifications> internal class GoogleAuthenticationHandler : OAuthAuthenticationHandler<GoogleAuthenticationOptions, IGoogleAuthenticationNotifications>
{ {
public GoogleAuthenticationHandler(HttpClient httpClient, ILogger logger) public GoogleAuthenticationHandler(HttpClient httpClient)
: base(httpClient, logger) : base(httpClient)
{ {
} }
protected override async Task<AuthenticationTicket> GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens) protected override async Task<AuthenticationTicket> GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens)
{ {
// Get the Google user // Get the Google user
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint); var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);
HttpResponseMessage graphResponse = await Backchannel.SendAsync(request, Context.RequestAborted); var graphResponse = await Backchannel.SendAsync(request, Context.RequestAborted);
graphResponse.EnsureSuccessStatusCode(); graphResponse.EnsureSuccessStatusCode();
var text = await graphResponse.Content.ReadAsStringAsync(); var text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text); var user = JObject.Parse(text);
var context = new GoogleAuthenticatedContext(Context, Options, user, tokens); var context = new GoogleAuthenticatedContext(Context, Options, user, tokens);
var identity = new ClaimsIdentity( var identity = new ClaimsIdentity(
@ -79,7 +78,7 @@ namespace Microsoft.AspNet.Authentication.Google
// TODO: Abstract this properties override pattern into the base class? // TODO: Abstract this properties override pattern into the base class?
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri) protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{ {
string scope = FormatScope(); var scope = FormatScope();
var queryStrings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); var queryStrings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
queryStrings.Add("response_type", "code"); queryStrings.Add("response_type", "code");
@ -92,10 +91,10 @@ namespace Microsoft.AspNet.Authentication.Google
AddQueryString(queryStrings, properties, "approval_prompt"); AddQueryString(queryStrings, properties, "approval_prompt");
AddQueryString(queryStrings, properties, "login_hint"); AddQueryString(queryStrings, properties, "login_hint");
string state = Options.StateDataFormat.Protect(properties); var state = Options.StateDataFormat.Protect(properties);
queryStrings.Add("state", state); queryStrings.Add("state", state);
string authorizationEndpoint = QueryHelpers.AddQueryString(Options.AuthorizationEndpoint, queryStrings); var authorizationEndpoint = QueryHelpers.AddQueryString(Options.AuthorizationEndpoint, queryStrings);
return authorizationEndpoint; return authorizationEndpoint;
} }

View File

@ -56,7 +56,7 @@ namespace Microsoft.AspNet.Authentication.Google
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="GoogleAuthenticationOptions"/> supplied to the constructor.</returns> /// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="GoogleAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<GoogleAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<GoogleAuthenticationOptions> CreateHandler()
{ {
return new GoogleAuthenticationHandler(Backchannel, Logger); return new GoogleAuthenticationHandler(Backchannel);
} }
} }
} }

View File

@ -33,4 +33,4 @@ namespace Microsoft.AspNet.Authentication.Google
/// </summary> /// </summary>
public string AccessType { get; set; } public string AccessType { get; set; }
} }
} }

View File

@ -1,35 +1,31 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Authentication.OAuth; using Microsoft.AspNet.Authentication.OAuth;
using Microsoft.Framework.Logging; using Microsoft.AspNet.Http.Authentication;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace Microsoft.AspNet.Authentication.MicrosoftAccount namespace Microsoft.AspNet.Authentication.MicrosoftAccount
{ {
internal class MicrosoftAccountAuthenticationHandler : OAuthAuthenticationHandler<MicrosoftAccountAuthenticationOptions, IMicrosoftAccountAuthenticationNotifications> internal class MicrosoftAccountAuthenticationHandler : OAuthAuthenticationHandler<MicrosoftAccountAuthenticationOptions, IMicrosoftAccountAuthenticationNotifications>
{ {
public MicrosoftAccountAuthenticationHandler(HttpClient httpClient, ILogger logger) public MicrosoftAccountAuthenticationHandler(HttpClient httpClient)
: base(httpClient, logger) : base(httpClient)
{ {
} }
protected override async Task<AuthenticationTicket> GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens) protected override async Task<AuthenticationTicket> GetUserInformationAsync(AuthenticationProperties properties, TokenResponse tokens)
{ {
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint); var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken);
HttpResponseMessage graphResponse = await Backchannel.SendAsync(request, Context.RequestAborted); var graphResponse = await Backchannel.SendAsync(request, Context.RequestAborted);
graphResponse.EnsureSuccessStatusCode(); graphResponse.EnsureSuccessStatusCode();
string accountString = await graphResponse.Content.ReadAsStringAsync(); var accountString = await graphResponse.Content.ReadAsStringAsync();
JObject accountInformation = JObject.Parse(accountString); var accountInformation = JObject.Parse(accountString);
var context = new MicrosoftAccountAuthenticatedContext(Context, Options, accountInformation, tokens); var context = new MicrosoftAccountAuthenticatedContext(Context, Options, accountInformation, tokens);
context.Properties = properties; context.Properties = properties;

View File

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Authentication.OAuth; using Microsoft.AspNet.Authentication.OAuth;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.DataProtection; using Microsoft.AspNet.DataProtection;
@ -50,7 +49,7 @@ namespace Microsoft.AspNet.Authentication.MicrosoftAccount
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="MicrosoftAccountAuthenticationOptions"/> supplied to the constructor.</returns> /// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="MicrosoftAccountAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<MicrosoftAccountAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<MicrosoftAccountAuthenticationOptions> CreateHandler()
{ {
return new MicrosoftAccountAuthenticationHandler(Backchannel, Logger); return new MicrosoftAccountAuthenticationHandler(Backchannel);
} }
} }
} }

View File

@ -19,16 +19,13 @@ namespace Microsoft.AspNet.Authentication.OAuth
where TOptions : OAuthAuthenticationOptions<TNotifications> where TOptions : OAuthAuthenticationOptions<TNotifications>
where TNotifications : IOAuthAuthenticationNotifications where TNotifications : IOAuthAuthenticationNotifications
{ {
public OAuthAuthenticationHandler(HttpClient backchannel, ILogger logger) public OAuthAuthenticationHandler(HttpClient backchannel)
{ {
Backchannel = backchannel; Backchannel = backchannel;
Logger = logger;
} }
protected HttpClient Backchannel { get; private set; } protected HttpClient Backchannel { get; private set; }
protected ILogger Logger { get; private set; }
public override async Task<bool> InvokeAsync() public override async Task<bool> InvokeAsync()
{ {
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path) if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
@ -107,7 +104,7 @@ namespace Microsoft.AspNet.Authentication.OAuth
} }
// OAuth2 10.12 CSRF // OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, Logger)) if (!ValidateCorrelationId(properties))
{ {
return new AuthenticationTicket(properties, Options.AuthenticationScheme); return new AuthenticationTicket(properties, Options.AuthenticationScheme);
} }

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Authentication.OAuth
[NotNull] IOptions<ExternalAuthenticationOptions> externalOptions, [NotNull] IOptions<ExternalAuthenticationOptions> externalOptions,
[NotNull] IOptions<TOptions> options, [NotNull] IOptions<TOptions> options,
ConfigureOptions<TOptions> configureOptions = null) ConfigureOptions<TOptions> configureOptions = null)
: base(next, options, configureOptions) : base(next, options, loggerFactory, configureOptions)
{ {
// todo: review error handling // todo: review error handling
if (string.IsNullOrWhiteSpace(Options.AuthenticationScheme)) if (string.IsNullOrWhiteSpace(Options.AuthenticationScheme))
@ -64,11 +64,9 @@ namespace Microsoft.AspNet.Authentication.OAuth
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "TokenEndpoint")); throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "TokenEndpoint"));
} }
Logger = loggerFactory.CreateLogger(this.GetType().FullName);
if (Options.StateDataFormat == null) if (Options.StateDataFormat == null)
{ {
IDataProtector dataProtector = dataProtectionProvider.CreateProtector( var dataProtector = dataProtectionProvider.CreateProtector(
this.GetType().FullName, Options.AuthenticationScheme, "v1"); this.GetType().FullName, Options.AuthenticationScheme, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector); Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
} }
@ -90,15 +88,13 @@ namespace Microsoft.AspNet.Authentication.OAuth
protected HttpClient Backchannel { get; private set; } protected HttpClient Backchannel { get; private set; }
protected ILogger Logger { get; private set; }
/// <summary> /// <summary>
/// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests. /// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests.
/// </summary> /// </summary>
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OAuthAuthenticationOptions"/> supplied to the constructor.</returns> /// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OAuthAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<TOptions> CreateHandler() protected override AuthenticationHandler<TOptions> CreateHandler()
{ {
return new OAuthAuthenticationHandler<TOptions, TNotifications>(Backchannel, Logger); return new OAuthAuthenticationHandler<TOptions, TNotifications>(Backchannel);
} }
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")]

View File

@ -17,14 +17,8 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
{ {
public class OAuthBearerAuthenticationHandler : AuthenticationHandler<OAuthBearerAuthenticationOptions> public class OAuthBearerAuthenticationHandler : AuthenticationHandler<OAuthBearerAuthenticationOptions>
{ {
private readonly ILogger _logger;
private OpenIdConnectConfiguration _configuration; private OpenIdConnectConfiguration _configuration;
public OAuthBearerAuthenticationHandler(ILogger logger)
{
_logger = logger;
}
protected override AuthenticationTicket AuthenticateCore() protected override AuthenticationTicket AuthenticateCore()
{ {
return AuthenticateCoreAsync().GetAwaiter().GetResult(); return AuthenticateCoreAsync().GetAwaiter().GetResult();
@ -63,7 +57,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
if (string.IsNullOrEmpty(token)) if (string.IsNullOrEmpty(token))
{ {
string authorization = Request.Headers.Get("Authorization"); var authorization = Request.Headers.Get("Authorization");
// If no authorization header found, nothing to process further // If no authorization header found, nothing to process further
if (string.IsNullOrEmpty(authorization)) if (string.IsNullOrEmpty(authorization))
@ -155,7 +149,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError("Exception occurred while processing message", ex); Logger.LogError("Exception occurred while processing message", ex);
// Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification. // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification.
if (Options.RefreshOnIssuerKeyNotFound && ex.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) if (Options.RefreshOnIssuerKeyNotFound && ex.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))

View File

@ -34,9 +34,8 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
[NotNull] ILoggerFactory loggerFactory, [NotNull] ILoggerFactory loggerFactory,
[NotNull] IOptions<OAuthBearerAuthenticationOptions> options, [NotNull] IOptions<OAuthBearerAuthenticationOptions> options,
ConfigureOptions<OAuthBearerAuthenticationOptions> configureOptions) ConfigureOptions<OAuthBearerAuthenticationOptions> configureOptions)
: base(next, options, configureOptions) : base(next, options, loggerFactory, configureOptions)
{ {
_logger = loggerFactory.CreateLogger<OAuthBearerAuthenticationMiddleware>();
if (Options.Notifications == null) if (Options.Notifications == null)
{ {
Options.Notifications = new OAuthBearerAuthenticationNotifications(); Options.Notifications = new OAuthBearerAuthenticationNotifications();
@ -86,7 +85,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
/// <returns>A new instance of the request handler</returns> /// <returns>A new instance of the request handler</returns>
protected override AuthenticationHandler<OAuthBearerAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<OAuthBearerAuthenticationOptions> CreateHandler()
{ {
return new OAuthBearerAuthenticationHandler(_logger); return new OAuthBearerAuthenticationHandler();
} }
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")]

View File

@ -23,18 +23,8 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
{ {
private const string NonceProperty = "N"; private const string NonceProperty = "N";
private const string UriSchemeDelimiter = "://"; private const string UriSchemeDelimiter = "://";
private readonly ILogger _logger;
private OpenIdConnectConfiguration _configuration; private OpenIdConnectConfiguration _configuration;
/// <summary>
/// Creates a new OpenIdConnectAuthenticationHandler
/// </summary>
/// <param name="logger"></param>
public OpenIdConnectAuthenticationHandler(ILogger logger)
{
_logger = logger;
}
private string CurrentUri private string CurrentUri
{ {
get get
@ -67,7 +57,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
_configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted); _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
} }
OpenIdConnectMessage openIdConnectMessage = new OpenIdConnectMessage() var openIdConnectMessage = new OpenIdConnectMessage()
{ {
IssuerAddress = _configuration == null ? string.Empty : (_configuration.EndSessionEndpoint ?? string.Empty), IssuerAddress = _configuration == null ? string.Empty : (_configuration.EndSessionEndpoint ?? string.Empty),
RequestType = OpenIdConnectRequestType.LogoutRequest, RequestType = OpenIdConnectRequestType.LogoutRequest,
@ -95,10 +85,10 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
if (!notification.HandledResponse) if (!notification.HandledResponse)
{ {
string redirectUri = notification.ProtocolMessage.CreateLogoutRequestUrl(); var redirectUri = notification.ProtocolMessage.CreateLogoutRequestUrl();
if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute)) if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
{ {
_logger.LogWarning(Resources.OIDCH_0051_RedirectUriLogoutIsNotWellFormed, redirectUri); Logger.LogWarning(Resources.OIDCH_0051_RedirectUriLogoutIsNotWellFormed, redirectUri);
} }
Response.Redirect(redirectUri); Response.Redirect(redirectUri);
@ -118,28 +108,25 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
/// <remarks>Uses log id's OIDCH-0026 - OIDCH-0050, next num: 37</remarks> /// <remarks>Uses log id's OIDCH-0026 - OIDCH-0050, next num: 37</remarks>
protected override async Task ApplyResponseChallengeAsync() protected override async Task ApplyResponseChallengeAsync()
{ {
if (_logger.IsEnabled(LogLevel.Debug)) Logger.LogDebug(Resources.OIDCH_0026_ApplyResponseChallengeAsync, this.GetType());
{
_logger.LogDebug(Resources.OIDCH_0026_ApplyResponseChallengeAsync, this.GetType());
}
if (ShouldConvertChallengeToForbidden()) if (ShouldConvertChallengeToForbidden())
{ {
_logger.LogDebug(Resources.OIDCH_0027_401_ConvertedTo_403); Logger.LogDebug(Resources.OIDCH_0027_401_ConvertedTo_403);
Response.StatusCode = 403; Response.StatusCode = 403;
return; return;
} }
if (Response.StatusCode != 401) if (Response.StatusCode != 401)
{ {
_logger.LogDebug(Resources.OIDCH_0028_StatusCodeNot401, Response.StatusCode); Logger.LogDebug(Resources.OIDCH_0028_StatusCodeNot401, Response.StatusCode);
return; return;
} }
// When Automatic should redirect on 401 even if there wasn't an explicit challenge. // When Automatic should redirect on 401 even if there wasn't an explicit challenge.
if (ChallengeContext == null && !Options.AutomaticAuthentication) if (ChallengeContext == null && !Options.AutomaticAuthentication)
{ {
_logger.LogDebug(Resources.OIDCH_0029_ChallengeContextEqualsNull); Logger.LogDebug(Resources.OIDCH_0029_ChallengeContextEqualsNull);
return; return;
} }
@ -158,17 +145,17 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
if (!string.IsNullOrWhiteSpace(properties.RedirectUri)) if (!string.IsNullOrWhiteSpace(properties.RedirectUri))
{ {
_logger.LogDebug(Resources.OIDCH_0030_Using_Properties_RedirectUri, properties.RedirectUri); Logger.LogDebug(Resources.OIDCH_0030_Using_Properties_RedirectUri, properties.RedirectUri);
} }
else if (Options.DefaultToCurrentUriOnRedirect) else if (Options.DefaultToCurrentUriOnRedirect)
{ {
_logger.LogDebug(Resources.OIDCH_0032_UsingCurrentUriRedirectUri, CurrentUri); Logger.LogDebug(Resources.OIDCH_0032_UsingCurrentUriRedirectUri, CurrentUri);
properties.RedirectUri = CurrentUri; properties.RedirectUri = CurrentUri;
} }
if (!string.IsNullOrWhiteSpace(Options.RedirectUri)) if (!string.IsNullOrWhiteSpace(Options.RedirectUri))
{ {
_logger.LogDebug(Resources.OIDCH_0031_Using_Options_RedirectUri, Options.RedirectUri); Logger.LogDebug(Resources.OIDCH_0031_Using_Options_RedirectUri, Options.RedirectUri);
} }
// When redeeming a 'code' for an AccessToken, this value is needed // When redeeming a 'code' for an AccessToken, this value is needed
@ -203,7 +190,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
{ {
if (!Options.NonceCache.TryAddNonce(message.Nonce)) if (!Options.NonceCache.TryAddNonce(message.Nonce))
{ {
_logger.LogError(Resources.OIDCH_0033_TryAddNonceFailed, message.Nonce); Logger.LogError(Resources.OIDCH_0033_TryAddNonceFailed, message.Nonce);
throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0033_TryAddNonceFailed, message.Nonce)); throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0033_TryAddNonceFailed, message.Nonce));
} }
} }
@ -221,19 +208,19 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
await Options.Notifications.RedirectToIdentityProvider(redirectToIdentityProviderNotification); await Options.Notifications.RedirectToIdentityProvider(redirectToIdentityProviderNotification);
if (redirectToIdentityProviderNotification.HandledResponse) if (redirectToIdentityProviderNotification.HandledResponse)
{ {
_logger.LogInformation(Resources.OIDCH_0034_RedirectToIdentityProviderNotificationHandledResponse); Logger.LogInformation(Resources.OIDCH_0034_RedirectToIdentityProviderNotificationHandledResponse);
return; return;
} }
else if (redirectToIdentityProviderNotification.Skipped) else if (redirectToIdentityProviderNotification.Skipped)
{ {
_logger.LogInformation(Resources.OIDCH_0035_RedirectToIdentityProviderNotificationSkipped); Logger.LogInformation(Resources.OIDCH_0035_RedirectToIdentityProviderNotificationSkipped);
return; return;
} }
string redirectUri = redirectToIdentityProviderNotification.ProtocolMessage.CreateAuthenticationRequestUrl(); var redirectUri = redirectToIdentityProviderNotification.ProtocolMessage.CreateAuthenticationRequestUrl();
if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute)) if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute))
{ {
_logger.LogWarning(Resources.OIDCH_0036_UriIsNotWellFormed, redirectUri); Logger.LogWarning(Resources.OIDCH_0036_UriIsNotWellFormed, redirectUri);
} }
Response.Redirect(redirectUri); Response.Redirect(redirectUri);
@ -251,10 +238,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
/// <remarks>Uses log id's OIDCH-0000 - OIDCH-0025</remarks> /// <remarks>Uses log id's OIDCH-0000 - OIDCH-0025</remarks>
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync() protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{ {
if (_logger.IsEnabled(LogLevel.Debug)) Logger.LogDebug(Resources.OIDCH_0000_AuthenticateCoreAsync, this.GetType());
{
_logger.LogDebug(Resources.OIDCH_0000_AuthenticateCoreAsync, this.GetType());
}
// Allow login to be constrained to a specific path. Need to make this runtime configurable. // Allow login to be constrained to a specific path. Need to make this runtime configurable.
if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path)) if (Options.CallbackPath.HasValue && Options.CallbackPath != (Request.PathBase + Request.Path))
@ -271,7 +255,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
&& Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) && Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)
&& Request.Body.CanRead) && Request.Body.CanRead)
{ {
IFormCollection form = await Request.ReadFormAsync(); var form = await Request.ReadFormAsync();
Request.Body.Seek(0, SeekOrigin.Begin); Request.Body.Seek(0, SeekOrigin.Begin);
message = new OpenIdConnectMessage(form); message = new OpenIdConnectMessage(form);
} }
@ -283,9 +267,9 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
try try
{ {
if (_logger.IsEnabled(LogLevel.Debug)) if (Logger.IsEnabled(LogLevel.Debug))
{ {
_logger.LogDebug(Resources.OIDCH_0001_MessageReceived, message.BuildRedirectUrl()); Logger.LogDebug(Resources.OIDCH_0001_MessageReceived, message.BuildRedirectUrl());
} }
var messageReceivedNotification = var messageReceivedNotification =
@ -297,34 +281,34 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
await Options.Notifications.MessageReceived(messageReceivedNotification); await Options.Notifications.MessageReceived(messageReceivedNotification);
if (messageReceivedNotification.HandledResponse) if (messageReceivedNotification.HandledResponse)
{ {
_logger.LogInformation(Resources.OIDCH_0002_MessageReceivedNotificationHandledResponse); Logger.LogInformation(Resources.OIDCH_0002_MessageReceivedNotificationHandledResponse);
return messageReceivedNotification.AuthenticationTicket; return messageReceivedNotification.AuthenticationTicket;
} }
if (messageReceivedNotification.Skipped) if (messageReceivedNotification.Skipped)
{ {
_logger.LogInformation(Resources.OIDCH_0003_MessageReceivedNotificationSkipped); Logger.LogInformation(Resources.OIDCH_0003_MessageReceivedNotificationSkipped);
return null; return null;
} }
// runtime always adds state, if we don't find it OR we failed to 'unprotect' it this is not a message we should process. // runtime always adds state, if we don't find it OR we failed to 'unprotect' it this is not a message we should process.
if (string.IsNullOrWhiteSpace(message.State)) if (string.IsNullOrWhiteSpace(message.State))
{ {
_logger.LogError(Resources.OIDCH_0004_MessageStateIsNullOrWhiteSpace); Logger.LogError(Resources.OIDCH_0004_MessageStateIsNullOrWhiteSpace);
return null; return null;
} }
var properties = GetPropertiesFromState(message.State); var properties = GetPropertiesFromState(message.State);
if (properties == null) if (properties == null)
{ {
_logger.LogError(Resources.OIDCH_0005_MessageStateIsInvalid); Logger.LogError(Resources.OIDCH_0005_MessageStateIsInvalid);
return null; return null;
} }
// devs will need to hook AuthenticationFailedNotification to avoid having 'raw' runtime errors displayed to users. // devs will need to hook AuthenticationFailedNotification to avoid having 'raw' runtime errors displayed to users.
if (!string.IsNullOrWhiteSpace(message.Error)) if (!string.IsNullOrWhiteSpace(message.Error))
{ {
_logger.LogError(Resources.OIDCH_0006_MessageErrorNotNull, message.Error); Logger.LogError(Resources.OIDCH_0006_MessageErrorNotNull, message.Error);
throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0006_MessageErrorNotNull, message.Error)); throw new OpenIdConnectProtocolException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0006_MessageErrorNotNull, message.Error));
} }
@ -333,14 +317,14 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
if (_configuration == null && Options.ConfigurationManager != null) if (_configuration == null && Options.ConfigurationManager != null)
{ {
_logger.LogDebug(Resources.OIDCH_0007_UpdatingConfiguration); Logger.LogDebug(Resources.OIDCH_0007_UpdatingConfiguration);
_configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted); _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted);
} }
// OpenIdConnect protocol allows a Code to be received without the id_token // OpenIdConnect protocol allows a Code to be received without the id_token
if (!string.IsNullOrWhiteSpace(message.IdToken)) if (!string.IsNullOrWhiteSpace(message.IdToken))
{ {
_logger.LogDebug(Resources.OIDCH_0020_IdTokenReceived, message.IdToken); Logger.LogDebug(Resources.OIDCH_0020_IdTokenReceived, message.IdToken);
var securityTokenReceivedNotification = var securityTokenReceivedNotification =
new SecurityTokenReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options) new SecurityTokenReceivedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions>(Context, Options)
{ {
@ -350,18 +334,18 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification); await Options.Notifications.SecurityTokenReceived(securityTokenReceivedNotification);
if (securityTokenReceivedNotification.HandledResponse) if (securityTokenReceivedNotification.HandledResponse)
{ {
_logger.LogInformation(Resources.OIDCH_0008_SecurityTokenReceivedNotificationHandledResponse); Logger.LogInformation(Resources.OIDCH_0008_SecurityTokenReceivedNotificationHandledResponse);
return securityTokenReceivedNotification.AuthenticationTicket; return securityTokenReceivedNotification.AuthenticationTicket;
} }
if (securityTokenReceivedNotification.Skipped) if (securityTokenReceivedNotification.Skipped)
{ {
_logger.LogInformation(Resources.OIDCH_0009_SecurityTokenReceivedNotificationSkipped); Logger.LogInformation(Resources.OIDCH_0009_SecurityTokenReceivedNotificationSkipped);
return null; return null;
} }
// Copy and augment to avoid cross request race conditions for updated configurations. // Copy and augment to avoid cross request race conditions for updated configurations.
TokenValidationParameters validationParameters = Options.TokenValidationParameters.Clone(); var validationParameters = Options.TokenValidationParameters.Clone();
if (_configuration != null) if (_configuration != null)
{ {
if (string.IsNullOrWhiteSpace(validationParameters.ValidIssuer)) if (string.IsNullOrWhiteSpace(validationParameters.ValidIssuer))
@ -386,7 +370,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
jwt = validatedToken as JwtSecurityToken; jwt = validatedToken as JwtSecurityToken;
if (jwt == null) if (jwt == null)
{ {
_logger.LogError(Resources.OIDCH_0010_ValidatedSecurityTokenNotJwt, validatedToken?.GetType()); Logger.LogError(Resources.OIDCH_0010_ValidatedSecurityTokenNotJwt, validatedToken?.GetType());
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0010_ValidatedSecurityTokenNotJwt, validatedToken?.GetType())); throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0010_ValidatedSecurityTokenNotJwt, validatedToken?.GetType()));
} }
} }
@ -394,7 +378,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
if (validatedToken == null) if (validatedToken == null)
{ {
_logger.LogError(Resources.OIDCH_0011_UnableToValidateToken, message.IdToken); Logger.LogError(Resources.OIDCH_0011_UnableToValidateToken, message.IdToken);
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0011_UnableToValidateToken, message.IdToken)); throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resources.OIDCH_0011_UnableToValidateToken, message.IdToken));
} }
@ -412,13 +396,13 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
// Rename? // Rename?
if (Options.UseTokenLifetime) if (Options.UseTokenLifetime)
{ {
DateTime issued = validatedToken.ValidFrom; var issued = validatedToken.ValidFrom;
if (issued != DateTime.MinValue) if (issued != DateTime.MinValue)
{ {
ticket.Properties.IssuedUtc = issued; ticket.Properties.IssuedUtc = issued;
} }
DateTime expires = validatedToken.ValidTo; var expires = validatedToken.ValidTo;
if (expires != DateTime.MinValue) if (expires != DateTime.MinValue)
{ {
ticket.Properties.ExpiresUtc = expires; ticket.Properties.ExpiresUtc = expires;
@ -435,13 +419,13 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification); await Options.Notifications.SecurityTokenValidated(securityTokenValidatedNotification);
if (securityTokenValidatedNotification.HandledResponse) if (securityTokenValidatedNotification.HandledResponse)
{ {
_logger.LogInformation(Resources.OIDCH_0012_SecurityTokenValidatedNotificationHandledResponse); Logger.LogInformation(Resources.OIDCH_0012_SecurityTokenValidatedNotificationHandledResponse);
return securityTokenValidatedNotification.AuthenticationTicket; return securityTokenValidatedNotification.AuthenticationTicket;
} }
if (securityTokenValidatedNotification.Skipped) if (securityTokenValidatedNotification.Skipped)
{ {
_logger.LogInformation(Resources.OIDCH_0013_SecurityTokenValidatedNotificationSkipped); Logger.LogInformation(Resources.OIDCH_0013_SecurityTokenValidatedNotificationSkipped);
return null; return null;
} }
@ -470,7 +454,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
if (message.Code != null) if (message.Code != null)
{ {
_logger.LogDebug(Resources.OIDCH_0014_CodeReceived, message.Code); Logger.LogDebug(Resources.OIDCH_0014_CodeReceived, message.Code);
if (ticket == null) if (ticket == null)
{ {
ticket = new AuthenticationTicket(properties, Options.AuthenticationScheme); ticket = new AuthenticationTicket(properties, Options.AuthenticationScheme);
@ -489,13 +473,13 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification); await Options.Notifications.AuthorizationCodeReceived(authorizationCodeReceivedNotification);
if (authorizationCodeReceivedNotification.HandledResponse) if (authorizationCodeReceivedNotification.HandledResponse)
{ {
_logger.LogInformation(Resources.OIDCH_0015_CodeReceivedNotificationHandledResponse); Logger.LogInformation(Resources.OIDCH_0015_CodeReceivedNotificationHandledResponse);
return authorizationCodeReceivedNotification.AuthenticationTicket; return authorizationCodeReceivedNotification.AuthenticationTicket;
} }
if (authorizationCodeReceivedNotification.Skipped) if (authorizationCodeReceivedNotification.Skipped)
{ {
_logger.LogInformation(Resources.OIDCH_0016_CodeReceivedNotificationSkipped); Logger.LogInformation(Resources.OIDCH_0016_CodeReceivedNotificationSkipped);
return null; return null;
} }
} }
@ -504,7 +488,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
} }
catch (Exception exception) catch (Exception exception)
{ {
_logger.LogError(Resources.OIDCH_0017_ExceptionOccurredWhileProcessingMessage, exception); Logger.LogError(Resources.OIDCH_0017_ExceptionOccurredWhileProcessingMessage, exception);
// Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification. // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the notification.
if (Options.RefreshOnIssuerKeyNotFound && exception.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException))) if (Options.RefreshOnIssuerKeyNotFound && exception.GetType().Equals(typeof(SecurityTokenSignatureKeyNotFoundException)))
@ -522,13 +506,13 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
await Options.Notifications.AuthenticationFailed(authenticationFailedNotification); await Options.Notifications.AuthenticationFailed(authenticationFailedNotification);
if (authenticationFailedNotification.HandledResponse) if (authenticationFailedNotification.HandledResponse)
{ {
_logger.LogInformation(Resources.OIDCH_0018_AuthenticationFailedNotificationHandledResponse); Logger.LogInformation(Resources.OIDCH_0018_AuthenticationFailedNotificationHandledResponse);
return authenticationFailedNotification.AuthenticationTicket; return authenticationFailedNotification.AuthenticationTicket;
} }
if (authenticationFailedNotification.Skipped) if (authenticationFailedNotification.Skipped)
{ {
_logger.LogInformation(Resources.OIDCH_0019_AuthenticationFailedNotificationSkipped); Logger.LogInformation(Resources.OIDCH_0019_AuthenticationFailedNotificationSkipped);
return null; return null;
} }
@ -579,7 +563,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
{ {
try try
{ {
string nonceDecodedValue = Options.StringDataFormat.Unprotect(nonceKey.Substring(OpenIdConnectAuthenticationDefaults.CookieNoncePrefix.Length, nonceKey.Length - OpenIdConnectAuthenticationDefaults.CookieNoncePrefix.Length)); var nonceDecodedValue = Options.StringDataFormat.Unprotect(nonceKey.Substring(OpenIdConnectAuthenticationDefaults.CookieNoncePrefix.Length, nonceKey.Length - OpenIdConnectAuthenticationDefaults.CookieNoncePrefix.Length));
if (nonceDecodedValue == nonce) if (nonceDecodedValue == nonce)
{ {
var cookieOptions = new CookieOptions var cookieOptions = new CookieOptions
@ -594,7 +578,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogWarning("Failed to un-protect the nonce cookie.", ex); Logger.LogWarning("Failed to un-protect the nonce cookie.", ex);
} }
} }
} }
@ -605,13 +589,13 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
private AuthenticationProperties GetPropertiesFromState(string state) private AuthenticationProperties GetPropertiesFromState(string state)
{ {
// assume a well formed query string: <a=b&>OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey=kasjd;fljasldkjflksdj<&c=d> // assume a well formed query string: <a=b&>OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey=kasjd;fljasldkjflksdj<&c=d>
int startIndex = 0; var startIndex = 0;
if (string.IsNullOrWhiteSpace(state) || (startIndex = state.IndexOf(OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey, StringComparison.Ordinal)) == -1) if (string.IsNullOrWhiteSpace(state) || (startIndex = state.IndexOf(OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey, StringComparison.Ordinal)) == -1)
{ {
return null; return null;
} }
int authenticationIndex = startIndex + OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey.Length; var authenticationIndex = startIndex + OpenIdConnectAuthenticationDefaults.AuthenticationPropertiesKey.Length;
if (authenticationIndex == -1 || authenticationIndex == state.Length || state[authenticationIndex] != '=') if (authenticationIndex == -1 || authenticationIndex == state.Length || state[authenticationIndex] != '=')
{ {
return null; return null;
@ -619,7 +603,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
// scan rest of string looking for '&' // scan rest of string looking for '&'
authenticationIndex++; authenticationIndex++;
int endIndex = state.Substring(authenticationIndex, state.Length - authenticationIndex).IndexOf("&", StringComparison.Ordinal); var endIndex = state.Substring(authenticationIndex, state.Length - authenticationIndex).IndexOf("&", StringComparison.Ordinal);
// -1 => no other parameters are after the AuthenticationPropertiesKey // -1 => no other parameters are after the AuthenticationPropertiesKey
if (endIndex == -1) if (endIndex == -1)
@ -643,8 +627,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
private async Task<bool> InvokeReplyPathAsync() private async Task<bool> InvokeReplyPathAsync()
{ {
AuthenticationTicket ticket = await AuthenticateAsync(); var ticket = await AuthenticateAsync();
if (ticket != null) if (ticket != null)
{ {
if (ticket.Principal != null) if (ticket.Principal != null)

View File

@ -25,8 +25,6 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
/// </summary> /// </summary>
public class OpenIdConnectAuthenticationMiddleware : AuthenticationMiddleware<OpenIdConnectAuthenticationOptions> public class OpenIdConnectAuthenticationMiddleware : AuthenticationMiddleware<OpenIdConnectAuthenticationOptions>
{ {
private readonly ILogger _logger;
/// <summary> /// <summary>
/// Initializes a <see cref="OpenIdConnectAuthenticationMiddleware"/> /// Initializes a <see cref="OpenIdConnectAuthenticationMiddleware"/>
/// </summary> /// </summary>
@ -45,9 +43,8 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
[NotNull] IOptions<ExternalAuthenticationOptions> externalOptions, [NotNull] IOptions<ExternalAuthenticationOptions> externalOptions,
[NotNull] IOptions<OpenIdConnectAuthenticationOptions> options, [NotNull] IOptions<OpenIdConnectAuthenticationOptions> options,
ConfigureOptions<OpenIdConnectAuthenticationOptions> configureOptions = null) ConfigureOptions<OpenIdConnectAuthenticationOptions> configureOptions = null)
: base(next, options, configureOptions) : base(next, options, loggerFactory, configureOptions)
{ {
_logger = loggerFactory.CreateLogger<OpenIdConnectAuthenticationMiddleware>();
if (string.IsNullOrEmpty(Options.SignInScheme) && !string.IsNullOrEmpty(externalOptions.Options.SignInScheme)) if (string.IsNullOrEmpty(Options.SignInScheme) && !string.IsNullOrEmpty(externalOptions.Options.SignInScheme))
{ {
Options.SignInScheme = externalOptions.Options.SignInScheme; Options.SignInScheme = externalOptions.Options.SignInScheme;
@ -120,7 +117,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
Options.MetadataAddress += ".well-known/openid-configuration"; Options.MetadataAddress += ".well-known/openid-configuration";
} }
HttpClient httpClient = new HttpClient(ResolveHttpMessageHandler(Options)); var httpClient = new HttpClient(ResolveHttpMessageHandler(Options));
httpClient.Timeout = Options.BackchannelTimeout; httpClient.Timeout = Options.BackchannelTimeout;
httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
Options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(Options.MetadataAddress, httpClient); Options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(Options.MetadataAddress, httpClient);
@ -134,13 +131,13 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIdConnectAuthenticationOptions"/> supplied to the constructor.</returns> /// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIdConnectAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<OpenIdConnectAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<OpenIdConnectAuthenticationOptions> CreateHandler()
{ {
return new OpenIdConnectAuthenticationHandler(_logger); return new OpenIdConnectAuthenticationHandler();
} }
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")]
private static HttpMessageHandler ResolveHttpMessageHandler(OpenIdConnectAuthenticationOptions options) private static HttpMessageHandler ResolveHttpMessageHandler(OpenIdConnectAuthenticationOptions options)
{ {
HttpMessageHandler handler = options.BackchannelHttpHandler ?? var handler = options.BackchannelHttpHandler ??
#if DNX451 #if DNX451
new WebRequestHandler(); new WebRequestHandler();
// If they provided a validator, apply it or fail. // If they provided a validator, apply it or fail.

View File

@ -38,7 +38,6 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect
/// <remarks> /// <remarks>
/// Defaults: /// Defaults:
/// <para>AddNonceToRequest: true.</para> /// <para>AddNonceToRequest: true.</para>
/// <para>AuthenticationMode: <see cref="AuthenticationMode.Active"/>.</para>
/// <para>BackchannelTimeout: 1 minute.</para> /// <para>BackchannelTimeout: 1 minute.</para>
/// <para>Caption: <see cref="OpenIdConnectAuthenticationDefaults.Caption"/>.</para> /// <para>Caption: <see cref="OpenIdConnectAuthenticationDefaults.Caption"/>.</para>
/// <para>ProtocolValidator: new <see cref="OpenIdConnectProtocolValidator"/>.</para> /// <para>ProtocolValidator: new <see cref="OpenIdConnectProtocolValidator"/>.</para>

View File

@ -12,7 +12,6 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Collections; using Microsoft.AspNet.Http.Collections;
using Microsoft.AspNet.Http.Authentication; using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Authentication;
using Microsoft.AspNet.Authentication.Twitter.Messages; using Microsoft.AspNet.Authentication.Twitter.Messages;
using Microsoft.AspNet.WebUtilities; using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
@ -28,12 +27,10 @@ namespace Microsoft.AspNet.Authentication.Twitter
private const string AccessTokenEndpoint = "https://api.twitter.com/oauth/access_token"; private const string AccessTokenEndpoint = "https://api.twitter.com/oauth/access_token";
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public TwitterAuthenticationHandler(HttpClient httpClient, ILogger logger) public TwitterAuthenticationHandler(HttpClient httpClient)
{ {
_httpClient = httpClient; _httpClient = httpClient;
_logger = logger;
} }
public override async Task<bool> InvokeAsync() public override async Task<bool> InvokeAsync()
@ -55,40 +52,40 @@ namespace Microsoft.AspNet.Authentication.Twitter
AuthenticationProperties properties = null; AuthenticationProperties properties = null;
try try
{ {
IReadableStringCollection query = Request.Query; var query = Request.Query;
string protectedRequestToken = Request.Cookies[StateCookie]; var protectedRequestToken = Request.Cookies[StateCookie];
RequestToken requestToken = Options.StateDataFormat.Unprotect(protectedRequestToken); var requestToken = Options.StateDataFormat.Unprotect(protectedRequestToken);
if (requestToken == null) if (requestToken == null)
{ {
_logger.LogWarning("Invalid state"); Logger.LogWarning("Invalid state");
return null; return null;
} }
properties = requestToken.Properties; properties = requestToken.Properties;
string returnedToken = query.Get("oauth_token"); var returnedToken = query.Get("oauth_token");
if (string.IsNullOrWhiteSpace(returnedToken)) if (string.IsNullOrWhiteSpace(returnedToken))
{ {
_logger.LogWarning("Missing oauth_token"); Logger.LogWarning("Missing oauth_token");
return new AuthenticationTicket(properties, Options.AuthenticationScheme); return new AuthenticationTicket(properties, Options.AuthenticationScheme);
} }
if (returnedToken != requestToken.Token) if (returnedToken != requestToken.Token)
{ {
_logger.LogWarning("Unmatched token"); Logger.LogWarning("Unmatched token");
return new AuthenticationTicket(properties, Options.AuthenticationScheme); return new AuthenticationTicket(properties, Options.AuthenticationScheme);
} }
string oauthVerifier = query.Get("oauth_verifier"); string oauthVerifier = query.Get("oauth_verifier");
if (string.IsNullOrWhiteSpace(oauthVerifier)) if (string.IsNullOrWhiteSpace(oauthVerifier))
{ {
_logger.LogWarning("Missing or blank oauth_verifier"); Logger.LogWarning("Missing or blank oauth_verifier");
return new AuthenticationTicket(properties, Options.AuthenticationScheme); return new AuthenticationTicket(properties, Options.AuthenticationScheme);
} }
AccessToken accessToken = await ObtainAccessTokenAsync(Options.ConsumerKey, Options.ConsumerSecret, requestToken, oauthVerifier); var accessToken = await ObtainAccessTokenAsync(Options.ConsumerKey, Options.ConsumerSecret, requestToken, oauthVerifier);
var context = new TwitterAuthenticatedContext(Context, accessToken.UserId, accessToken.ScreenName, accessToken.Token, accessToken.TokenSecret); var context = new TwitterAuthenticatedContext(Context, accessToken.UserId, accessToken.ScreenName, accessToken.Token, accessToken.TokenSecret);
@ -120,7 +117,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError("Authentication failed", ex); Logger.LogError("Authentication failed", ex);
return new AuthenticationTicket(properties, Options.AuthenticationScheme); return new AuthenticationTicket(properties, Options.AuthenticationScheme);
} }
} }
@ -148,8 +145,8 @@ namespace Microsoft.AspNet.Authentication.Twitter
return; return;
} }
string requestPrefix = Request.Scheme + "://" + Request.Host; var requestPrefix = Request.Scheme + "://" + Request.Host;
string callBackUrl = requestPrefix + RequestPathBase + Options.CallbackPath; var callBackUrl = requestPrefix + RequestPathBase + Options.CallbackPath;
AuthenticationProperties properties; AuthenticationProperties properties;
if (ChallengeContext == null) if (ChallengeContext == null)
@ -165,11 +162,11 @@ namespace Microsoft.AspNet.Authentication.Twitter
properties.RedirectUri = requestPrefix + Request.PathBase + Request.Path + Request.QueryString; properties.RedirectUri = requestPrefix + Request.PathBase + Request.Path + Request.QueryString;
} }
RequestToken requestToken = await ObtainRequestTokenAsync(Options.ConsumerKey, Options.ConsumerSecret, callBackUrl, properties); var requestToken = await ObtainRequestTokenAsync(Options.ConsumerKey, Options.ConsumerSecret, callBackUrl, properties);
if (requestToken.CallbackConfirmed) if (requestToken.CallbackConfirmed)
{ {
string twitterAuthenticationEndpoint = AuthenticationEndpoint + requestToken.Token; var twitterAuthenticationEndpoint = AuthenticationEndpoint + requestToken.Token;
var cookieOptions = new CookieOptions var cookieOptions = new CookieOptions
{ {
@ -186,16 +183,16 @@ namespace Microsoft.AspNet.Authentication.Twitter
} }
else else
{ {
_logger.LogError("requestToken CallbackConfirmed!=true"); Logger.LogError("requestToken CallbackConfirmed!=true");
} }
} }
public async Task<bool> InvokeReturnPathAsync() public async Task<bool> InvokeReturnPathAsync()
{ {
AuthenticationTicket model = await AuthenticateAsync(); var model = await AuthenticateAsync();
if (model == null) if (model == null)
{ {
_logger.LogWarning("Invalid return state, unable to redirect."); Logger.LogWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500; Response.StatusCode = 500;
return true; return true;
} }
@ -230,9 +227,9 @@ namespace Microsoft.AspNet.Authentication.Twitter
private async Task<RequestToken> ObtainRequestTokenAsync(string consumerKey, string consumerSecret, string callBackUri, AuthenticationProperties properties) private async Task<RequestToken> ObtainRequestTokenAsync(string consumerKey, string consumerSecret, string callBackUri, AuthenticationProperties properties)
{ {
_logger.LogVerbose("ObtainRequestToken"); Logger.LogVerbose("ObtainRequestToken");
string nonce = Guid.NewGuid().ToString("N"); var nonce = Guid.NewGuid().ToString("N");
var authorizationParts = new SortedDictionary<string, string> var authorizationParts = new SortedDictionary<string, string>
{ {
@ -250,7 +247,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
parameterBuilder.AppendFormat("{0}={1}&", Uri.EscapeDataString(authorizationKey.Key), Uri.EscapeDataString(authorizationKey.Value)); parameterBuilder.AppendFormat("{0}={1}&", Uri.EscapeDataString(authorizationKey.Key), Uri.EscapeDataString(authorizationKey.Value));
} }
parameterBuilder.Length--; parameterBuilder.Length--;
string parameterString = parameterBuilder.ToString(); var parameterString = parameterBuilder.ToString();
var canonicalizedRequestBuilder = new StringBuilder(); var canonicalizedRequestBuilder = new StringBuilder();
canonicalizedRequestBuilder.Append(HttpMethod.Post.Method); canonicalizedRequestBuilder.Append(HttpMethod.Post.Method);
@ -259,7 +256,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
canonicalizedRequestBuilder.Append("&"); canonicalizedRequestBuilder.Append("&");
canonicalizedRequestBuilder.Append(Uri.EscapeDataString(parameterString)); canonicalizedRequestBuilder.Append(Uri.EscapeDataString(parameterString));
string signature = ComputeSignature(consumerSecret, null, canonicalizedRequestBuilder.ToString()); var signature = ComputeSignature(consumerSecret, null, canonicalizedRequestBuilder.ToString());
authorizationParts.Add("oauth_signature", signature); authorizationParts.Add("oauth_signature", signature);
var authorizationHeaderBuilder = new StringBuilder(); var authorizationHeaderBuilder = new StringBuilder();
@ -274,11 +271,11 @@ namespace Microsoft.AspNet.Authentication.Twitter
var request = new HttpRequestMessage(HttpMethod.Post, RequestTokenEndpoint); var request = new HttpRequestMessage(HttpMethod.Post, RequestTokenEndpoint);
request.Headers.Add("Authorization", authorizationHeaderBuilder.ToString()); request.Headers.Add("Authorization", authorizationHeaderBuilder.ToString());
HttpResponseMessage response = await _httpClient.SendAsync(request, Context.RequestAborted); var response = await _httpClient.SendAsync(request, Context.RequestAborted);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
string responseText = await response.Content.ReadAsStringAsync(); string responseText = await response.Content.ReadAsStringAsync();
IFormCollection responseParameters = new FormCollection(FormReader.ReadForm(responseText)); var responseParameters = new FormCollection(FormReader.ReadForm(responseText));
if (string.Equals(responseParameters["oauth_callback_confirmed"], "true", StringComparison.Ordinal)) if (string.Equals(responseParameters["oauth_callback_confirmed"], "true", StringComparison.Ordinal))
{ {
return new RequestToken { Token = Uri.UnescapeDataString(responseParameters["oauth_token"]), TokenSecret = Uri.UnescapeDataString(responseParameters["oauth_token_secret"]), CallbackConfirmed = true, Properties = properties }; return new RequestToken { Token = Uri.UnescapeDataString(responseParameters["oauth_token"]), TokenSecret = Uri.UnescapeDataString(responseParameters["oauth_token_secret"]), CallbackConfirmed = true, Properties = properties };
@ -291,9 +288,9 @@ namespace Microsoft.AspNet.Authentication.Twitter
{ {
// https://dev.twitter.com/docs/api/1/post/oauth/access_token // https://dev.twitter.com/docs/api/1/post/oauth/access_token
_logger.LogVerbose("ObtainAccessToken"); Logger.LogVerbose("ObtainAccessToken");
string nonce = Guid.NewGuid().ToString("N"); var nonce = Guid.NewGuid().ToString("N");
var authorizationParts = new SortedDictionary<string, string> var authorizationParts = new SortedDictionary<string, string>
{ {
@ -312,7 +309,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
parameterBuilder.AppendFormat("{0}={1}&", Uri.EscapeDataString(authorizationKey.Key), Uri.EscapeDataString(authorizationKey.Value)); parameterBuilder.AppendFormat("{0}={1}&", Uri.EscapeDataString(authorizationKey.Key), Uri.EscapeDataString(authorizationKey.Value));
} }
parameterBuilder.Length--; parameterBuilder.Length--;
string parameterString = parameterBuilder.ToString(); var parameterString = parameterBuilder.ToString();
var canonicalizedRequestBuilder = new StringBuilder(); var canonicalizedRequestBuilder = new StringBuilder();
canonicalizedRequestBuilder.Append(HttpMethod.Post.Method); canonicalizedRequestBuilder.Append(HttpMethod.Post.Method);
@ -321,7 +318,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
canonicalizedRequestBuilder.Append("&"); canonicalizedRequestBuilder.Append("&");
canonicalizedRequestBuilder.Append(Uri.EscapeDataString(parameterString)); canonicalizedRequestBuilder.Append(Uri.EscapeDataString(parameterString));
string signature = ComputeSignature(consumerSecret, token.TokenSecret, canonicalizedRequestBuilder.ToString()); var signature = ComputeSignature(consumerSecret, token.TokenSecret, canonicalizedRequestBuilder.ToString());
authorizationParts.Add("oauth_signature", signature); authorizationParts.Add("oauth_signature", signature);
authorizationParts.Remove("oauth_verifier"); authorizationParts.Remove("oauth_verifier");
@ -344,17 +341,16 @@ namespace Microsoft.AspNet.Authentication.Twitter
request.Content = new FormUrlEncodedContent(formPairs); request.Content = new FormUrlEncodedContent(formPairs);
HttpResponseMessage response = await _httpClient.SendAsync(request, Context.RequestAborted); var response = await _httpClient.SendAsync(request, Context.RequestAborted);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
_logger.LogError("AccessToken request failed with a status code of " + response.StatusCode); Logger.LogError("AccessToken request failed with a status code of " + response.StatusCode);
response.EnsureSuccessStatusCode(); // throw response.EnsureSuccessStatusCode(); // throw
} }
string responseText = await response.Content.ReadAsStringAsync(); var responseText = await response.Content.ReadAsStringAsync();
var responseParameters = new FormCollection(FormReader.ReadForm(responseText));
IFormCollection responseParameters = new FormCollection(FormReader.ReadForm(responseText));
return new AccessToken return new AccessToken
{ {
@ -367,7 +363,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
private static string GenerateTimeStamp() private static string GenerateTimeStamp()
{ {
TimeSpan secondsSinceUnixEpocStart = DateTime.UtcNow - Epoch; var secondsSinceUnixEpocStart = DateTime.UtcNow - Epoch;
return Convert.ToInt64(secondsSinceUnixEpocStart.TotalSeconds).ToString(CultureInfo.InvariantCulture); return Convert.ToInt64(secondsSinceUnixEpocStart.TotalSeconds).ToString(CultureInfo.InvariantCulture);
} }
@ -380,7 +376,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
"{0}&{1}", "{0}&{1}",
Uri.EscapeDataString(consumerSecret), Uri.EscapeDataString(consumerSecret),
string.IsNullOrEmpty(tokenSecret) ? string.Empty : Uri.EscapeDataString(tokenSecret))); string.IsNullOrEmpty(tokenSecret) ? string.Empty : Uri.EscapeDataString(tokenSecret)));
byte[] hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(signatureData)); var hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(signatureData));
return Convert.ToBase64String(hash); return Convert.ToBase64String(hash);
} }
} }
@ -390,4 +386,4 @@ namespace Microsoft.AspNet.Authentication.Twitter
// N/A - No SignIn or SignOut support. // N/A - No SignIn or SignOut support.
} }
} }
} }

View File

@ -22,7 +22,6 @@ namespace Microsoft.AspNet.Authentication.Twitter
[SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Middleware are not disposable.")] [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Middleware are not disposable.")]
public class TwitterAuthenticationMiddleware : AuthenticationMiddleware<TwitterAuthenticationOptions> public class TwitterAuthenticationMiddleware : AuthenticationMiddleware<TwitterAuthenticationOptions>
{ {
private readonly ILogger _logger;
private readonly HttpClient _httpClient; private readonly HttpClient _httpClient;
/// <summary> /// <summary>
@ -40,7 +39,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
[NotNull] IOptions<ExternalAuthenticationOptions> externalOptions, [NotNull] IOptions<ExternalAuthenticationOptions> externalOptions,
[NotNull] IOptions<TwitterAuthenticationOptions> options, [NotNull] IOptions<TwitterAuthenticationOptions> options,
ConfigureOptions<TwitterAuthenticationOptions> configureOptions = null) ConfigureOptions<TwitterAuthenticationOptions> configureOptions = null)
: base(next, options, configureOptions) : base(next, options, loggerFactory, configureOptions)
{ {
if (string.IsNullOrWhiteSpace(Options.ConsumerSecret)) if (string.IsNullOrWhiteSpace(Options.ConsumerSecret))
{ {
@ -51,8 +50,6 @@ namespace Microsoft.AspNet.Authentication.Twitter
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ConsumerKey")); throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ConsumerKey"));
} }
_logger = loggerFactory.CreateLogger(typeof(TwitterAuthenticationMiddleware).FullName);
if (Options.Notifications == null) if (Options.Notifications == null)
{ {
Options.Notifications = new TwitterAuthenticationNotifications(); Options.Notifications = new TwitterAuthenticationNotifications();
@ -90,7 +87,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="TwitterAuthenticationOptions"/> supplied to the constructor.</returns> /// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="TwitterAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<TwitterAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<TwitterAuthenticationOptions> CreateHandler()
{ {
return new TwitterAuthenticationHandler(_httpClient, _logger); return new TwitterAuthenticationHandler(_httpClient);
} }
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")]

View File

@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -50,6 +48,8 @@ namespace Microsoft.AspNet.Authentication
protected PathString RequestPathBase { get; private set; } protected PathString RequestPathBase { get; private set; }
protected ILogger Logger { get; private set; }
internal AuthenticationOptions BaseOptions internal AuthenticationOptions BaseOptions
{ {
get { return _baseOptions; } get { return _baseOptions; }
@ -61,11 +61,12 @@ namespace Microsoft.AspNet.Authentication
public bool Faulted { get; set; } public bool Faulted { get; set; }
protected async Task BaseInitializeAsync(AuthenticationOptions options, HttpContext context) protected async Task BaseInitializeAsync([NotNull] AuthenticationOptions options, [NotNull] HttpContext context, [NotNull] ILogger logger)
{ {
_baseOptions = options; _baseOptions = options;
Context = context; Context = context;
RequestPathBase = Request.PathBase; RequestPathBase = Request.PathBase;
Logger = logger;
RegisterAuthenticationHandler(); RegisterAuthenticationHandler();
@ -414,13 +415,13 @@ namespace Microsoft.AspNet.Authentication
Response.Cookies.Append(correlationKey, correlationId, cookieOptions); Response.Cookies.Append(correlationKey, correlationId, cookieOptions);
} }
protected bool ValidateCorrelationId([NotNull] AuthenticationProperties properties, [NotNull] ILogger logger) protected bool ValidateCorrelationId([NotNull] AuthenticationProperties properties)
{ {
var correlationKey = Constants.CorrelationPrefix + BaseOptions.AuthenticationScheme; var correlationKey = Constants.CorrelationPrefix + BaseOptions.AuthenticationScheme;
var correlationCookie = Request.Cookies[correlationKey]; var correlationCookie = Request.Cookies[correlationKey];
if (string.IsNullOrWhiteSpace(correlationCookie)) if (string.IsNullOrWhiteSpace(correlationCookie))
{ {
logger.LogWarning("{0} cookie not found.", correlationKey); Logger.LogWarning("{0} cookie not found.", correlationKey);
return false; return false;
} }
@ -436,7 +437,7 @@ namespace Microsoft.AspNet.Authentication
correlationKey, correlationKey,
out correlationExtra)) out correlationExtra))
{ {
logger.LogWarning("{0} state property not found.", correlationKey); Logger.LogWarning("{0} state property not found.", correlationKey);
return false; return false;
} }
@ -444,7 +445,7 @@ namespace Microsoft.AspNet.Authentication
if (!string.Equals(correlationCookie, correlationExtra, StringComparison.Ordinal)) if (!string.Equals(correlationCookie, correlationExtra, StringComparison.Ordinal))
{ {
logger.LogWarning("{0} correlation cookie and state property mismatch.", correlationKey); Logger.LogWarning("{0} correlation cookie and state property mismatch.", correlationKey);
return false; return false;
} }
@ -464,5 +465,4 @@ namespace Microsoft.AspNet.Authentication
auth.Handler = PriorHandler; auth.Handler = PriorHandler;
} }
} }
} }

View File

@ -3,6 +3,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.Framework.Logging;
namespace Microsoft.AspNet.Authentication namespace Microsoft.AspNet.Authentication
{ {
@ -19,11 +20,12 @@ namespace Microsoft.AspNet.Authentication
/// </summary> /// </summary>
/// <param name="options">The original options passed by the application control behavior</param> /// <param name="options">The original options passed by the application control behavior</param>
/// <param name="context">The utility object to observe the current request and response</param> /// <param name="context">The utility object to observe the current request and response</param>
/// <param name="logger">The logging factory used to create loggers</param>
/// <returns>async completion</returns> /// <returns>async completion</returns>
public Task Initialize(TOptions options, HttpContext context) public Task Initialize(TOptions options, HttpContext context, ILogger logger)
{ {
Options = options; Options = options;
return BaseInitializeAsync(options, context); return BaseInitializeAsync(options, context, logger);
} }
} }
} }

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.Logging;
using Microsoft.Framework.OptionsModel; using Microsoft.Framework.OptionsModel;
namespace Microsoft.AspNet.Authentication namespace Microsoft.AspNet.Authentication
@ -17,6 +18,7 @@ namespace Microsoft.AspNet.Authentication
protected AuthenticationMiddleware( protected AuthenticationMiddleware(
[NotNull] RequestDelegate next, [NotNull] RequestDelegate next,
[NotNull] IOptions<TOptions> options, [NotNull] IOptions<TOptions> options,
[NotNull] ILoggerFactory loggerFactory,
ConfigureOptions<TOptions> configureOptions) ConfigureOptions<TOptions> configureOptions)
{ {
if (configureOptions != null) if (configureOptions != null)
@ -28,6 +30,8 @@ namespace Microsoft.AspNet.Authentication
{ {
Options = options.Options; Options = options.Options;
} }
Logger = loggerFactory.CreateLogger(this.GetType().FullName);
_next = next; _next = next;
} }
@ -35,10 +39,12 @@ namespace Microsoft.AspNet.Authentication
public TOptions Options { get; set; } public TOptions Options { get; set; }
public ILogger Logger { get; set; }
public async Task Invoke(HttpContext context) public async Task Invoke(HttpContext context)
{ {
AuthenticationHandler<TOptions> handler = CreateHandler(); var handler = CreateHandler();
await handler.Initialize(Options, context); await handler.Initialize(Options, context, Logger);
try try
{ {
if (!await handler.InvokeAsync()) if (!await handler.InvokeAsync())

View File

@ -75,4 +75,4 @@ namespace Microsoft.AspNet.Authorization
return any ? policyBuilder.Build() : null; return any ? policyBuilder.Build() : null;
} }
} }
} }

View File

@ -3,6 +3,7 @@
using System; using System;
using Microsoft.AspNet.Http; using Microsoft.AspNet.Http;
using Microsoft.Framework.Logging;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Authentication namespace Microsoft.AspNet.Authentication
@ -13,12 +14,10 @@ namespace Microsoft.AspNet.Authentication
public void ShouldHandleSchemeAreDeterminedOnlyByMatchingAuthenticationScheme() public void ShouldHandleSchemeAreDeterminedOnlyByMatchingAuthenticationScheme()
{ {
var handler = new TestHandler("Alpha"); var handler = new TestHandler("Alpha");
var passiveNoMatch = handler.ShouldHandleScheme("Beta");
bool passiveNoMatch = handler.ShouldHandleScheme("Beta");
handler = new TestHandler("Alpha"); handler = new TestHandler("Alpha");
var passiveWithMatch = handler.ShouldHandleScheme("Alpha");
bool passiveWithMatch = handler.ShouldHandleScheme("Alpha");
Assert.False(passiveNoMatch); Assert.False(passiveNoMatch);
Assert.True(passiveWithMatch); Assert.True(passiveWithMatch);
@ -56,7 +55,7 @@ namespace Microsoft.AspNet.Authentication
{ {
public TestHandler(string scheme) public TestHandler(string scheme)
{ {
Initialize(new TestOptions(), new DefaultHttpContext()); Initialize(new TestOptions(), new DefaultHttpContext(), new LoggerFactory().CreateLogger("TestHandler"));
Options.AuthenticationScheme = scheme; Options.AuthenticationScheme = scheme;
} }
@ -90,7 +89,7 @@ namespace Microsoft.AspNet.Authentication
{ {
public TestAutoHandler(string scheme, bool auto) public TestAutoHandler(string scheme, bool auto)
{ {
Initialize(new TestAutoOptions(), new DefaultHttpContext()); Initialize(new TestAutoOptions(), new DefaultHttpContext(), new LoggerFactory().CreateLogger("TestHandler"));
Options.AuthenticationScheme = scheme; Options.AuthenticationScheme = scheme;
Options.AutomaticAuthentication = auto; Options.AutomaticAuthentication = auto;
} }

View File

@ -226,6 +226,8 @@ namespace Microsoft.AspNet.Authentication.Google
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.InternalServerError); transaction.Response.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
} }
[Fact] [Fact]
public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState() public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState()
{ {

View File

@ -565,14 +565,9 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect
/// </summary> /// </summary>
public class CustomOpenIdConnectAuthenticationHandler : OpenIdConnectAuthenticationHandler public class CustomOpenIdConnectAuthenticationHandler : OpenIdConnectAuthenticationHandler
{ {
public CustomOpenIdConnectAuthenticationHandler(ILogger logger) public async Task BaseInitializeAsyncPublic(AuthenticationOptions options, HttpContext context, ILogger logger)
: base(logger)
{ {
} await base.BaseInitializeAsync(options, context, logger);
public async Task BaseInitializeAsyncPublic(AuthenticationOptions options, HttpContext context)
{
await base.BaseInitializeAsync(options, context);
} }
public override bool ShouldHandleScheme(string authenticationScheme) public override bool ShouldHandleScheme(string authenticationScheme)
@ -619,13 +614,7 @@ namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect
protected override AuthenticationHandler<OpenIdConnectAuthenticationOptions> CreateHandler() protected override AuthenticationHandler<OpenIdConnectAuthenticationOptions> CreateHandler()
{ {
return new CustomOpenIdConnectAuthenticationHandler(Logger); return new CustomOpenIdConnectAuthenticationHandler();
}
public ILogger Logger
{
get;
set;
} }
} }

View File

@ -13,5 +13,8 @@
<PropertyGroup> <PropertyGroup>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" /> <Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project> </Project>