Move ClaimsIssuer to base AuthenticationOptions

Also step 1 of refactoring tests
This commit is contained in:
Hao Kung 2015-05-05 14:50:59 -07:00
parent f864244124
commit ce48c1fc7d
27 changed files with 327 additions and 492 deletions

View File

@ -193,8 +193,8 @@ namespace Microsoft.AspNet.Authentication.Cookies
_sessionKey = await Options.SessionStore.StoreAsync(model);
var principal = new ClaimsPrincipal(
new ClaimsIdentity(
new[] { new Claim(SessionIdClaim, _sessionKey) },
Options.AuthenticationScheme));
new[] { new Claim(SessionIdClaim, _sessionKey, ClaimValueTypes.String, Options.ClaimsIssuer) },
Options.ClaimsIssuer));
model = new AuthenticationTicket(principal, null, Options.AuthenticationScheme);
}
var cookieValue = Options.TicketDataFormat.Protect(model);
@ -243,7 +243,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
await Options.SessionStore.RenewAsync(_sessionKey, model);
var principal = new ClaimsPrincipal(
new ClaimsIdentity(
new[] { new Claim(SessionIdClaim, _sessionKey) },
new[] { new Claim(SessionIdClaim, _sessionKey, ClaimValueTypes.String, Options.ClaimsIssuer) },
Options.AuthenticationScheme));
model = new AuthenticationTicket(principal, null, Options.AuthenticationScheme);
}

View File

@ -13,7 +13,6 @@ using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Http.Collections;
using Microsoft.AspNet.Http.Extensions;
using Microsoft.AspNet.WebUtilities;
using Microsoft.Framework.WebEncoders;
using Newtonsoft.Json.Linq;
namespace Microsoft.AspNet.Authentication.Facebook
@ -65,34 +64,34 @@ namespace Microsoft.AspNet.Authentication.Facebook
var context = new FacebookAuthenticatedContext(Context, Options, user, tokens);
var identity = new ClaimsIdentity(
Options.AuthenticationScheme,
Options.ClaimsIssuer,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, ClaimValueTypes.String, Options.AuthenticationScheme));
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, ClaimValueTypes.String, Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.UserName))
{
identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, ClaimValueTypes.String, Options.AuthenticationScheme));
identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, ClaimValueTypes.String, Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.Email))
{
identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, ClaimValueTypes.String, Options.AuthenticationScheme));
identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, ClaimValueTypes.String, Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.Name))
{
identity.AddClaim(new Claim("urn:facebook:name", context.Name, ClaimValueTypes.String, Options.AuthenticationScheme));
identity.AddClaim(new Claim("urn:facebook:name", context.Name, ClaimValueTypes.String, Options.ClaimsIssuer));
// Many Facebook accounts do not set the UserName field. Fall back to the Name field instead.
if (string.IsNullOrEmpty(context.UserName))
{
identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, ClaimValueTypes.String, Options.AuthenticationScheme));
identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name, ClaimValueTypes.String, Options.ClaimsIssuer));
}
}
if (!string.IsNullOrEmpty(context.Link))
{
identity.AddClaim(new Claim("urn:facebook:link", context.Link, ClaimValueTypes.String, Options.AuthenticationScheme));
identity.AddClaim(new Claim("urn:facebook:link", context.Link, ClaimValueTypes.String, Options.ClaimsIssuer));
}
context.Properties = properties;
context.Principal = new ClaimsPrincipal(identity);
@ -104,7 +103,7 @@ namespace Microsoft.AspNet.Authentication.Facebook
private string GenerateAppSecretProof(string accessToken)
{
using (HMACSHA256 algorithm = new HMACSHA256(Encoding.ASCII.GetBytes(Options.AppSecret)))
using (var algorithm = new HMACSHA256(Encoding.ASCII.GetBytes(Options.AppSecret)))
{
var hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(accessToken));
var builder = new StringBuilder();
@ -124,4 +123,4 @@ namespace Microsoft.AspNet.Authentication.Facebook
return string.Join(",", Options.Scope);
}
}
}
}

View File

@ -33,39 +33,39 @@ namespace Microsoft.AspNet.Authentication.Google
var context = new GoogleAuthenticatedContext(Context, Options, user, tokens);
var identity = new ClaimsIdentity(
Options.AuthenticationScheme,
Options.ClaimsIssuer,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id,
ClaimValueTypes.String, Options.AuthenticationScheme));
ClaimValueTypes.String, Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.GivenName))
{
identity.AddClaim(new Claim(ClaimTypes.GivenName, context.GivenName,
ClaimValueTypes.String, Options.AuthenticationScheme));
ClaimValueTypes.String, Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.FamilyName))
{
identity.AddClaim(new Claim(ClaimTypes.Surname, context.FamilyName,
ClaimValueTypes.String, Options.AuthenticationScheme));
ClaimValueTypes.String, Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.Name))
{
identity.AddClaim(new Claim(ClaimTypes.Name, context.Name, ClaimValueTypes.String,
Options.AuthenticationScheme));
Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.Email))
{
identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, ClaimValueTypes.String,
Options.AuthenticationScheme));
Options.ClaimsIssuer));
}
if (!string.IsNullOrEmpty(context.Profile))
{
identity.AddClaim(new Claim("urn:google:profile", context.Profile, ClaimValueTypes.String,
Options.AuthenticationScheme));
Options.ClaimsIssuer));
}
context.Properties = properties;
context.Principal = new ClaimsPrincipal(identity);
@ -120,4 +120,4 @@ namespace Microsoft.AspNet.Authentication.Google
queryStrings[name] = value;
}
}
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNet.Authentication.OAuth;
using Microsoft.AspNet.Builder;

View File

@ -1,12 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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 Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Authentication;
using Microsoft.AspNet.Authentication.OAuth;
using Microsoft.AspNet.Http;
namespace Microsoft.AspNet.Authentication.Google
{

View File

@ -32,18 +32,18 @@ namespace Microsoft.AspNet.Authentication.MicrosoftAccount
var identity = new ClaimsIdentity(
new[]
{
new Claim(ClaimTypes.NameIdentifier, context.Id, ClaimValueTypes.String, Options.AuthenticationScheme),
new Claim(ClaimTypes.Name, context.Name, ClaimValueTypes.String, Options.AuthenticationScheme),
new Claim("urn:microsoftaccount:id", context.Id, ClaimValueTypes.String, Options.AuthenticationScheme),
new Claim("urn:microsoftaccount:name", context.Name, ClaimValueTypes.String, Options.AuthenticationScheme)
new Claim(ClaimTypes.NameIdentifier, context.Id, ClaimValueTypes.String, Options.ClaimsIssuer),
new Claim(ClaimTypes.Name, context.Name, ClaimValueTypes.String, Options.ClaimsIssuer),
new Claim("urn:microsoftaccount:id", context.Id, ClaimValueTypes.String, Options.ClaimsIssuer),
new Claim("urn:microsoftaccount:name", context.Name, ClaimValueTypes.String, Options.ClaimsIssuer)
},
Options.AuthenticationScheme,
Options.ClaimsIssuer,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrWhiteSpace(context.Email))
{
identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, ClaimValueTypes.String, Options.AuthenticationScheme));
identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, ClaimValueTypes.String, Options.ClaimsIssuer));
}
context.Principal = new ClaimsPrincipal(identity);

View File

@ -69,7 +69,7 @@ namespace Microsoft.AspNet.Authentication.OAuth
if (Options.StateDataFormat == null)
{
var dataProtector = dataProtectionProvider.CreateProtector(
this.GetType().FullName, Options.AuthenticationScheme, "v1");
GetType().FullName, Options.AuthenticationScheme, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}

View File

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Authentication;
@ -106,11 +105,6 @@ namespace Microsoft.AspNet.Authentication.OAuth
/// </summary>
public string SignInScheme { get; set; }
/// <summary>
/// Gets or sets the issuer that should be used for any claims that are created
/// </summary>
public string ClaimsIssuer { get; set; }
/// <summary>
/// Gets or sets the type used to secure data handled by the middleware.
/// </summary>

View File

@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
// notify user token was received
var securityTokenReceivedNotification =
new SecurityTokenReceivedNotification<HttpContext, OAuthBearerAuthenticationOptions>(Context, Options)
new SecurityTokenReceivedNotification<HttpContext, OAuthBearerAuthenticationOptions>(Context, Options)
{
ProtocolMessage = Context,
SecurityToken = token,
@ -110,7 +110,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
}
else
{
IEnumerable<string> issuers = new[] { _configuration.Issuer };
var issuers = new[] { _configuration.Issuer };
validationParameters.ValidIssuers = (validationParameters.ValidIssuers == null ? issuers : validationParameters.ValidIssuers.Concat(issuers));
}
@ -122,8 +122,8 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
{
if (validator.CanReadToken(token))
{
ClaimsPrincipal principal = validator.ValidateToken(token, validationParameters, out validatedToken);
AuthenticationTicket ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Options.AuthenticationScheme);
var principal = validator.ValidateToken(token, validationParameters, out validatedToken);
var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), Options.AuthenticationScheme);
var securityTokenValidatedNotification = new SecurityTokenValidatedNotification<HttpContext, OAuthBearerAuthenticationOptions>(Context, Options)
{
ProtocolMessage = Context,

View File

@ -23,8 +23,6 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
/// </summary>
public class OAuthBearerAuthenticationMiddleware : AuthenticationMiddleware<OAuthBearerAuthenticationOptions>
{
private readonly ILogger _logger;
/// <summary>
/// Bearer authentication component which is added to an HTTP pipeline. This constructor is not
/// called by application code directly, instead it is added by calling the the IAppBuilder UseOAuthBearerAuthentication
@ -72,7 +70,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
Options.MetadataAddress += ".well-known/openid-configuration";
}
HttpClient httpClient = new HttpClient(ResolveHttpMessageHandler(Options));
var httpClient = new HttpClient(ResolveHttpMessageHandler(Options));
httpClient.Timeout = Options.BackchannelTimeout;
httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.Net.Http;
using Microsoft.AspNet.Authentication;
using Microsoft.IdentityModel.Protocols;
namespace Microsoft.AspNet.Authentication.OAuthBearer

View File

@ -78,7 +78,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
return new AuthenticationTicket(properties, Options.AuthenticationScheme);
}
string oauthVerifier = query.Get("oauth_verifier");
var oauthVerifier = query.Get("oauth_verifier");
if (string.IsNullOrWhiteSpace(oauthVerifier))
{
Logger.LogWarning("Missing or blank oauth_verifier");
@ -93,12 +93,12 @@ namespace Microsoft.AspNet.Authentication.Twitter
new ClaimsIdentity(
new[]
{
new Claim(ClaimTypes.NameIdentifier, accessToken.UserId, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationScheme),
new Claim(ClaimTypes.Name, accessToken.ScreenName, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationScheme),
new Claim("urn:twitter:userid", accessToken.UserId, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationScheme),
new Claim("urn:twitter:screenname", accessToken.ScreenName, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationScheme)
new Claim(ClaimTypes.NameIdentifier, accessToken.UserId, "http://www.w3.org/2001/XMLSchema#string", Options.ClaimsIssuer),
new Claim(ClaimTypes.Name, accessToken.ScreenName, "http://www.w3.org/2001/XMLSchema#string", Options.ClaimsIssuer),
new Claim("urn:twitter:userid", accessToken.UserId, "http://www.w3.org/2001/XMLSchema#string", Options.ClaimsIssuer),
new Claim("urn:twitter:screenname", accessToken.ScreenName, "http://www.w3.org/2001/XMLSchema#string", Options.ClaimsIssuer)
},
Options.AuthenticationScheme,
Options.ClaimsIssuer,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType));
context.Properties = requestToken.Properties;

View File

@ -35,6 +35,12 @@ namespace Microsoft.AspNet.Authentication
Logger = loggerFactory.CreateLogger(this.GetType().FullName);
UrlEncoder = encoder;
if (string.IsNullOrEmpty(Options.ClaimsIssuer))
{
// Default to something reasonable
Options.ClaimsIssuer = Options.AuthenticationScheme;
}
_next = next;
}

View File

@ -33,6 +33,11 @@ namespace Microsoft.AspNet.Authentication
/// </summary>
public bool AutomaticAuthentication { get; set; }
/// <summary>
/// Gets or sets the issuer that should be used for any claims that are created
/// </summary>
public string ClaimsIssuer { get; set; }
/// <summary>
/// Additional information about the authentication type which is made available to the application.
/// </summary>

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. 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.Framework.Internal;

View File

@ -1,9 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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.Linq;
using System.Security.Claims;
using Microsoft.AspNet.Http;
using Microsoft.Framework.Internal;
@ -21,7 +18,7 @@ namespace Microsoft.AspNet.Authentication
/// <param name="identity"></param>
public static void AddUserPrincipal([NotNull] HttpContext context, [NotNull] ClaimsPrincipal principal)
{
ClaimsPrincipal existingPrincipal = context.User;
var existingPrincipal = context.User;
if (existingPrincipal != null)
{
foreach (var existingClaimsIdentity in existingPrincipal.Identities)

View File

@ -27,10 +27,10 @@ namespace Microsoft.AspNet.Authentication.Cookies
[Fact]
public async Task NormalRequestPassesThrough()
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
});
HttpResponseMessage response = await server.CreateClient().GetAsync("http://example.com/normal");
var response = await server.CreateClient().GetAsync("http://example.com/normal");
response.StatusCode.ShouldBe(HttpStatusCode.OK);
}
@ -39,13 +39,13 @@ namespace Microsoft.AspNet.Authentication.Cookies
[InlineData(false)]
public async Task ProtectedRequestShouldRedirectToLoginOnlyWhenAutomatic(bool auto)
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.LoginPath = new PathString("/login");
options.AutomaticAuthentication = auto;
});
Transaction transaction = await SendAsync(server, "http://example.com/protected");
var transaction = await SendAsync(server, "http://example.com/protected");
transaction.Response.StatusCode.ShouldBe(auto ? HttpStatusCode.Redirect : HttpStatusCode.Unauthorized);
if (auto)
@ -61,13 +61,13 @@ namespace Microsoft.AspNet.Authentication.Cookies
[InlineData(false)]
public async Task ProtectedCustomRequestShouldRedirectToCustomLogin(bool auto)
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.LoginPath = new PathString("/login");
options.AutomaticAuthentication = auto;
});
Transaction transaction = await SendAsync(server, "http://example.com/protected/CustomRedirect");
var transaction = await SendAsync(server, "http://example.com/protected/CustomRedirect");
transaction.Response.StatusCode.ShouldBe(auto ? HttpStatusCode.Redirect : HttpStatusCode.Unauthorized);
if (auto)
@ -102,15 +102,15 @@ namespace Microsoft.AspNet.Authentication.Cookies
[Fact]
public async Task SignInCausesDefaultCookieToBeCreated()
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.LoginPath = new PathString("/login");
options.CookieName = "TestCookie";
}, SignInAsAlice);
Transaction transaction = await SendAsync(server, "http://example.com/testpath");
var transaction = await SendAsync(server, "http://example.com/testpath");
string setCookie = transaction.SetCookie;
var setCookie = transaction.SetCookie;
setCookie.ShouldStartWith("TestCookie=");
setCookie.ShouldContain("; path=/");
setCookie.ShouldContain("; HttpOnly");
@ -122,7 +122,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
[Fact]
public async Task SignInWrongAuthTypeThrows()
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.LoginPath = new PathString("/login");
options.CookieName = "TestCookie";
@ -134,7 +134,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
[Fact]
public async Task SignOutWrongAuthTypeThrows()
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.LoginPath = new PathString("/login");
options.CookieName = "TestCookie";
@ -155,15 +155,15 @@ namespace Microsoft.AspNet.Authentication.Cookies
string requestUri,
bool shouldBeSecureOnly)
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.LoginPath = new PathString("/login");
options.CookieName = "TestCookie";
options.CookieSecure = cookieSecureOption;
}, SignInAsAlice);
Transaction transaction = await SendAsync(server, requestUri);
string setCookie = transaction.SetCookie;
var transaction = await SendAsync(server, requestUri);
var setCookie = transaction.SetCookie;
if (shouldBeSecureOnly)
{
@ -187,9 +187,9 @@ namespace Microsoft.AspNet.Authentication.Cookies
options.CookieHttpOnly = true;
}, SignInAsAlice, new Uri("http://example.com/base"));
Transaction transaction1 = await SendAsync(server1, "http://example.com/base/testpath");
var transaction1 = await SendAsync(server1, "http://example.com/base/testpath");
string setCookie1 = transaction1.SetCookie;
var setCookie1 = transaction1.SetCookie;
setCookie1.ShouldContain("TestCookie=");
setCookie1.ShouldContain(" path=/foo");
@ -197,16 +197,16 @@ namespace Microsoft.AspNet.Authentication.Cookies
setCookie1.ShouldContain(" secure");
setCookie1.ShouldContain(" HttpOnly");
TestServer server2 = CreateServer(options =>
var server2 = CreateServer(options =>
{
options.CookieName = "SecondCookie";
options.CookieSecure = CookieSecureOption.Never;
options.CookieHttpOnly = false;
}, SignInAsAlice, new Uri("http://example.com/base"));
Transaction transaction2 = await SendAsync(server2, "http://example.com/base/testpath");
var transaction2 = await SendAsync(server2, "http://example.com/base/testpath");
string setCookie2 = transaction2.SetCookie;
var setCookie2 = transaction2.SetCookie;
setCookie2.ShouldContain("SecondCookie=");
setCookie2.ShouldContain(" path=/base");
@ -219,14 +219,14 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieContainsIdentity()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
FindClaimValue(transaction2, ClaimTypes.Name).ShouldBe("Alice");
}
@ -235,7 +235,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieAppliesClaimsTransform()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
},
@ -253,9 +253,9 @@ namespace Microsoft.AspNet.Authentication.Cookies
return p;
}));
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
FindClaimValue(transaction2, ClaimTypes.Name).ShouldBe("Alice");
FindClaimValue(transaction2, "xform").ShouldBe("yup");
@ -266,24 +266,24 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieStopsWorkingAfterExpiration()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
options.SlidingExpiration = false;
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(7));
Transaction transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(7));
Transaction transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
transaction2.SetCookie.ShouldBe(null);
FindClaimValue(transaction2, ClaimTypes.Name).ShouldBe("Alice");
@ -297,7 +297,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieExpirationCanBeOverridenInSignin()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
@ -311,17 +311,17 @@ namespace Microsoft.AspNet.Authentication.Cookies
return Task.FromResult<object>(null);
});
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(3));
Transaction transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(3));
Transaction transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
transaction2.SetCookie.ShouldBe(null);
FindClaimValue(transaction2, ClaimTypes.Name).ShouldBe("Alice");
@ -335,7 +335,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieExpirationCanBeOverridenInEvent()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
@ -349,17 +349,17 @@ namespace Microsoft.AspNet.Authentication.Cookies
};
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(3));
Transaction transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(3));
Transaction transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
transaction2.SetCookie.ShouldBe(null);
FindClaimValue(transaction2, ClaimTypes.Name).ShouldBe("Alice");
@ -373,25 +373,25 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieIsRenewedWithSlidingExpiration()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
options.SlidingExpiration = true;
}, SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(4));
Transaction transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction3 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(4));
// transaction4 should arrive with a new SetCookie value
Transaction transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
var transaction4 = await SendAsync(server, "http://example.com/me/Cookies", transaction1.CookieNameValue);
clock.Add(TimeSpan.FromMinutes(4));
@ -410,13 +410,13 @@ namespace Microsoft.AspNet.Authentication.Cookies
[Fact]
public async Task AjaxRedirectsAsExtraHeaderOnTwoHundred()
{
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.LoginPath = new PathString("/login");
options.AutomaticAuthentication = true;
});
Transaction transaction = await SendAsync(server, "http://example.com/protected", ajaxRequest: true);
var transaction = await SendAsync(server, "http://example.com/protected", ajaxRequest: true);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.OK);
var responded = transaction.Response.Headers.GetValues("X-Responded-JSON");
@ -429,9 +429,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieUsesPathBaseByDefault()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
{
},
var server = CreateServer(options => { },
context =>
{
Assert.Equal(new PathString("/base"), context.Request.PathBase);
@ -441,7 +439,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
},
new Uri("http://example.com/base"));
Transaction transaction1 = await SendAsync(server, "http://example.com/base/testpath");
var transaction1 = await SendAsync(server, "http://example.com/base/testpath");
Assert.True(transaction1.SetCookie.Contains("path=/base"));
}
@ -449,15 +447,15 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieTurns401To403IfAuthenticated()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
},
SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/unauthorized", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/unauthorized", transaction1.CookieNameValue);
transaction2.Response.StatusCode.ShouldBe(HttpStatusCode.Forbidden);
}
@ -466,20 +464,20 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieTurns401ToAccessDeniedWhenSetAndIfAuthenticated()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
options.AccessDeniedPath = new PathString("/accessdenied");
},
SignInAsAlice);
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/unauthorized", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/unauthorized", transaction1.CookieNameValue);
transaction2.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
Uri location = transaction2.Response.Headers.Location;
var location = transaction2.Response.Headers.Location;
location.LocalPath.ShouldBe("/accessdenied");
}
@ -487,21 +485,21 @@ namespace Microsoft.AspNet.Authentication.Cookies
public async Task CookieDoesNothingTo401IfNotAuthenticated()
{
var clock = new TestClock();
TestServer server = CreateServer(options =>
var server = CreateServer(options =>
{
options.SystemClock = clock;
});
Transaction transaction1 = await SendAsync(server, "http://example.com/testpath");
var transaction1 = await SendAsync(server, "http://example.com/testpath");
Transaction transaction2 = await SendAsync(server, "http://example.com/unauthorized", transaction1.CookieNameValue);
var transaction2 = await SendAsync(server, "http://example.com/unauthorized", transaction1.CookieNameValue);
transaction2.Response.StatusCode.ShouldBe(HttpStatusCode.Unauthorized);
}
private static string FindClaimValue(Transaction transaction, string claimType)
{
XElement claim = transaction.ResponseElement.Elements("claim").SingleOrDefault(elt => elt.Attribute("type").Value == claimType);
var claim = transaction.ResponseElement.Elements("claim").SingleOrDefault(elt => elt.Attribute("type").Value == claimType);
if (claim == null)
{
return null;
@ -514,9 +512,9 @@ namespace Microsoft.AspNet.Authentication.Cookies
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Add("Cookie", cookie);
HttpResponseMessage response2 = await server.CreateClient().SendAsync(request);
string text = await response2.Content.ReadAsStringAsync();
XElement me = XElement.Parse(text);
var response2 = await server.CreateClient().SendAsync(request);
var text = await response2.Content.ReadAsStringAsync();
var me = XElement.Parse(text);
return me;
}
@ -525,6 +523,7 @@ namespace Microsoft.AspNet.Authentication.Cookies
var server = TestServer.Create(app =>
{
app.UseCookieAuthentication(configureOptions);
if (claimsTransform != null)
{
app.UseClaimsTransformation();

View File

@ -2,10 +2,7 @@
// 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.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
@ -29,8 +26,7 @@ namespace Microsoft.AspNet.Authentication.Facebook
},
services =>
{
services.AddWebEncoders();
services.AddDataProtection();
services.AddAuthentication();
services.ConfigureFacebookAuthentication(options =>
{
options.AppId = "Test App Id";
@ -58,7 +54,7 @@ namespace Microsoft.AspNet.Authentication.Facebook
context.Authentication.Challenge("Facebook");
return true;
});
var transaction = await SendAsync(server, "http://example.com/challenge");
var transaction = await server.SendAsync("http://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
query.ShouldContain("custom=test");
@ -75,8 +71,7 @@ namespace Microsoft.AspNet.Authentication.Facebook
},
services =>
{
services.AddWebEncoders();
services.AddDataProtection();
services.AddAuthentication();
services.ConfigureFacebookAuthentication(options =>
{
options.AppId = "Test App Id";
@ -96,7 +91,7 @@ namespace Microsoft.AspNet.Authentication.Facebook
context.Authentication.Challenge("Facebook");
return true;
});
var transaction = await SendAsync(server, "http://example.com/challenge");
var transaction = await server.SendAsync("http://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var location = transaction.Response.Headers.Location.AbsoluteUri;
location.ShouldContain("https://www.facebook.com/v2.2/dialog/oauth");
@ -125,34 +120,5 @@ namespace Microsoft.AspNet.Authentication.Facebook
},
configureServices);
}
private static async Task<Transaction> SendAsync(TestServer server, string uri, string cookieHeader = null)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
if (!string.IsNullOrEmpty(cookieHeader))
{
request.Headers.Add("Cookie", cookieHeader);
}
var transaction = new Transaction
{
Request = request,
Response = await server.CreateClient().SendAsync(request),
};
if (transaction.Response.Headers.Contains("Set-Cookie"))
{
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
}
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
return transaction;
}
private class Transaction
{
public HttpRequestMessage Request { get; set; }
public HttpResponseMessage Response { get; set; }
public IList<string> SetCookie { get; set; }
public string ResponseText { get; set; }
}
}
}

View File

@ -2,16 +2,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.AspNet.Authentication.DataHandler;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.DataProtection;
@ -28,8 +24,6 @@ namespace Microsoft.AspNet.Authentication.Google
{
public class GoogleMiddlewareTests
{
private const string CookieAuthenticationScheme = "Cookie";
[Fact]
public async Task ChallengeWillTriggerRedirection()
{
@ -38,7 +32,7 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
});
var transaction = await SendAsync(server, "https://example.com/challenge");
var transaction = await server.SendAsync("https://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var location = transaction.Response.Headers.Location.ToString();
location.ShouldContain("https://accounts.google.com/o/oauth2/auth?response_type=code");
@ -61,7 +55,7 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientSecret = "Test Secret";
options.AutomaticAuthentication = true;
});
var transaction = await SendAsync(server, "https://example.com/401");
var transaction = await server.SendAsync("https://example.com/401");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var location = transaction.Response.Headers.Location.ToString();
location.ShouldContain("https://accounts.google.com/o/oauth2/auth?response_type=code");
@ -79,7 +73,7 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
});
var transaction = await SendAsync(server, "https://example.com/challenge");
var transaction = await server.SendAsync("https://example.com/challenge");
Console.WriteLine(transaction.SetCookie);
transaction.SetCookie.Single().ShouldContain(".AspNet.Correlation.Google=");
}
@ -93,7 +87,7 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientSecret = "Test Secret";
options.AutomaticAuthentication = true;
});
var transaction = await SendAsync(server, "https://example.com/401");
var transaction = await server.SendAsync("https://example.com/401");
Console.WriteLine(transaction.SetCookie);
transaction.SetCookie.Single().ShouldContain(".AspNet.Correlation.Google=");
}
@ -106,7 +100,7 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
});
var transaction = await SendAsync(server, "https://example.com/challenge");
var transaction = await server.SendAsync("https://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
query.ShouldContain("&scope=" + UrlEncoder.Default.UrlEncode("openid profile email"));
@ -121,7 +115,7 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientSecret = "Test Secret";
options.AutomaticAuthentication = true;
});
var transaction = await SendAsync(server, "https://example.com/401");
var transaction = await server.SendAsync("https://example.com/401");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
query.ShouldContain("&scope=" + UrlEncoder.Default.UrlEncode("openid profile email"));
@ -155,7 +149,7 @@ namespace Microsoft.AspNet.Authentication.Google
return Task.FromResult<object>(null);
});
var transaction = await SendAsync(server, "https://example.com/challenge2");
var transaction = await server.SendAsync("https://example.com/challenge2");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
query.ShouldContain("scope=" + UrlEncoder.Default.UrlEncode("https://www.googleapis.com/auth/plus.login"));
@ -179,7 +173,7 @@ namespace Microsoft.AspNet.Authentication.Google
}
};
});
var transaction = await SendAsync(server, "https://example.com/challenge");
var transaction = await server.SendAsync("https://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
query.ShouldContain("custom=test");
@ -222,14 +216,16 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
});
var transaction = await SendAsync(server, "https://example.com/signin-google?code=TestCode");
var transaction = await server.SendAsync("https://example.com/signin-google?code=TestCode");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
}
[Fact]
public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState()
[Theory]
[InlineData(null)]
[InlineData("CustomIssuer")]
public async Task ReplyPathWillAuthenticateValidAuthorizeCodeAndState(string claimsIssuer)
{
var stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("GoogleTest"));
var server = CreateServer(options =>
@ -237,6 +233,7 @@ namespace Microsoft.AspNet.Authentication.Google
options.ClientId = "Test Id";
options.ClientSecret = "Test Secret";
options.StateDataFormat = stateFormat;
options.ClaimsIssuer = claimsIssuer;
options.BackchannelHttpHandler = new TestHttpMessageHandler
{
Sender = req =>
@ -283,23 +280,24 @@ namespace Microsoft.AspNet.Authentication.Google
properties.Items.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
var transaction = await server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state),
correlationKey + "=" + correlationValue);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
transaction.Response.Headers.Location.ToString().ShouldBe("/me");
transaction.SetCookie.Count.ShouldBe(2);
transaction.SetCookie[0].ShouldContain(correlationKey);
transaction.SetCookie[1].ShouldContain(".AspNet.Cookie");
transaction.SetCookie[1].ShouldContain(".AspNet." + TestExtensions.CookieAuthenticationScheme);
var authCookie = transaction.AuthenticationCookieValue;
transaction = await SendAsync(server, "https://example.com/me", authCookie);
transaction = await server.SendAsync("https://example.com/me", authCookie);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.OK);
transaction.FindClaimValue(ClaimTypes.Name).ShouldBe("Test Name");
transaction.FindClaimValue(ClaimTypes.NameIdentifier).ShouldBe("Test User ID");
transaction.FindClaimValue(ClaimTypes.GivenName).ShouldBe("Test Given Name");
transaction.FindClaimValue(ClaimTypes.Surname).ShouldBe("Test Family Name");
transaction.FindClaimValue(ClaimTypes.Email).ShouldBe("Test email");
var expectedIssuer = claimsIssuer ?? GoogleAuthenticationDefaults.AuthenticationScheme;
transaction.FindClaimValue(ClaimTypes.Name, expectedIssuer).ShouldBe("Test Name");
transaction.FindClaimValue(ClaimTypes.NameIdentifier, expectedIssuer).ShouldBe("Test User ID");
transaction.FindClaimValue(ClaimTypes.GivenName, expectedIssuer).ShouldBe("Test Given Name");
transaction.FindClaimValue(ClaimTypes.Surname, expectedIssuer).ShouldBe("Test Family Name");
transaction.FindClaimValue(ClaimTypes.Email, expectedIssuer).ShouldBe("Test email");
// Ensure claims transformation
transaction.FindClaimValue("xform").ShouldBe("yup");
@ -328,7 +326,7 @@ namespace Microsoft.AspNet.Authentication.Google
properties.Items.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
var transaction = await server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state),
correlationKey + "=" + correlationValue);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
@ -358,7 +356,7 @@ namespace Microsoft.AspNet.Authentication.Google
properties.Items.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
var transaction = await server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state),
correlationKey + "=" + correlationValue);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
@ -419,7 +417,7 @@ namespace Microsoft.AspNet.Authentication.Google
OnAuthenticated = context =>
{
var refreshToken = context.RefreshToken;
context.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken) }, "Google"));
context.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken, ClaimValueTypes.String, "Google") }, "Google"));
return Task.FromResult<object>(null);
}
};
@ -430,17 +428,17 @@ namespace Microsoft.AspNet.Authentication.Google
properties.Items.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
var transaction = await server.SendAsync(
"https://example.com/signin-google?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state),
correlationKey + "=" + correlationValue);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
transaction.Response.Headers.Location.ToString().ShouldBe("/me");
transaction.SetCookie.Count.ShouldBe(2);
transaction.SetCookie[0].ShouldContain(correlationKey);
transaction.SetCookie[1].ShouldContain(".AspNet.Cookie");
transaction.SetCookie[1].ShouldContain(".AspNet." + TestExtensions.CookieAuthenticationScheme);
var authCookie = transaction.AuthenticationCookieValue;
transaction = await SendAsync(server, "https://example.com/me", authCookie);
transaction = await server.SendAsync("https://example.com/me", authCookie);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.OK);
transaction.FindClaimValue("RefreshToken").ShouldBe("Test Refresh Token");
}
@ -453,40 +451,13 @@ namespace Microsoft.AspNet.Authentication.Google
return res;
}
private static async Task<Transaction> SendAsync(TestServer server, string uri, string cookieHeader = null)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
if (!string.IsNullOrEmpty(cookieHeader))
{
request.Headers.Add("Cookie", cookieHeader);
}
var transaction = new Transaction
{
Request = request,
Response = await server.CreateClient().SendAsync(request),
};
if (transaction.Response.Headers.Contains("Set-Cookie"))
{
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
}
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
if (transaction.Response.Content != null &&
transaction.Response.Content.Headers.ContentType != null &&
transaction.Response.Content.Headers.ContentType.MediaType == "text/xml")
{
transaction.ResponseElement = XElement.Parse(transaction.ResponseText);
}
return transaction;
}
private static TestServer CreateServer(Action<GoogleAuthenticationOptions> configureOptions, Func<HttpContext, Task> testpath = null)
{
return TestServer.Create(app =>
{
app.UseCookieAuthentication(options =>
{
options.AuthenticationScheme = CookieAuthenticationScheme;
options.AuthenticationScheme = TestExtensions.CookieAuthenticationScheme;
options.AutomaticAuthentication = true;
});
app.UseGoogleAuthentication(configureOptions);
@ -502,7 +473,7 @@ namespace Microsoft.AspNet.Authentication.Google
}
else if (req.Path == new PathString("/me"))
{
Describe(res, context.User);
res.Describe(context.User);
}
else if (req.Path == new PathString("/unauthorized"))
{
@ -535,7 +506,7 @@ namespace Microsoft.AspNet.Authentication.Google
services.AddAuthentication();
services.Configure<ExternalAuthenticationOptions>(options =>
{
options.SignInScheme = CookieAuthenticationScheme;
options.SignInScheme = TestExtensions.CookieAuthenticationScheme;
});
services.ConfigureClaimsTransformation(p =>
{
@ -547,79 +518,5 @@ namespace Microsoft.AspNet.Authentication.Google
});
}
private static void Describe(HttpResponse res, ClaimsPrincipal user)
{
res.StatusCode = 200;
res.ContentType = "text/xml";
var xml = new XElement("xml");
if (user != null)
{
foreach (var identity in user.Identities)
{
xml.Add(identity.Claims.Select(claim => new XElement("claim", new XAttribute("type", claim.Type), new XAttribute("value", claim.Value))));
}
}
using (var memory = new MemoryStream())
{
using (var writer = new XmlTextWriter(memory, Encoding.UTF8))
{
xml.WriteTo(writer);
}
res.Body.Write(memory.ToArray(), 0, memory.ToArray().Length);
}
}
private class TestHttpMessageHandler : HttpMessageHandler
{
public Func<HttpRequestMessage, HttpResponseMessage> Sender { get; set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (Sender != null)
{
return Task.FromResult(Sender(request));
}
return Task.FromResult<HttpResponseMessage>(null);
}
}
private class Transaction
{
public HttpRequestMessage Request { get; set; }
public HttpResponseMessage Response { get; set; }
public IList<string> SetCookie { get; set; }
public string ResponseText { get; set; }
public XElement ResponseElement { get; set; }
public string AuthenticationCookieValue
{
get
{
if (SetCookie != null && SetCookie.Count > 0)
{
var authCookie = SetCookie.SingleOrDefault(c => c.Contains(".AspNet.Cookie="));
if (authCookie != null)
{
return authCookie.Substring(0, authCookie.IndexOf(';'));
}
}
return null;
}
}
public string FindClaimValue(string claimType)
{
var claim = ResponseElement.Elements("claim").SingleOrDefault(elt => elt.Attribute("type").Value == claimType);
if (claim == null)
{
return null;
}
return claim.Attribute("value").Value;
}
}
}
}

View File

@ -1,16 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.AspNet.Authentication.DataHandler;
using Microsoft.AspNet.Authentication.MicrosoftAccount;
using Microsoft.AspNet.Builder;
@ -43,13 +38,8 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount
context.Response.Redirect(context.RedirectUri + "&custom=test");
}
};
},
context =>
{
context.Authentication.Challenge("Microsoft");
return true;
});
var transaction = await SendAsync(server, "http://example.com/challenge");
var transaction = await server.SendAsync("http://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
query.ShouldContain("custom=test");
@ -63,13 +53,8 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount
{
options.ClientId = "Test Client Id";
options.ClientSecret = "Test Client Secret";
},
context =>
{
context.Authentication.Challenge("Microsoft");
return true;
});
var transaction = await SendAsync(server, "http://example.com/challenge");
var transaction = await server.SendAsync("http://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var location = transaction.Response.Headers.Location.AbsoluteUri;
location.ShouldContain("https://login.live.com/oauth20_authorize.srf");
@ -83,7 +68,7 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount
[Fact]
public async Task AuthenticatedEventCanGetRefreshToken()
{
ISecureDataFormat<AuthenticationProperties> stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("MsftTest"));
var stateFormat = new PropertiesDataFormat(new EphemeralDataProtectionProvider().CreateProtector("MsftTest"));
var server = CreateServer(
options =>
{
@ -127,15 +112,10 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount
OnAuthenticated = context =>
{
var refreshToken = context.RefreshToken;
context.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken) }));
context.Principal.AddIdentity(new ClaimsIdentity(new Claim[] { new Claim("RefreshToken", refreshToken, ClaimValueTypes.String, "Microsoft") }, "Microsoft"));
return Task.FromResult<object>(null);
}
};
},
context =>
{
Describe(context.Response, context.User);
return true;
});
var properties = new AuthenticationProperties();
var correlationKey = ".AspNet.Correlation.Microsoft";
@ -143,34 +123,46 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount
properties.Items.Add(correlationKey, correlationValue);
properties.RedirectUri = "/me";
var state = stateFormat.Protect(properties);
var transaction = await SendAsync(server,
var transaction = await server.SendAsync(
"https://example.com/signin-microsoft?code=TestCode&state=" + UrlEncoder.Default.UrlEncode(state),
correlationKey + "=" + correlationValue);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
transaction.Response.Headers.Location.ToString().ShouldBe("/me");
transaction.SetCookie.Count.ShouldBe(2);
transaction.SetCookie[0].ShouldContain(correlationKey);
transaction.SetCookie[1].ShouldContain(".AspNet.External");
transaction.SetCookie[1].ShouldContain(".AspNet." + TestExtensions.CookieAuthenticationScheme);
var authCookie = transaction.AuthenticationCookieValue;
transaction = await SendAsync(server, "https://example.com/me", authCookie);
transaction = await server.SendAsync("https://example.com/me", authCookie);
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.OK);
transaction.FindClaimValue("RefreshToken").ShouldBe("Test Refresh Token");
}
private static TestServer CreateServer(Action<MicrosoftAccountAuthenticationOptions> configureOptions, Func<HttpContext, bool> handler)
private static TestServer CreateServer(Action<MicrosoftAccountAuthenticationOptions> configureOptions)
{
return TestServer.Create(app =>
{
app.UseCookieAuthentication(options =>
{
options.AuthenticationScheme = "External";
options.AuthenticationScheme = TestExtensions.CookieAuthenticationScheme;
options.AutomaticAuthentication = true;
});
app.UseMicrosoftAccountAuthentication(configureOptions);
app.Use(async (context, next) =>
{
if (handler == null || !handler(context))
var req = context.Request;
var res = context.Response;
if (req.Path == new PathString("/challenge"))
{
context.Authentication.Challenge("Microsoft");
res.StatusCode = 401;
}
else if (req.Path == new PathString("/me"))
{
res.Describe(context.User);
}
else
{
await next();
}
@ -181,38 +173,11 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount
services.AddAuthentication();
services.Configure<ExternalAuthenticationOptions>(options =>
{
options.SignInScheme = "External";
options.SignInScheme = TestExtensions.CookieAuthenticationScheme;
});
});
}
private static async Task<Transaction> SendAsync(TestServer server, string uri, string cookieHeader = null)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
if (!string.IsNullOrEmpty(cookieHeader))
{
request.Headers.Add("Cookie", cookieHeader);
}
var transaction = new Transaction
{
Request = request,
Response = await server.CreateClient().SendAsync(request),
};
if (transaction.Response.Headers.Contains("Set-Cookie"))
{
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
}
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
if (transaction.Response.Content != null &&
transaction.Response.Content.Headers.ContentType != null &&
transaction.Response.Content.Headers.ContentType.MediaType == "text/xml")
{
transaction.ResponseElement = XElement.Parse(transaction.ResponseText);
}
return transaction;
}
private static HttpResponseMessage ReturnJsonResponse(object content)
{
var res = new HttpResponseMessage(HttpStatusCode.OK);
@ -220,78 +185,5 @@ namespace Microsoft.AspNet.Authentication.Tests.MicrosoftAccount
res.Content = new StringContent(text, Encoding.UTF8, "application/json");
return res;
}
private static void Describe(HttpResponse res, ClaimsPrincipal principal)
{
res.StatusCode = 200;
res.ContentType = "text/xml";
var xml = new XElement("xml");
if (principal != null)
{
foreach (var identity in principal.Identities)
{
xml.Add(identity.Claims.Select(claim => new XElement("claim", new XAttribute("type", claim.Type), new XAttribute("value", claim.Value))));
}
}
using (var memory = new MemoryStream())
{
using (var writer = new XmlTextWriter(memory, Encoding.UTF8))
{
xml.WriteTo(writer);
}
res.Body.Write(memory.ToArray(), 0, memory.ToArray().Length);
}
}
private class TestHttpMessageHandler : HttpMessageHandler
{
public Func<HttpRequestMessage, HttpResponseMessage> Sender { get; set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (Sender != null)
{
return Task.FromResult(Sender(request));
}
return Task.FromResult<HttpResponseMessage>(null);
}
}
private class Transaction
{
public HttpRequestMessage Request { get; set; }
public HttpResponseMessage Response { get; set; }
public IList<string> SetCookie { get; set; }
public string ResponseText { get; set; }
public XElement ResponseElement { get; set; }
public string AuthenticationCookieValue
{
get
{
if (SetCookie != null && SetCookie.Count > 0)
{
var authCookie = SetCookie.SingleOrDefault(c => c.Contains(".AspNet.External="));
if (authCookie != null)
{
return authCookie.Substring(0, authCookie.IndexOf(';'));
}
}
return null;
}
}
public string FindClaimValue(string claimType)
{
XElement claim = ResponseElement.Elements("claim").SingleOrDefault(elt => elt.Attribute("type").Value == claimType);
if (claim == null)
{
return null;
}
return claim.Attribute("value").Value;
}
}
}
}

View File

@ -2,7 +2,6 @@
// 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.IdentityModel.Tokens;
using System.Net;
using System.Net.Http;
@ -36,7 +35,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
};
});
string newBearerToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImtyaU1QZG1Cdng2OHNrVDgtbVBBQjNCc2VlQSJ9.eyJhdWQiOiJodHRwczovL1R1c2hhclRlc3Qub25taWNyb3NvZnQuY29tL1RvZG9MaXN0U2VydmljZS1NYW51YWxKd3QiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9hZmJlY2UwMy1hZWFhLTRmM2YtODVlNy1jZTA4ZGQyMGNlNTAvIiwiaWF0IjoxNDE4MzMwNjE0LCJuYmYiOjE0MTgzMzA2MTQsImV4cCI6MTQxODMzNDUxNCwidmVyIjoiMS4wIiwidGlkIjoiYWZiZWNlMDMtYWVhYS00ZjNmLTg1ZTctY2UwOGRkMjBjZTUwIiwiYW1yIjpbInB3ZCJdLCJvaWQiOiI1Mzk3OTdjMi00MDE5LTQ2NTktOWRiNS03MmM0Yzc3NzhhMzMiLCJ1cG4iOiJWaWN0b3JAVHVzaGFyVGVzdC5vbm1pY3Jvc29mdC5jb20iLCJ1bmlxdWVfbmFtZSI6IlZpY3RvckBUdXNoYXJUZXN0Lm9ubWljcm9zb2Z0LmNvbSIsInN1YiI6IkQyMm9aMW9VTzEzTUFiQXZrdnFyd2REVE80WXZJdjlzMV9GNWlVOVUwYnciLCJmYW1pbHlfbmFtZSI6Ikd1cHRhIiwiZ2l2ZW5fbmFtZSI6IlZpY3RvciIsImFwcGlkIjoiNjEzYjVhZjgtZjJjMy00MWI2LWExZGMtNDE2Yzk3ODAzMGI3IiwiYXBwaWRhY3IiOiIwIiwic2NwIjoidXNlcl9pbXBlcnNvbmF0aW9uIiwiYWNyIjoiMSJ9.N_Kw1EhoVGrHbE6hOcm7ERdZ7paBQiNdObvp2c6T6n5CE8p0fZqmUd-ya_EqwElcD6SiKSiP7gj0gpNUnOJcBl_H2X8GseaeeMxBrZdsnDL8qecc6_ygHruwlPltnLTdka67s1Ow4fDSHaqhVTEk6lzGmNEcbNAyb0CxQxU6o7Fh0yHRiWoLsT8yqYk8nKzsHXfZBNby4aRo3_hXaa4i0SZLYfDGGYPdttG4vT_u54QGGd4Wzbonv2gjDlllOVGOwoJS6kfl1h8mk0qxdiIaT_ChbDWgkWvTB7bTvBE-EgHgV0XmAo0WtJeSxgjsG3KhhEPsONmqrSjhIUV4IVnF2w";
var newBearerToken = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImtyaU1QZG1Cdng2OHNrVDgtbVBBQjNCc2VlQSJ9.eyJhdWQiOiJodHRwczovL1R1c2hhclRlc3Qub25taWNyb3NvZnQuY29tL1RvZG9MaXN0U2VydmljZS1NYW51YWxKd3QiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9hZmJlY2UwMy1hZWFhLTRmM2YtODVlNy1jZTA4ZGQyMGNlNTAvIiwiaWF0IjoxNDE4MzMwNjE0LCJuYmYiOjE0MTgzMzA2MTQsImV4cCI6MTQxODMzNDUxNCwidmVyIjoiMS4wIiwidGlkIjoiYWZiZWNlMDMtYWVhYS00ZjNmLTg1ZTctY2UwOGRkMjBjZTUwIiwiYW1yIjpbInB3ZCJdLCJvaWQiOiI1Mzk3OTdjMi00MDE5LTQ2NTktOWRiNS03MmM0Yzc3NzhhMzMiLCJ1cG4iOiJWaWN0b3JAVHVzaGFyVGVzdC5vbm1pY3Jvc29mdC5jb20iLCJ1bmlxdWVfbmFtZSI6IlZpY3RvckBUdXNoYXJUZXN0Lm9ubWljcm9zb2Z0LmNvbSIsInN1YiI6IkQyMm9aMW9VTzEzTUFiQXZrdnFyd2REVE80WXZJdjlzMV9GNWlVOVUwYnciLCJmYW1pbHlfbmFtZSI6Ikd1cHRhIiwiZ2l2ZW5fbmFtZSI6IlZpY3RvciIsImFwcGlkIjoiNjEzYjVhZjgtZjJjMy00MWI2LWExZGMtNDE2Yzk3ODAzMGI3IiwiYXBwaWRhY3IiOiIwIiwic2NwIjoidXNlcl9pbXBlcnNvbmF0aW9uIiwiYWNyIjoiMSJ9.N_Kw1EhoVGrHbE6hOcm7ERdZ7paBQiNdObvp2c6T6n5CE8p0fZqmUd-ya_EqwElcD6SiKSiP7gj0gpNUnOJcBl_H2X8GseaeeMxBrZdsnDL8qecc6_ygHruwlPltnLTdka67s1Ow4fDSHaqhVTEk6lzGmNEcbNAyb0CxQxU6o7Fh0yHRiWoLsT8yqYk8nKzsHXfZBNby4aRo3_hXaa4i0SZLYfDGGYPdttG4vT_u54QGGd4Wzbonv2gjDlllOVGOwoJS6kfl1h8mk0qxdiIaT_ChbDWgkWvTB7bTvBE-EgHgV0XmAo0WtJeSxgjsG3KhhEPsONmqrSjhIUV4IVnF2w";
var response = await SendAsync(server, "http://example.com/oauth", newBearerToken);
response.Response.StatusCode.ShouldBe(HttpStatusCode.OK);
}
@ -339,6 +338,7 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
services => services.AddAuthentication());
}
// TODO: see if we can share the TestExtensions SendAsync method (only diff is auth header)
private static async Task<Transaction> SendAsync(TestServer server, string uri, string authorizationHeader = null)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
@ -364,14 +364,5 @@ namespace Microsoft.AspNet.Authentication.OAuthBearer
return transaction;
}
private class Transaction
{
public HttpRequestMessage Request { get; set; }
public HttpResponseMessage Response { get; set; }
public IList<string> SetCookie { get; set; }
public string ResponseText { get; set; }
public XElement ResponseElement { get; set; }
}
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.IdentityModel.Protocols;
using System;
namespace Microsoft.AspNet.Authentication.Tests.OpenIdConnect

View File

@ -1,12 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Authentication;
using Shouldly;
using Xunit;
@ -17,7 +15,7 @@ namespace Microsoft.AspNet.Authentication
[Fact]
public void AddingToAnonymousIdentityDoesNotKeepAnonymousIdentity()
{
HttpContext context = new DefaultHttpContext();
var context = new DefaultHttpContext();
context.User.ShouldNotBe(null);
context.User.Identity.IsAuthenticated.ShouldBe(false);
@ -36,7 +34,7 @@ namespace Microsoft.AspNet.Authentication
[Fact]
public void AddingExistingIdentityChangesDefaultButPreservesPrior()
{
HttpContext context = new DefaultHttpContext();
var context = new DefaultHttpContext();
context.User = new GenericPrincipal(new GenericIdentity("Test1", "Alpha"), null);
context.User.Identity.AuthenticationType.ShouldBe("Alpha");

View File

@ -0,0 +1,73 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.TestHost;
namespace Microsoft.AspNet.Authentication
{
public static class TestExtensions
{
public const string CookieAuthenticationScheme = "External";
public static async Task<Transaction> SendAsync(this TestServer server, string uri, string cookieHeader = null)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
if (!string.IsNullOrEmpty(cookieHeader))
{
request.Headers.Add("Cookie", cookieHeader);
}
var transaction = new Transaction
{
Request = request,
Response = await server.CreateClient().SendAsync(request),
};
if (transaction.Response.Headers.Contains("Set-Cookie"))
{
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
}
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
if (transaction.Response.Content != null &&
transaction.Response.Content.Headers.ContentType != null &&
transaction.Response.Content.Headers.ContentType.MediaType == "text/xml")
{
transaction.ResponseElement = XElement.Parse(transaction.ResponseText);
}
return transaction;
}
public static void Describe(this HttpResponse res, ClaimsPrincipal principal)
{
res.StatusCode = 200;
res.ContentType = "text/xml";
var xml = new XElement("xml");
if (principal != null)
{
foreach (var identity in principal.Identities)
{
xml.Add(identity.Claims.Select(claim =>
new XElement("claim", new XAttribute("type", claim.Type),
new XAttribute("value", claim.Value),
new XAttribute("issuer", claim.Issuer))));
}
}
using (var memory = new MemoryStream())
{
using (var writer = new XmlTextWriter(memory, Encoding.UTF8))
{
xml.WriteTo(writer);
}
res.Body.Write(memory.ToArray(), 0, memory.ToArray().Length);
}
}
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Authentication
{
public class TestHttpMessageHandler : HttpMessageHandler
{
public Func<HttpRequestMessage, HttpResponseMessage> Sender { get; set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (Sender != null)
{
return Task.FromResult(Sender(request));
}
return Task.FromResult<HttpResponseMessage>(null);
}
}
}

View File

@ -0,0 +1,50 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Xml.Linq;
namespace Microsoft.AspNet.Authentication
{
public class Transaction
{
public HttpRequestMessage Request { get; set; }
public HttpResponseMessage Response { get; set; }
public IList<string> SetCookie { get; set; }
public string ResponseText { get; set; }
public XElement ResponseElement { get; set; }
public string AuthenticationCookieValue
{
get
{
if (SetCookie != null && SetCookie.Count > 0)
{
var authCookie = SetCookie.SingleOrDefault(c => c.Contains(".AspNet." + TestExtensions.CookieAuthenticationScheme + "="));
if (authCookie != null)
{
return authCookie.Substring(0, authCookie.IndexOf(';'));
}
}
return null;
}
}
public string FindClaimValue(string claimType, string issuer = null)
{
var claim = ResponseElement.Elements("claim")
.SingleOrDefault(elt => elt.Attribute("type").Value == claimType &&
(issuer == null || elt.Attribute("issuer").Value == issuer));
if (claim == null)
{
return null;
}
return claim.Attribute("value").Value;
}
}
}

View File

@ -1,8 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
@ -57,7 +55,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
context.Authentication.Challenge("Twitter");
return true;
});
var transaction = await SendAsync(server, "http://example.com/challenge");
var transaction = await server.SendAsync("http://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var query = transaction.Response.Headers.Location.Query;
query.ShouldContain("custom=test");
@ -95,7 +93,7 @@ namespace Microsoft.AspNet.Authentication.Twitter
context.Authentication.Challenge("Twitter");
return true;
});
var transaction = await SendAsync(server, "http://example.com/challenge");
var transaction = await server.SendAsync("http://example.com/challenge");
transaction.Response.StatusCode.ShouldBe(HttpStatusCode.Redirect);
var location = transaction.Response.Headers.Location.AbsoluteUri;
location.ShouldContain("https://twitter.com/oauth/authenticate?oauth_token=");
@ -130,49 +128,5 @@ namespace Microsoft.AspNet.Authentication.Twitter
});
});
}
private static async Task<Transaction> SendAsync(TestServer server, string uri, string cookieHeader = null)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
if (!string.IsNullOrEmpty(cookieHeader))
{
request.Headers.Add("Cookie", cookieHeader);
}
var transaction = new Transaction
{
Request = request,
Response = await server.CreateClient().SendAsync(request),
};
if (transaction.Response.Headers.Contains("Set-Cookie"))
{
transaction.SetCookie = transaction.Response.Headers.GetValues("Set-Cookie").ToList();
}
transaction.ResponseText = await transaction.Response.Content.ReadAsStringAsync();
return transaction;
}
private class TestHttpMessageHandler : HttpMessageHandler
{
public Func<HttpRequestMessage, HttpResponseMessage> Sender { get; set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (Sender != null)
{
return Task.FromResult(Sender(request));
}
return Task.FromResult<HttpResponseMessage>(null);
}
}
private class Transaction
{
public HttpRequestMessage Request { get; set; }
public HttpResponseMessage Response { get; set; }
public IList<string> SetCookie { get; set; }
public string ResponseText { get; set; }
}
}
}