Replace JObject with JsonDocument in Authentication (#7105)
This commit is contained in:
parent
d630a20d1a
commit
67037a0039
|
|
@ -21,7 +21,7 @@ namespace MusicStore.Mocks.Facebook
|
|||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.NameIdentifier)?.Value == "Id", "");
|
||||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst("urn:facebook:link")?.Value == "https://www.facebook.com/myLink", "");
|
||||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.Name)?.Value == "AspnetvnextTest AspnetvnextTest", "");
|
||||
Helpers.ThrowIfConditionFailed(() => context.User.SelectToken("id").ToString() == context.Identity.FindFirst(ClaimTypes.NameIdentifier)?.Value, "");
|
||||
Helpers.ThrowIfConditionFailed(() => context.User.GetString("id") == context.Identity.FindFirst(ClaimTypes.NameIdentifier)?.Value, "");
|
||||
Helpers.ThrowIfConditionFailed(() => context.ExpiresIn.Value == TimeSpan.FromSeconds(100), "");
|
||||
Helpers.ThrowIfConditionFailed(() => context.AccessToken == "ValidAccessToken", "");
|
||||
context.Principal.Identities.First().AddClaim(new Claim("ManageStore", "false"));
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ namespace MusicStore.Mocks.Google
|
|||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.Surname)?.Value == "AspnetvnextTest", "FamilyName is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.Name)?.Value == "AspnetvnextTest AspnetvnextTest", "Name is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.ExpiresIn.Value == TimeSpan.FromSeconds(1200), "ExpiresIn is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.User != null, "User object is not valid");
|
||||
context.Principal.Identities.First().AddClaim(new Claim("ManageStore", "false"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@ namespace MusicStore.Mocks.MicrosoftAccount
|
|||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.NameIdentifier)?.Value == "fccf9a24999f4f4f", "Id is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.Name)?.Value == "AspnetvnextTest AspnetvnextTest", "Name is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.ExpiresIn.Value == TimeSpan.FromSeconds(3600), "ExpiresIn is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.User != null, "User object is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.NameIdentifier)?.Value == context.User.SelectToken("id").ToString(), "User id is not valid");
|
||||
Helpers.ThrowIfConditionFailed(() => context.Identity.FindFirst(ClaimTypes.NameIdentifier)?.Value == context.User.GetString("id"), "User id is not valid");
|
||||
context.Principal.Identities.First().AddClaim(new Claim("ManageStore", "false"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
#launchSettings.json files are required for the auth samples. The ports must not change.
|
||||
!launchSettings.json
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:1780/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"CookieSample": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:1782/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:1771/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"CookieSessionSample": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:1776/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// 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.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
public static class JsonDocumentAuthExtensions
|
||||
{
|
||||
public static string GetString(this JsonElement element, string key) =>
|
||||
element.TryGetProperty(key, out var property)
|
||||
? property.ToString() : null;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,12 +8,12 @@ using System.Security.Claims;
|
|||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Facebook
|
||||
{
|
||||
|
|
@ -41,15 +41,13 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
|
|||
throw new HttpRequestException($"An error occurred when retrieving Facebook user information ({response.StatusCode}). Please check if the authentication information is correct and the corresponding Facebook Graph API is enabled.");
|
||||
}
|
||||
|
||||
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
|
||||
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
|
||||
context.RunClaimActions();
|
||||
|
||||
await Events.CreatingTicket(context);
|
||||
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
|
||||
using (var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()))
|
||||
{
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
|
||||
context.RunClaimActions();
|
||||
await Events.CreatingTicket(context);
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private string GenerateAppSecretProof(string accessToken)
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ using System.Net.Http;
|
|||
using System.Net.Http.Headers;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Google
|
||||
{
|
||||
|
|
@ -37,13 +37,13 @@ namespace Microsoft.AspNetCore.Authentication.Google
|
|||
throw new HttpRequestException($"An error occurred when retrieving Google user information ({response.StatusCode}). Please check if the authentication information is correct and the corresponding Google+ API is enabled.");
|
||||
}
|
||||
|
||||
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
|
||||
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
|
||||
context.RunClaimActions();
|
||||
|
||||
await Events.CreatingTicket(context);
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
using (var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()))
|
||||
{
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
|
||||
context.RunClaimActions();
|
||||
await Events.CreatingTicket(context);
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Abstract this properties override pattern into the base class?
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "https://localhost:44318/",
|
||||
"sslPort": 44318
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"SocialSample": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:44318/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,11 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Pipelines;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
@ -10,7 +14,6 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace JwtBearerSample
|
||||
{
|
||||
|
|
@ -93,19 +96,37 @@ namespace JwtBearerSample
|
|||
{
|
||||
var reader = new StreamReader(context.Request.Body);
|
||||
var body = await reader.ReadToEndAsync();
|
||||
var obj = JObject.Parse(body);
|
||||
var todo = new Todo() { Description = obj["Description"].Value<string>(), Owner = context.User.Identity.Name };
|
||||
Todos.Add(todo);
|
||||
using (var json = JsonDocument.Parse(body))
|
||||
{
|
||||
var obj = json.RootElement;
|
||||
var todo = new Todo() { Description = obj.GetProperty("Description").GetString(), Owner = context.User.Identity.Name };
|
||||
Todos.Add(todo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.ContentType = "application/json";
|
||||
response.Headers[HeaderNames.CacheControl] = "no-cache";
|
||||
var json = JToken.FromObject(Todos);
|
||||
await response.WriteAsync(json.ToString());
|
||||
Serialize(Todos, response.BodyPipe);
|
||||
await response.BodyPipe.FlushAsync();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void Serialize(IList<Todo> todos, IBufferWriter<byte> output)
|
||||
{
|
||||
var writer = new Utf8JsonWriter(output);
|
||||
writer.WriteStartArray();
|
||||
foreach (var todo in todos)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
writer.WriteString("Description", todo.Description);
|
||||
writer.WriteString("Owner", todo.Owner);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ using System.Net.Http;
|
|||
using System.Net.Http.Headers;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
|
||||
{
|
||||
|
|
@ -30,13 +30,13 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
|
|||
throw new HttpRequestException($"An error occurred when retrieving Microsoft user information ({response.StatusCode}). Please check if the authentication information is correct and the corresponding Microsoft Account API is enabled.");
|
||||
}
|
||||
|
||||
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
|
||||
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload);
|
||||
context.RunClaimActions();
|
||||
|
||||
await Events.CreatingTicket(context);
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
using (var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()))
|
||||
{
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
|
||||
context.RunClaimActions();
|
||||
await Events.CreatingTicket(context);
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
|
||||
{
|
||||
|
|
@ -29,7 +27,7 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
|
|||
ClaimActions.MapJsonKey(ClaimTypes.Name, "displayName");
|
||||
ClaimActions.MapJsonKey(ClaimTypes.GivenName, "givenName");
|
||||
ClaimActions.MapJsonKey(ClaimTypes.Surname, "surname");
|
||||
ClaimActions.MapCustomJson(ClaimTypes.Email, user => user.Value<string>("mail") ?? user.Value<string>("userPrincipalName"));
|
||||
ClaimActions.MapCustomJson(ClaimTypes.Email, user => user.GetString("mail") ?? user.GetString("userPrincipalName"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Security.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
||||
{
|
||||
|
|
@ -37,6 +37,6 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
/// <param name="userData">The source data to examine. This value may be null.</param>
|
||||
/// <param name="identity">The identity to add Claims to.</param>
|
||||
/// <param name="issuer">The value to use for Claim.Issuer when creating a Claim.</param>
|
||||
public abstract void Run(JObject userData, ClaimsIdentity identity, string issuer);
|
||||
public abstract void Run(JsonElement userData, ClaimsIdentity identity, string issuer);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
|
|
@ -69,7 +69,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <param name="collection"></param>
|
||||
/// <param name="claimType">The value to use for Claim.Type when creating a Claim.</param>
|
||||
/// <param name="resolver">The Func that will be called to select value from the given json user data.</param>
|
||||
public static void MapCustomJson(this ClaimActionCollection collection, string claimType, Func<JObject, string> resolver)
|
||||
public static void MapCustomJson(this ClaimActionCollection collection, string claimType, Func<JsonElement, string> resolver)
|
||||
{
|
||||
collection.MapCustomJson(claimType, ClaimValueTypes.String, resolver);
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
/// <param name="claimType">The value to use for Claim.Type when creating a Claim.</param>
|
||||
/// <param name="valueType">The value to use for Claim.ValueType when creating a Claim.</param>
|
||||
/// <param name="resolver">The Func that will be called to select value from the given json user data.</param>
|
||||
public static void MapCustomJson(this ClaimActionCollection collection, string claimType, string valueType, Func<JObject, string> resolver)
|
||||
public static void MapCustomJson(this ClaimActionCollection collection, string claimType, string valueType, Func<JsonElement, string> resolver)
|
||||
{
|
||||
collection.Add(new CustomJsonClaimAction(claimType, valueType, resolver));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Security.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
||||
{
|
||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
/// <param name="claimType">The value to use for Claim.Type when creating a Claim.</param>
|
||||
/// <param name="valueType">The value to use for Claim.ValueType when creating a Claim.</param>
|
||||
/// <param name="resolver">The Func that will be called to select value from the given json user data.</param>
|
||||
public CustomJsonClaimAction(string claimType, string valueType, Func<JObject, string> resolver)
|
||||
public CustomJsonClaimAction(string claimType, string valueType, Func<JsonElement, string> resolver)
|
||||
: base(claimType, valueType)
|
||||
{
|
||||
Resolver = resolver;
|
||||
|
|
@ -27,15 +27,11 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
/// <summary>
|
||||
/// The Func that will be called to select value from the given json user data.
|
||||
/// </summary>
|
||||
public Func<JObject, string> Resolver { get; }
|
||||
public Func<JsonElement, string> Resolver { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
|
||||
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
|
||||
{
|
||||
if (userData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var value = Resolver(userData);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Linq;
|
||||
using System.Security.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
||||
{
|
||||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
|
||||
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
|
||||
{
|
||||
foreach (var claim in identity.FindAll(ClaimType).ToList())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ using System;
|
|||
using System.Globalization;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
|
|
@ -15,27 +15,6 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
/// </summary>
|
||||
public class OAuthCreatingTicketContext : ResultContext<OAuthOptions>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="OAuthCreatingTicketContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="principal">The <see cref="ClaimsPrincipal"/>.</param>
|
||||
/// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
|
||||
/// <param name="context">The HTTP environment.</param>
|
||||
/// <param name="scheme">The authentication scheme.</param>
|
||||
/// <param name="options">The options used by the authentication middleware.</param>
|
||||
/// <param name="backchannel">The HTTP client used by the authentication middleware</param>
|
||||
/// <param name="tokens">The tokens returned from the token endpoint.</param>
|
||||
public OAuthCreatingTicketContext(
|
||||
ClaimsPrincipal principal,
|
||||
AuthenticationProperties properties,
|
||||
HttpContext context,
|
||||
AuthenticationScheme scheme,
|
||||
OAuthOptions options,
|
||||
HttpClient backchannel,
|
||||
OAuthTokenResponse tokens)
|
||||
: this(principal, properties, context, scheme, options, backchannel, tokens, user: new JObject())
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="OAuthCreatingTicketContext"/>.
|
||||
/// </summary>
|
||||
|
|
@ -55,7 +34,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
OAuthOptions options,
|
||||
HttpClient backchannel,
|
||||
OAuthTokenResponse tokens,
|
||||
JObject user)
|
||||
JsonElement user)
|
||||
: base(context, scheme, options)
|
||||
{
|
||||
if (backchannel == null)
|
||||
|
|
@ -68,11 +47,6 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
throw new ArgumentNullException(nameof(tokens));
|
||||
}
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
TokenResponse = tokens;
|
||||
Backchannel = backchannel;
|
||||
User = user;
|
||||
|
|
@ -82,9 +56,9 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
|
||||
/// <summary>
|
||||
/// Gets the JSON-serialized user or an empty
|
||||
/// <see cref="JObject"/> if it is not available.
|
||||
/// <see cref="JsonElement"/> if it is not available.
|
||||
/// </summary>
|
||||
public JObject User { get; }
|
||||
public JsonElement User { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the token response returned by the authentication service.
|
||||
|
|
@ -136,17 +110,12 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
|
||||
public void RunClaimActions() => RunClaimActions(User);
|
||||
|
||||
public void RunClaimActions(JObject userData)
|
||||
public void RunClaimActions(JsonElement userData)
|
||||
{
|
||||
if (userData == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(userData));
|
||||
}
|
||||
|
||||
foreach (var action in Options.ClaimActions)
|
||||
{
|
||||
action.Run(userData, Identity, Options.ClaimsIssuer ?? Scheme.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Security.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
||||
{
|
||||
|
|
@ -30,20 +30,27 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
public string JsonKey { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
|
||||
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
|
||||
{
|
||||
var value = userData?[JsonKey];
|
||||
if (value is JValue)
|
||||
if (!userData.TryGetProperty(JsonKey, out var value))
|
||||
{
|
||||
AddClaim(value?.ToString(), identity, issuer);
|
||||
return;
|
||||
}
|
||||
else if (value is JArray)
|
||||
if (value.Type == JsonValueType.Array)
|
||||
{
|
||||
foreach (var v in value)
|
||||
foreach (var v in value.EnumerateArray())
|
||||
{
|
||||
AddClaim(v?.ToString(), identity, issuer);
|
||||
AddClaim(v.ToString(), identity, issuer);
|
||||
}
|
||||
}
|
||||
else if (value.Type == JsonValueType.Object || value.Type == JsonValueType.Undefined)
|
||||
{
|
||||
// Skip, because they were previously skipped
|
||||
}
|
||||
else
|
||||
{
|
||||
AddClaim(value.ToString(), identity, issuer);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddClaim(string value, ClaimsIdentity identity, string issuer)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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 Newtonsoft.Json.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
||||
{
|
||||
|
|
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
public string SubKey { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
|
||||
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
|
||||
{
|
||||
var value = GetValue(userData, JsonKey, SubKey);
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
|
|
@ -42,15 +42,12 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
}
|
||||
|
||||
// Get the given subProperty from a property.
|
||||
private static string GetValue(JObject userData, string propertyName, string subProperty)
|
||||
private static string GetValue(JsonElement userData, string propertyName, string subProperty)
|
||||
{
|
||||
if (userData != null && userData.TryGetValue(propertyName, out var value))
|
||||
if (userData.TryGetProperty(propertyName, out var value)
|
||||
&& value.Type == JsonValueType.Object && value.TryGetProperty(subProperty, out value))
|
||||
{
|
||||
var subObject = JObject.Parse(value.ToString());
|
||||
if (subObject != null && subObject.TryGetValue(subProperty, out value))
|
||||
{
|
||||
return value.ToString();
|
||||
}
|
||||
return value.ToString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Security.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
||||
{
|
||||
|
|
@ -17,24 +17,20 @@ namespace Microsoft.AspNetCore.Authentication.OAuth.Claims
|
|||
{
|
||||
}
|
||||
|
||||
public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
|
||||
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
|
||||
{
|
||||
if (userData == null)
|
||||
foreach (var pair in userData.EnumerateObject())
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var pair in userData)
|
||||
{
|
||||
var claimValue = userData.TryGetValue(pair.Key, out var value) ? value.ToString() : null;
|
||||
var claimValue = pair.Value.ToString();
|
||||
|
||||
// Avoid adding a claim if there's a duplicate name and value. This often happens in OIDC when claims are
|
||||
// retrieved both from the id_token and from the user-info endpoint.
|
||||
var duplicate = identity.FindFirst(c => string.Equals(c.Type, pair.Key, StringComparison.OrdinalIgnoreCase)
|
||||
var duplicate = identity.FindFirst(c => string.Equals(c.Type, pair.Name, StringComparison.OrdinalIgnoreCase)
|
||||
&& string.Equals(c.Value, claimValue, StringComparison.Ordinal)) != null;
|
||||
|
||||
if (!duplicate)
|
||||
{
|
||||
identity.AddClaim(new Claim(pair.Key, claimValue, ClaimValueTypes.String, issuer));
|
||||
identity.AddClaim(new Claim(pair.Name, claimValue, ClaimValueTypes.String, issuer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>ASP.NET Core middleware that enables an application to support any standard OAuth 2.0 authentication workflow.</Description>
|
||||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Authentication" />
|
||||
<Reference Include="Newtonsoft.Json" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ using System.Net.Http.Headers;
|
|||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
|
|
@ -99,62 +99,63 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
return HandleRequestResult.Fail("Code was not found.", properties);
|
||||
}
|
||||
|
||||
var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath));
|
||||
|
||||
if (tokens.Error != null)
|
||||
using (var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath)))
|
||||
{
|
||||
return HandleRequestResult.Fail(tokens.Error, properties);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(tokens.AccessToken))
|
||||
{
|
||||
return HandleRequestResult.Fail("Failed to retrieve access token.", properties);
|
||||
}
|
||||
|
||||
var identity = new ClaimsIdentity(ClaimsIssuer);
|
||||
|
||||
if (Options.SaveTokens)
|
||||
{
|
||||
var authTokens = new List<AuthenticationToken>();
|
||||
|
||||
authTokens.Add(new AuthenticationToken { Name = "access_token", Value = tokens.AccessToken });
|
||||
if (!string.IsNullOrEmpty(tokens.RefreshToken))
|
||||
if (tokens.Error != null)
|
||||
{
|
||||
authTokens.Add(new AuthenticationToken { Name = "refresh_token", Value = tokens.RefreshToken });
|
||||
return HandleRequestResult.Fail(tokens.Error, properties);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(tokens.TokenType))
|
||||
if (string.IsNullOrEmpty(tokens.AccessToken))
|
||||
{
|
||||
authTokens.Add(new AuthenticationToken { Name = "token_type", Value = tokens.TokenType });
|
||||
return HandleRequestResult.Fail("Failed to retrieve access token.", properties);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(tokens.ExpiresIn))
|
||||
var identity = new ClaimsIdentity(ClaimsIssuer);
|
||||
|
||||
if (Options.SaveTokens)
|
||||
{
|
||||
int value;
|
||||
if (int.TryParse(tokens.ExpiresIn, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
|
||||
var authTokens = new List<AuthenticationToken>();
|
||||
|
||||
authTokens.Add(new AuthenticationToken { Name = "access_token", Value = tokens.AccessToken });
|
||||
if (!string.IsNullOrEmpty(tokens.RefreshToken))
|
||||
{
|
||||
// https://www.w3.org/TR/xmlschema-2/#dateTime
|
||||
// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
|
||||
var expiresAt = Clock.UtcNow + TimeSpan.FromSeconds(value);
|
||||
authTokens.Add(new AuthenticationToken
|
||||
{
|
||||
Name = "expires_at",
|
||||
Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
|
||||
});
|
||||
authTokens.Add(new AuthenticationToken { Name = "refresh_token", Value = tokens.RefreshToken });
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(tokens.TokenType))
|
||||
{
|
||||
authTokens.Add(new AuthenticationToken { Name = "token_type", Value = tokens.TokenType });
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(tokens.ExpiresIn))
|
||||
{
|
||||
int value;
|
||||
if (int.TryParse(tokens.ExpiresIn, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
|
||||
{
|
||||
// https://www.w3.org/TR/xmlschema-2/#dateTime
|
||||
// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
|
||||
var expiresAt = Clock.UtcNow + TimeSpan.FromSeconds(value);
|
||||
authTokens.Add(new AuthenticationToken
|
||||
{
|
||||
Name = "expires_at",
|
||||
Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
properties.StoreTokens(authTokens);
|
||||
}
|
||||
|
||||
properties.StoreTokens(authTokens);
|
||||
}
|
||||
|
||||
var ticket = await CreateTicketAsync(identity, properties, tokens);
|
||||
if (ticket != null)
|
||||
{
|
||||
return HandleRequestResult.Success(ticket);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HandleRequestResult.Fail("Failed to retrieve user information from remote server.", properties);
|
||||
var ticket = await CreateTicketAsync(identity, properties, tokens);
|
||||
if (ticket != null)
|
||||
{
|
||||
return HandleRequestResult.Success(ticket);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HandleRequestResult.Fail("Failed to retrieve user information from remote server.", properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +178,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted);
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
|
||||
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
|
||||
return OAuthTokenResponse.Success(payload);
|
||||
}
|
||||
else
|
||||
|
|
@ -198,9 +199,12 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
|
||||
protected virtual async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
|
||||
{
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens);
|
||||
await Events.CreatingTicket(context);
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
using (var user = JsonDocument.Parse("{}"))
|
||||
{
|
||||
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, user.RootElement);
|
||||
await Events.CreatingTicket(context);
|
||||
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
|
||||
|
|
|
|||
|
|
@ -2,19 +2,20 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OAuth
|
||||
{
|
||||
public class OAuthTokenResponse
|
||||
public class OAuthTokenResponse : IDisposable
|
||||
{
|
||||
private OAuthTokenResponse(JObject response)
|
||||
private OAuthTokenResponse(JsonDocument response)
|
||||
{
|
||||
Response = response;
|
||||
AccessToken = response.Value<string>("access_token");
|
||||
TokenType = response.Value<string>("token_type");
|
||||
RefreshToken = response.Value<string>("refresh_token");
|
||||
ExpiresIn = response.Value<string>("expires_in");
|
||||
var root = response.RootElement;
|
||||
AccessToken = root.GetString("access_token");
|
||||
TokenType = root.GetString("token_type");
|
||||
RefreshToken = root.GetString("refresh_token");
|
||||
ExpiresIn = root.GetString("expires_in");
|
||||
}
|
||||
|
||||
private OAuthTokenResponse(Exception error)
|
||||
|
|
@ -22,7 +23,7 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
Error = error;
|
||||
}
|
||||
|
||||
public static OAuthTokenResponse Success(JObject response)
|
||||
public static OAuthTokenResponse Success(JsonDocument response)
|
||||
{
|
||||
return new OAuthTokenResponse(response);
|
||||
}
|
||||
|
|
@ -32,11 +33,16 @@ namespace Microsoft.AspNetCore.Authentication.OAuth
|
|||
return new OAuthTokenResponse(error);
|
||||
}
|
||||
|
||||
public JObject Response { get; set; }
|
||||
public void Dispose()
|
||||
{
|
||||
Response?.Dispose();
|
||||
}
|
||||
|
||||
public JsonDocument Response { get; set; }
|
||||
public string AccessToken { get; set; }
|
||||
public string TokenType { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
public string ExpiresIn { get; set; }
|
||||
public Exception Error { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "https://localhost:44318/",
|
||||
"sslPort": 44318
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"SocialSample": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:44318/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "https://localhost:44318/",
|
||||
"sslPort": 44318
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"SocialSample": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:44318/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using System.IdentityModel.Tokens.Jwt;
|
|||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
|
|
@ -16,7 +17,6 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace OpenIdConnectSample
|
||||
{
|
||||
|
|
@ -208,30 +208,31 @@ namespace OpenIdConnectSample
|
|||
var tokenResponse = await options.Backchannel.PostAsync(metadata.TokenEndpoint, content, context.RequestAborted);
|
||||
tokenResponse.EnsureSuccessStatusCode();
|
||||
|
||||
var payload = JObject.Parse(await tokenResponse.Content.ReadAsStringAsync());
|
||||
|
||||
// Persist the new acess token
|
||||
props.UpdateTokenValue("access_token", payload.Value<string>("access_token"));
|
||||
props.UpdateTokenValue("refresh_token", payload.Value<string>("refresh_token"));
|
||||
if (int.TryParse(payload.Value<string>("expires_in"), NumberStyles.Integer, CultureInfo.InvariantCulture, out var seconds))
|
||||
using (var payload = JsonDocument.Parse(await tokenResponse.Content.ReadAsStringAsync()))
|
||||
{
|
||||
var expiresAt = DateTimeOffset.UtcNow + TimeSpan.FromSeconds(seconds);
|
||||
props.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
|
||||
// Persist the new acess token
|
||||
props.UpdateTokenValue("access_token", payload.RootElement.GetString("access_token"));
|
||||
props.UpdateTokenValue("refresh_token", payload.RootElement.GetString("refresh_token"));
|
||||
if (payload.RootElement.TryGetProperty("expires_in", out var property) && property.TryGetInt32(out var seconds))
|
||||
{
|
||||
var expiresAt = DateTimeOffset.UtcNow + TimeSpan.FromSeconds(seconds);
|
||||
props.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
|
||||
}
|
||||
await context.SignInAsync(user, props);
|
||||
|
||||
await WriteHtmlAsync(response, async res =>
|
||||
{
|
||||
await res.WriteAsync($"<h1>Refreshed.</h1>");
|
||||
await res.WriteAsync("<a class=\"btn btn-default\" href=\"/refresh\">Refresh tokens</a>");
|
||||
await res.WriteAsync("<a class=\"btn btn-default\" href=\"/\">Home</a>");
|
||||
|
||||
await res.WriteAsync("<h2>Tokens:</h2>");
|
||||
await WriteTableHeader(res, new string[] { "Token Type", "Value" }, props.GetTokens().Select(token => new string[] { token.Name, token.Value }));
|
||||
|
||||
await res.WriteAsync("<h2>Payload:</h2>");
|
||||
await res.WriteAsync(HtmlEncoder.Default.Encode(payload.ToString()).Replace(",", ",<br>") + "<br>");
|
||||
});
|
||||
}
|
||||
await context.SignInAsync(user, props);
|
||||
|
||||
await WriteHtmlAsync(response, async res =>
|
||||
{
|
||||
await res.WriteAsync($"<h1>Refreshed.</h1>");
|
||||
await res.WriteAsync("<a class=\"btn btn-default\" href=\"/refresh\">Refresh tokens</a>");
|
||||
await res.WriteAsync("<a class=\"btn btn-default\" href=\"/\">Home</a>");
|
||||
|
||||
await res.WriteAsync("<h2>Tokens:</h2>");
|
||||
await WriteTableHeader(res, new string[] { "Token Type", "Value" }, props.GetTokens().Select(token => new string[] { token.Name, token.Value }));
|
||||
|
||||
await res.WriteAsync("<h2>Payload:</h2>");
|
||||
await res.WriteAsync(HtmlEncoder.Default.Encode(payload.ToString()).Replace(",", ",<br>") + "<br>");
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
||||
{
|
||||
|
|
@ -16,6 +16,6 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
|
||||
public OpenIdConnectMessage ProtocolMessage { get; set; }
|
||||
|
||||
public JObject User { get; set; }
|
||||
public JsonDocument User { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using System.Security.Claims;
|
|||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
@ -20,7 +21,6 @@ using Microsoft.Extensions.Primitives;
|
|||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
||||
{
|
||||
|
|
@ -712,10 +712,13 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
}
|
||||
else
|
||||
{
|
||||
var identity = (ClaimsIdentity)user.Identity;
|
||||
foreach (var action in Options.ClaimActions)
|
||||
using (var payload = JsonDocument.Parse("{}"))
|
||||
{
|
||||
action.Run(null, identity, ClaimsIssuer);
|
||||
var identity = (ClaimsIdentity)user.Identity;
|
||||
foreach (var action in Options.ClaimActions)
|
||||
{
|
||||
action.Run(payload.RootElement, identity, ClaimsIssuer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -853,42 +856,46 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
responseMessage.EnsureSuccessStatusCode();
|
||||
var userInfoResponse = await responseMessage.Content.ReadAsStringAsync();
|
||||
|
||||
JObject user;
|
||||
JsonDocument user;
|
||||
var contentType = responseMessage.Content.Headers.ContentType;
|
||||
if (contentType.MediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
user = JObject.Parse(userInfoResponse);
|
||||
user = JsonDocument.Parse(userInfoResponse);
|
||||
}
|
||||
else if (contentType.MediaType.Equals("application/jwt", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var userInfoEndpointJwt = new JwtSecurityToken(userInfoResponse);
|
||||
user = JObject.FromObject(userInfoEndpointJwt.Payload);
|
||||
user = JsonDocument.Parse(userInfoEndpointJwt.Payload.SerializeToJson());
|
||||
}
|
||||
else
|
||||
{
|
||||
return HandleRequestResult.Fail("Unknown response type: " + contentType.MediaType, properties);
|
||||
}
|
||||
|
||||
var userInformationReceivedContext = await RunUserInformationReceivedEventAsync(principal, properties, message, user);
|
||||
if (userInformationReceivedContext.Result != null)
|
||||
using (user)
|
||||
{
|
||||
return userInformationReceivedContext.Result;
|
||||
}
|
||||
principal = userInformationReceivedContext.Principal;
|
||||
properties = userInformationReceivedContext.Properties;
|
||||
user = userInformationReceivedContext.User;
|
||||
var userInformationReceivedContext = await RunUserInformationReceivedEventAsync(principal, properties, message, user);
|
||||
if (userInformationReceivedContext.Result != null)
|
||||
{
|
||||
return userInformationReceivedContext.Result;
|
||||
}
|
||||
principal = userInformationReceivedContext.Principal;
|
||||
properties = userInformationReceivedContext.Properties;
|
||||
using (var updatedUser = userInformationReceivedContext.User)
|
||||
{
|
||||
Options.ProtocolValidator.ValidateUserInfoResponse(new OpenIdConnectProtocolValidationContext()
|
||||
{
|
||||
UserInfoEndpointResponse = userInfoResponse,
|
||||
ValidatedIdToken = jwt,
|
||||
});
|
||||
|
||||
Options.ProtocolValidator.ValidateUserInfoResponse(new OpenIdConnectProtocolValidationContext()
|
||||
{
|
||||
UserInfoEndpointResponse = userInfoResponse,
|
||||
ValidatedIdToken = jwt,
|
||||
});
|
||||
var identity = (ClaimsIdentity)principal.Identity;
|
||||
|
||||
var identity = (ClaimsIdentity)principal.Identity;
|
||||
|
||||
foreach (var action in Options.ClaimActions)
|
||||
{
|
||||
action.Run(user, identity, ClaimsIssuer);
|
||||
foreach (var action in Options.ClaimActions)
|
||||
{
|
||||
action.Run(user.RootElement, identity, ClaimsIssuer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HandleRequestResult.Success(new AuthenticationTicket(principal, properties, Scheme.Name));
|
||||
|
|
@ -1144,7 +1151,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
|
|||
return context;
|
||||
}
|
||||
|
||||
private async Task<UserInformationReceivedContext> RunUserInformationReceivedEventAsync(ClaimsPrincipal principal, AuthenticationProperties properties, OpenIdConnectMessage message, JObject user)
|
||||
private async Task<UserInformationReceivedContext> RunUserInformationReceivedEventAsync(ClaimsPrincipal principal, AuthenticationProperties properties, OpenIdConnectMessage message, JsonDocument user)
|
||||
{
|
||||
Logger.UserInformationReceived(user.ToString());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.OpenIdConnect.Claims
|
||||
{
|
||||
|
|
@ -27,9 +27,9 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect.Claims
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
|
||||
public override void Run(JsonElement userData, ClaimsIdentity identity, string issuer)
|
||||
{
|
||||
var value = userData?.Value<string>(JsonKey);
|
||||
var value = userData.GetString(JsonKey);
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
// Not found
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
// 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.Security.Claims;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Twitter
|
||||
{
|
||||
|
|
@ -36,14 +35,14 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
string screenName,
|
||||
string accessToken,
|
||||
string accessTokenSecret,
|
||||
JObject user)
|
||||
JsonElement user)
|
||||
: base(context, scheme, options)
|
||||
{
|
||||
UserId = userId;
|
||||
ScreenName = screenName;
|
||||
AccessToken = accessToken;
|
||||
AccessTokenSecret = accessTokenSecret;
|
||||
User = user ?? new JObject();
|
||||
User = user;
|
||||
Principal = principal;
|
||||
Properties = properties;
|
||||
}
|
||||
|
|
@ -70,8 +69,8 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
|
||||
/// <summary>
|
||||
/// Gets the JSON-serialized user or an empty
|
||||
/// <see cref="JObject"/> if it is not available.
|
||||
/// <see cref="JsonElement"/> if it is not available.
|
||||
/// </summary>
|
||||
public JObject User { get; }
|
||||
public JsonElement User { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ using System.Security.Claims;
|
|||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication.Twitter
|
||||
{
|
||||
|
|
@ -99,25 +99,33 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
},
|
||||
ClaimsIssuer);
|
||||
|
||||
JObject user = null;
|
||||
JsonDocument user;
|
||||
if (Options.RetrieveUserDetails)
|
||||
{
|
||||
user = await RetrieveUserDetailsAsync(accessToken, identity);
|
||||
}
|
||||
|
||||
if (Options.SaveTokens)
|
||||
else
|
||||
{
|
||||
properties.StoreTokens(new [] {
|
||||
new AuthenticationToken { Name = "access_token", Value = accessToken.Token },
|
||||
new AuthenticationToken { Name = "access_token_secret", Value = accessToken.TokenSecret }
|
||||
});
|
||||
user = JsonDocument.Parse("{}");
|
||||
}
|
||||
|
||||
return HandleRequestResult.Success(await CreateTicketAsync(identity, properties, accessToken, user));
|
||||
using (user)
|
||||
{
|
||||
if (Options.SaveTokens)
|
||||
{
|
||||
properties.StoreTokens(new[] {
|
||||
new AuthenticationToken { Name = "access_token", Value = accessToken.Token },
|
||||
new AuthenticationToken { Name = "access_token_secret", Value = accessToken.TokenSecret }
|
||||
});
|
||||
}
|
||||
|
||||
var ticket = await CreateTicketAsync(identity, properties, accessToken, user.RootElement);
|
||||
return HandleRequestResult.Success(ticket);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task<AuthenticationTicket> CreateTicketAsync(
|
||||
ClaimsIdentity identity, AuthenticationProperties properties, AccessToken token, JObject user)
|
||||
ClaimsIdentity identity, AuthenticationProperties properties, AccessToken token, JsonElement user)
|
||||
{
|
||||
foreach (var action in Options.ClaimActions)
|
||||
{
|
||||
|
|
@ -275,7 +283,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
}
|
||||
|
||||
// https://dev.twitter.com/rest/reference/get/account/verify_credentials
|
||||
private async Task<JObject> RetrieveUserDetailsAsync(AccessToken accessToken, ClaimsIdentity identity)
|
||||
private async Task<JsonDocument> RetrieveUserDetailsAsync(AccessToken accessToken, ClaimsIdentity identity)
|
||||
{
|
||||
Logger.RetrieveUserDetails();
|
||||
|
||||
|
|
@ -288,7 +296,7 @@ namespace Microsoft.AspNetCore.Authentication.Twitter
|
|||
}
|
||||
var responseText = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var result = JObject.Parse(responseText);
|
||||
var result = JsonDocument.Parse(responseText);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "https://localhost:44318/",
|
||||
"sslPort": 44318
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"SocialSample": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:44318/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "https://localhost:44318/",
|
||||
"sslPort": 44318
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"SocialSample": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:44318/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ using System.Net.Http;
|
|||
using System.Net.Http.Headers;
|
||||
using System.Security.Claims;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
|
|
@ -21,7 +22,6 @@ using Microsoft.AspNetCore.Http.Extensions;
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace SocialSample
|
||||
{
|
||||
|
|
@ -207,9 +207,10 @@ namespace SocialSample
|
|||
var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var user = JObject.Parse(await response.Content.ReadAsStringAsync());
|
||||
|
||||
context.RunClaimActions(user);
|
||||
using (var user = JsonDocument.Parse(await response.Content.ReadAsStringAsync()))
|
||||
{
|
||||
context.RunClaimActions(user.RootElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
@ -332,24 +333,25 @@ namespace SocialSample
|
|||
var refreshResponse = await options.Backchannel.PostAsync(options.TokenEndpoint, content, context.RequestAborted);
|
||||
refreshResponse.EnsureSuccessStatusCode();
|
||||
|
||||
var payload = JObject.Parse(await refreshResponse.Content.ReadAsStringAsync());
|
||||
|
||||
// Persist the new acess token
|
||||
authProperties.UpdateTokenValue("access_token", payload.Value<string>("access_token"));
|
||||
refreshToken = payload.Value<string>("refresh_token");
|
||||
if (!string.IsNullOrEmpty(refreshToken))
|
||||
using (var payload = JsonDocument.Parse(await refreshResponse.Content.ReadAsStringAsync()))
|
||||
{
|
||||
authProperties.UpdateTokenValue("refresh_token", refreshToken);
|
||||
}
|
||||
if (int.TryParse(payload.Value<string>("expires_in"), NumberStyles.Integer, CultureInfo.InvariantCulture, out var seconds))
|
||||
{
|
||||
var expiresAt = DateTimeOffset.UtcNow + TimeSpan.FromSeconds(seconds);
|
||||
authProperties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
|
||||
}
|
||||
await context.SignInAsync(user, authProperties);
|
||||
|
||||
await PrintRefreshedTokensAsync(response, payload, authProperties);
|
||||
// Persist the new acess token
|
||||
authProperties.UpdateTokenValue("access_token", payload.RootElement.GetString("access_token"));
|
||||
refreshToken = payload.RootElement.GetString("refresh_token");
|
||||
if (!string.IsNullOrEmpty(refreshToken))
|
||||
{
|
||||
authProperties.UpdateTokenValue("refresh_token", refreshToken);
|
||||
}
|
||||
if (payload.RootElement.TryGetProperty("expires_in", out var property) && property.TryGetInt32(out var seconds))
|
||||
{
|
||||
var expiresAt = DateTimeOffset.UtcNow + TimeSpan.FromSeconds(seconds);
|
||||
authProperties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
|
||||
}
|
||||
await context.SignInAsync(user, authProperties);
|
||||
|
||||
await PrintRefreshedTokensAsync(response, payload, authProperties);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
|
||||
|
|
@ -368,18 +370,18 @@ namespace SocialSample
|
|||
}.ToQueryString();
|
||||
|
||||
var refreshResponse = await options.Backchannel.GetStringAsync(options.TokenEndpoint + query);
|
||||
var payload = JObject.Parse(refreshResponse);
|
||||
|
||||
authProperties.UpdateTokenValue("access_token", payload.Value<string>("access_token"));
|
||||
if (int.TryParse(payload.Value<string>("expires_in"), NumberStyles.Integer, CultureInfo.InvariantCulture, out var seconds))
|
||||
using (var payload = JsonDocument.Parse(refreshResponse))
|
||||
{
|
||||
var expiresAt = DateTimeOffset.UtcNow + TimeSpan.FromSeconds(seconds);
|
||||
authProperties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
|
||||
authProperties.UpdateTokenValue("access_token", payload.RootElement.GetString("access_token"));
|
||||
if (payload.RootElement.TryGetProperty("expires_in", out var property) && property.TryGetInt32(out var seconds))
|
||||
{
|
||||
var expiresAt = DateTimeOffset.UtcNow + TimeSpan.FromSeconds(seconds);
|
||||
authProperties.UpdateTokenValue("expires_at", expiresAt.ToString("o", CultureInfo.InvariantCulture));
|
||||
}
|
||||
await context.SignInAsync(user, authProperties);
|
||||
|
||||
await PrintRefreshedTokensAsync(response, payload, authProperties);
|
||||
}
|
||||
await context.SignInAsync(user, authProperties);
|
||||
|
||||
await PrintRefreshedTokensAsync(response, payload, authProperties);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -485,12 +487,12 @@ namespace SocialSample
|
|||
throw new NotImplementedException(currentAuthType);
|
||||
}
|
||||
|
||||
private async Task PrintRefreshedTokensAsync(HttpResponse response, JObject payload, AuthenticationProperties authProperties)
|
||||
private async Task PrintRefreshedTokensAsync(HttpResponse response, JsonDocument payload, AuthenticationProperties authProperties)
|
||||
{
|
||||
response.ContentType = "text/html";
|
||||
await response.WriteAsync("<html><body>");
|
||||
await response.WriteAsync("Refreshed.<br>");
|
||||
await response.WriteAsync(HtmlEncoder.Default.Encode(payload.ToString()).Replace(",", ",<br>") + "<br>");
|
||||
await response.WriteAsync(HtmlEncoder.Default.Encode(payload.RootElement.ToString()).Replace(",", ",<br>") + "<br>");
|
||||
|
||||
await response.WriteAsync("<br>Tokens:<br>");
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false">
|
||||
<environmentVariables />
|
||||
</aspNetCore>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
|
|
@ -1,14 +1,11 @@
|
|||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Testing.xunit;
|
||||
using Xunit;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Authentication
|
||||
{
|
||||
|
|
@ -17,15 +14,12 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
[Fact]
|
||||
public void CanMapSingleValueUserDataToClaim()
|
||||
{
|
||||
var userData = new JObject
|
||||
{
|
||||
["name"] = "test"
|
||||
};
|
||||
var userData = JsonDocument.Parse("{ \"name\": \"test\" }");
|
||||
|
||||
var identity = new ClaimsIdentity();
|
||||
|
||||
var action = new JsonKeyClaimAction("name", "name", "name");
|
||||
action.Run(userData, identity, "iss");
|
||||
action.Run(userData.RootElement, identity, "iss");
|
||||
|
||||
Assert.Equal("name", identity.FindFirst("name").Type);
|
||||
Assert.Equal("test", identity.FindFirst("name").Value);
|
||||
|
|
@ -34,15 +28,12 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
[Fact]
|
||||
public void CanMapArrayValueUserDataToClaims()
|
||||
{
|
||||
var userData = new JObject
|
||||
{
|
||||
["role"] = new JArray { "role1", "role2" }
|
||||
};
|
||||
var userData = JsonDocument.Parse("{ \"role\": [ \"role1\", null, \"role2\" ] }");
|
||||
|
||||
var identity = new ClaimsIdentity();
|
||||
|
||||
var action = new JsonKeyClaimAction("role", "role", "role");
|
||||
action.Run(userData, identity, "iss");
|
||||
action.Run(userData.RootElement, identity, "iss");
|
||||
|
||||
var roleClaims = identity.FindAll("role").ToList();
|
||||
Assert.Equal(2, roleClaims.Count);
|
||||
|
|
@ -55,15 +46,11 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
[Fact]
|
||||
public void MapAllSucceeds()
|
||||
{
|
||||
var userData = new JObject
|
||||
{
|
||||
["name0"] = "value0",
|
||||
["name1"] = "value1",
|
||||
};
|
||||
var userData = JsonDocument.Parse("{ \"name0\": \"value0\", \"name1\": \"value1\" }");
|
||||
|
||||
var identity = new ClaimsIdentity();
|
||||
var action = new MapAllClaimsAction();
|
||||
action.Run(userData, identity, "iss");
|
||||
action.Run(userData.RootElement, identity, "iss");
|
||||
|
||||
Assert.Equal("name0", identity.FindFirst("name0").Type);
|
||||
Assert.Equal("value0", identity.FindFirst("name0").Value);
|
||||
|
|
@ -74,17 +61,13 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
[Fact]
|
||||
public void MapAllAllowesDulicateKeysWithUniqueValues()
|
||||
{
|
||||
var userData = new JObject
|
||||
{
|
||||
["name0"] = "value0",
|
||||
["name1"] = "value1",
|
||||
};
|
||||
var userData = JsonDocument.Parse("{ \"name0\": \"value0\", \"name1\": \"value1\" }");
|
||||
|
||||
var identity = new ClaimsIdentity();
|
||||
identity.AddClaim(new Claim("name0", "value2"));
|
||||
identity.AddClaim(new Claim("name1", "value3"));
|
||||
var action = new MapAllClaimsAction();
|
||||
action.Run(userData, identity, "iss");
|
||||
action.Run(userData.RootElement, identity, "iss");
|
||||
|
||||
Assert.Equal(2, identity.FindAll("name0").Count());
|
||||
Assert.Equal(2, identity.FindAll("name1").Count());
|
||||
|
|
@ -93,17 +76,13 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
[Fact]
|
||||
public void MapAllSkipsDuplicateValues()
|
||||
{
|
||||
var userData = new JObject
|
||||
{
|
||||
["name0"] = "value0",
|
||||
["name1"] = "value1",
|
||||
};
|
||||
var userData = JsonDocument.Parse("{ \"name0\": \"value0\", \"name1\": \"value1\" }");
|
||||
|
||||
var identity = new ClaimsIdentity();
|
||||
identity.AddClaim(new Claim("name0", "value0"));
|
||||
identity.AddClaim(new Claim("name1", "value1"));
|
||||
var action = new MapAllClaimsAction();
|
||||
action.Run(userData, identity, "iss");
|
||||
action.Run(userData.RootElement, identity, "iss");
|
||||
|
||||
Assert.Single(identity.FindAll("name0"));
|
||||
Assert.Single(identity.FindAll("name1"));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
|
@ -325,10 +324,7 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
|
|||
if (req.RequestUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped) == FacebookDefaults.TokenEndpoint)
|
||||
{
|
||||
var res = new HttpResponseMessage(HttpStatusCode.OK);
|
||||
var graphResponse = JsonConvert.SerializeObject(new
|
||||
{
|
||||
access_token = "TestAuthToken"
|
||||
});
|
||||
var graphResponse = "{ \"access_token\": \"TestAuthToken\" }";
|
||||
res.Content = new StringContent(graphResponse, Encoding.UTF8);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -337,11 +333,7 @@ namespace Microsoft.AspNetCore.Authentication.Facebook
|
|||
{
|
||||
finalUserInfoEndpoint = req.RequestUri.ToString();
|
||||
var res = new HttpResponseMessage(HttpStatusCode.OK);
|
||||
var graphResponse = JsonConvert.SerializeObject(new
|
||||
{
|
||||
id = "TestProfileId",
|
||||
name = "TestName"
|
||||
});
|
||||
var graphResponse = "{ \"id\": \"TestProfileId\", \"name\": \"TestName\" }";
|
||||
res.Content = new StringContent(graphResponse, Encoding.UTF8);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using Microsoft.AspNetCore.TestHost;
|
|||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -704,7 +703,6 @@ namespace Microsoft.AspNetCore.Authentication.Google
|
|||
{
|
||||
OnCreatingTicket = context =>
|
||||
{
|
||||
Assert.NotNull(context.User);
|
||||
Assert.Equal("Test Access Token", context.AccessToken);
|
||||
Assert.Equal("Test Refresh Token", context.RefreshToken);
|
||||
Assert.Equal(TimeSpan.FromSeconds(3600), context.ExpiresIn);
|
||||
|
|
@ -972,7 +970,7 @@ namespace Microsoft.AspNetCore.Authentication.Google
|
|||
private static HttpResponseMessage ReturnJsonResponse(object content, HttpStatusCode code = HttpStatusCode.OK)
|
||||
{
|
||||
var res = new HttpResponseMessage(code);
|
||||
var text = JsonConvert.SerializeObject(content);
|
||||
var text = Newtonsoft.Json.JsonConvert.SerializeObject(content);
|
||||
res.Content = new StringContent(text, Encoding.UTF8, "application/json");
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using Microsoft.AspNetCore.Http;
|
|||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
|
@ -302,7 +301,7 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
|
|||
private static HttpResponseMessage ReturnJsonResponse(object content)
|
||||
{
|
||||
var res = new HttpResponseMessage(HttpStatusCode.OK);
|
||||
var text = JsonConvert.SerializeObject(content);
|
||||
var text = Newtonsoft.Json.JsonConvert.SerializeObject(content);
|
||||
res.Content = new StringContent(text, Encoding.UTF8, "application/json");
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue