[ApiAuthorization] Small fixes to adjust for the code on the SPA templates (#7090)
* Fix solution file * Fixes the post_logout_redirect_uri parameter on the DefaultClientRequestParametersProvider * Propagate state on ending session autoredirect * Update defaults for local-spa profile to align them with template code * Disable explicit support for WebApplications, it can still be enabled normally by configuring IS and we haven't evaluated the scenario E2E.
This commit is contained in:
parent
3e3441481c
commit
e0b264f1c0
|
|
@ -1,4 +1,4 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
|
|
@ -32,10 +32,5 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
/// The application is a native application like a mobile or desktop application.
|
/// The application is a native application like a mobile or desktop application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string NativeApp = "NativeApp";
|
public const string NativeApp = "NativeApp";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The application is a web application.
|
|
||||||
/// </summary>
|
|
||||||
internal const string WebApplication = "WebApplication";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -12,8 +12,8 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
{
|
{
|
||||||
internal class ConfigureClients : IConfigureOptions<ApiAuthorizationOptions>
|
internal class ConfigureClients : IConfigureOptions<ApiAuthorizationOptions>
|
||||||
{
|
{
|
||||||
private const string DefaultLocalSPARelativeRedirectUri = "";
|
private const string DefaultLocalSPARelativeRedirectUri = "/authentication/login-callback";
|
||||||
private const string DefaultLocalSPARelativePostLogoutRedirectUri = "";
|
private const string DefaultLocalSPARelativePostLogoutRedirectUri = "/authentication/logout-callback";
|
||||||
|
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
private readonly ILogger<ConfigureClients> _logger;
|
private readonly ILogger<ConfigureClients> _logger;
|
||||||
|
|
@ -50,9 +50,6 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
case ApplicationProfiles.SPA:
|
case ApplicationProfiles.SPA:
|
||||||
yield return GetSPA(name, definition);
|
yield return GetSPA(name, definition);
|
||||||
break;
|
break;
|
||||||
//case ApplicationProfiles.WebApplication:
|
|
||||||
// yield return GetWebApplication(name, definition);
|
|
||||||
// break;
|
|
||||||
case ApplicationProfiles.IdentityServerSPA:
|
case ApplicationProfiles.IdentityServerSPA:
|
||||||
yield return GetLocalSPA(name, definition);
|
yield return GetLocalSPA(name, definition);
|
||||||
break;
|
break;
|
||||||
|
|
@ -66,47 +63,6 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Client GetWebApplication(string name, ClientDefinition definition)
|
|
||||||
{
|
|
||||||
if (definition.RedirectUri == null ||
|
|
||||||
!Uri.TryCreate(definition.RedirectUri, UriKind.Absolute, out var redirectUri))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The redirect uri " +
|
|
||||||
$"'{definition.RedirectUri}' for '{name}' is invalid. " +
|
|
||||||
$"The redirect URI must be an absolute url.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definition.LogoutUri == null ||
|
|
||||||
!Uri.TryCreate(definition.LogoutUri, UriKind.Absolute, out var postLogouturi))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The logout uri " +
|
|
||||||
$"'{definition.LogoutUri}' for '{name}' is invalid. " +
|
|
||||||
$"The logout URI must be an absolute url.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.Equals(
|
|
||||||
redirectUri.GetLeftPart(UriPartial.Authority),
|
|
||||||
postLogouturi.GetLeftPart(UriPartial.Authority),
|
|
||||||
StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The redirect uri and the logout uri " +
|
|
||||||
$"for '{name}' have a different scheme, host or port.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (definition.ClientSecret == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The configuration for '{name}' does not contain a client secret. " +
|
|
||||||
$"Client secrets are required for web applications.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ClientBuilder.WebApplication(name)
|
|
||||||
.WithRedirectUri(definition.RedirectUri)
|
|
||||||
.WithLogoutRedirectUri(definition.LogoutUri)
|
|
||||||
.FromConfiguration()
|
|
||||||
.WithClientSecret(definition.ClientSecret)
|
|
||||||
.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Client GetSPA(string name, ClientDefinition definition)
|
private Client GetSPA(string name, ClientDefinition definition)
|
||||||
{
|
{
|
||||||
if (definition.RedirectUri == null ||
|
if (definition.RedirectUri == null ||
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -12,8 +12,10 @@ using IdentityServer4.Services;
|
||||||
using IdentityServer4.Validation;
|
using IdentityServer4.Validation;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
{
|
{
|
||||||
|
|
@ -67,7 +69,13 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
await ctx.SignOutAsync();
|
await ctx.SignOutAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RedirectResult(result.ValidatedRequest.PostLogOutUri);
|
var postLogOutUri = result.ValidatedRequest.PostLogOutUri;
|
||||||
|
if (result.ValidatedRequest.State != null)
|
||||||
|
{
|
||||||
|
postLogOutUri = QueryHelpers.AddQueryString(postLogOutUri, OpenIdConnectParameterNames.State, result.ValidatedRequest.State);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RedirectResult(postLogOutUri);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using IdentityServer4.Extensions;
|
using IdentityServer4.Extensions;
|
||||||
|
|
@ -43,9 +43,6 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
case ApplicationProfiles.NativeApp:
|
case ApplicationProfiles.NativeApp:
|
||||||
responseType = "code";
|
responseType = "code";
|
||||||
break;
|
break;
|
||||||
//case ApplicationProfiles.WebApplication:
|
|
||||||
// responseType = "id_token code";
|
|
||||||
// break;
|
|
||||||
default:
|
default:
|
||||||
throw new InvalidOperationException($"Invalid application type '{type}' for '{clientId}'.");
|
throw new InvalidOperationException($"Invalid application type '{type}' for '{clientId}'.");
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +52,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
["authority"] = authority,
|
["authority"] = authority,
|
||||||
["client_id"] = client.ClientId,
|
["client_id"] = client.ClientId,
|
||||||
["redirect_uri"] = UrlFactory.GetAbsoluteUrl(context, client.RedirectUris.First()),
|
["redirect_uri"] = UrlFactory.GetAbsoluteUrl(context, client.RedirectUris.First()),
|
||||||
["post_logout_redirect_uri"] = UrlFactory.GetAbsoluteUrl(context, client.RedirectUris.First()),
|
["post_logout_redirect_uri"] = UrlFactory.GetAbsoluteUrl(context, client.PostLogoutRedirectUris.First()),
|
||||||
["response_type"] = responseType,
|
["response_type"] = responseType,
|
||||||
["scope"] = string.Join(" ", client.AllowedScopes)
|
["scope"] = string.Join(" ", client.AllowedScopes)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -65,21 +65,6 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
.WithScopes(IdentityServerConstants.StandardScopes.OfflineAccess);
|
.WithScopes(IdentityServerConstants.StandardScopes.OfflineAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new builder for an externally registered web application.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="clientId">The client id for the web application.</param>
|
|
||||||
/// <returns>A <see cref="ClientBuilder"/>.</returns>
|
|
||||||
internal static ClientBuilder WebApplication(string clientId)
|
|
||||||
{
|
|
||||||
var client = CreateClient(clientId);
|
|
||||||
return new ClientBuilder(client)
|
|
||||||
.WithApplicationProfile(ApplicationProfiles.WebApplication)
|
|
||||||
.WithAllowedGrants(GrantTypes.HybridAndClientCredentials)
|
|
||||||
.WithScopes(IdentityServerConstants.StandardScopes.OfflineAccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of <see cref="ClientBuilder"/>.
|
/// Initializes a new instance of <see cref="ClientBuilder"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using IdentityServer4.Models;
|
using IdentityServer4.Models;
|
||||||
|
|
@ -110,17 +110,5 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
configure(app);
|
configure(app);
|
||||||
Add(app.Build());
|
Add(app.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds an externally registered web application..
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="clientId">The client id for the web application.</param>
|
|
||||||
/// <param name="configure">The <see cref="Action{ClientBuilder}"/> to configure the web application.</param>
|
|
||||||
public void AddWebApplication(string clientId, Action<ClientBuilder> configure)
|
|
||||||
{
|
|
||||||
var app = ClientBuilder.WebApplication(clientId);
|
|
||||||
configure(app);
|
|
||||||
Add(app.Build());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
|
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
|
||||||
|
|
@ -31,7 +32,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
|
||||||
.Build());
|
.Build());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
configureClientScopes.PostConfigure(Extensions.Options.Options.DefaultName, options);
|
configureClientScopes.PostConfigure(Options.DefaultName, options);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
foreach (var client in options.Clients)
|
foreach (var client in options.Clients)
|
||||||
|
|
@ -63,7 +64,7 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
|
||||||
.Build());
|
.Build());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
configureClientScopes.PostConfigure(Extensions.Options.Options.DefaultName, options);
|
configureClientScopes.PostConfigure(Options.DefaultName, options);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var spaClient = Assert.Single(options.Clients, c => c.ClientId == "TestSPA");
|
var spaClient = Assert.Single(options.Clients, c => c.ClientId == "TestSPA");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using IdentityServer4;
|
using IdentityServer4;
|
||||||
|
|
@ -58,13 +58,12 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
|
||||||
Assert.Equal("MyClient", client.ClientId);
|
Assert.Equal("MyClient", client.ClientId);
|
||||||
Assert.Equal("MyClient", client.ClientName);
|
Assert.Equal("MyClient", client.ClientName);
|
||||||
Assert.True(client.AllowAccessTokensViaBrowser);
|
Assert.True(client.AllowAccessTokensViaBrowser);
|
||||||
Assert.Equal(new[] { "" }, client.RedirectUris.ToArray());
|
Assert.Equal(new[] { "/authentication/login-callback" }, client.RedirectUris.ToArray());
|
||||||
Assert.Equal(new[] { "" }, client.PostLogoutRedirectUris.ToArray());
|
Assert.Equal(new[] { "/authentication/logout-callback" }, client.PostLogoutRedirectUris.ToArray());
|
||||||
Assert.Empty(client.AllowedCorsOrigins);
|
Assert.Empty(client.AllowedCorsOrigins);
|
||||||
Assert.False(client.RequireConsent);
|
Assert.False(client.RequireConsent);
|
||||||
Assert.Empty(client.ClientSecrets);
|
Assert.Empty(client.ClientSecrets);
|
||||||
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
|
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
|
||||||
//Assert.Equal(expectedScopes, client.AllowedScopes.ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -101,7 +100,6 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
|
||||||
Assert.Equal(GrantTypes.Code.ToArray(), client.AllowedGrantTypes.ToArray());
|
Assert.Equal(GrantTypes.Code.ToArray(), client.AllowedGrantTypes.ToArray());
|
||||||
Assert.True(client.RequirePkce);
|
Assert.True(client.RequirePkce);
|
||||||
Assert.False(client.AllowPlainTextPkce);
|
Assert.False(client.AllowPlainTextPkce);
|
||||||
//Assert.Equal(expectedScopes, client.AllowedScopes.ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -142,43 +140,6 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Configuration
|
||||||
Assert.False(client.RequireConsent);
|
Assert.False(client.RequireConsent);
|
||||||
Assert.Empty(client.ClientSecrets);
|
Assert.Empty(client.ClientSecrets);
|
||||||
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
|
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
|
||||||
//Assert.Equal(expectedScopes, client.AllowedScopes.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void GetClients_ReadsWebAppFromConfiguration()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
|
|
||||||
var config = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
["MyClient:Profile"] = "IdentityServerSPA"
|
|
||||||
}).Build();
|
|
||||||
|
|
||||||
var resources = Array.Empty<ApiResource>();
|
|
||||||
var expectedScopes = new[]
|
|
||||||
{
|
|
||||||
IdentityServerConstants.StandardScopes.OpenId,
|
|
||||||
IdentityServerConstants.StandardScopes.Profile
|
|
||||||
};
|
|
||||||
|
|
||||||
var clientLoader = new ConfigureClients(config, new TestLogger<ConfigureClients>());
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var clients = clientLoader.GetClients();
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var client = Assert.Single(clients);
|
|
||||||
Assert.Equal("MyClient", client.ClientId);
|
|
||||||
Assert.Equal("MyClient", client.ClientName);
|
|
||||||
Assert.True(client.AllowAccessTokensViaBrowser);
|
|
||||||
Assert.Equal(new[] { "" }, client.RedirectUris.ToArray());
|
|
||||||
Assert.Equal(new[] { "" }, client.PostLogoutRedirectUris.ToArray());
|
|
||||||
Assert.Empty(client.AllowedCorsOrigins);
|
|
||||||
Assert.False(client.RequireConsent);
|
|
||||||
Assert.Empty(client.ClientSecrets);
|
|
||||||
Assert.Equal(GrantTypes.Implicit.ToArray(), client.AllowedGrantTypes.ToArray());
|
|
||||||
//Assert.Equal(expectedScopes, client.AllowedScopes.ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -209,8 +170,8 @@ var config = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<str
|
||||||
Assert.Equal("MyClient", client.ClientId);
|
Assert.Equal("MyClient", client.ClientId);
|
||||||
Assert.Equal("MyClient", client.ClientName);
|
Assert.Equal("MyClient", client.ClientName);
|
||||||
Assert.True(client.AllowAccessTokensViaBrowser);
|
Assert.True(client.AllowAccessTokensViaBrowser);
|
||||||
Assert.Equal(new[] { "" }, client.RedirectUris.ToArray());
|
Assert.Equal(new[] { "/authentication/login-callback" }, client.RedirectUris.ToArray());
|
||||||
Assert.Equal(new[] { "" }, client.PostLogoutRedirectUris.ToArray());
|
Assert.Equal(new[] { "/authentication/logout-callback" }, client.PostLogoutRedirectUris.ToArray());
|
||||||
Assert.Empty(client.AllowedCorsOrigins);
|
Assert.Empty(client.AllowedCorsOrigins);
|
||||||
Assert.False(client.RequireConsent);
|
Assert.False(client.RequireConsent);
|
||||||
Assert.Empty(client.ClientSecrets);
|
Assert.Empty(client.ClientSecrets);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// 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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
@ -11,9 +12,11 @@ using IdentityServer4.Services;
|
||||||
using IdentityServer4.Validation;
|
using IdentityServer4.Validation;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -79,7 +82,8 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
ValidatedRequest = new ValidatedEndSessionRequest()
|
ValidatedRequest = new ValidatedEndSessionRequest()
|
||||||
{
|
{
|
||||||
Client = ClientBuilder.IdentityServerSPA("MySPA").Build(),
|
Client = ClientBuilder.IdentityServerSPA("MySPA").Build(),
|
||||||
PostLogOutUri = "https://www.example.com/logout"
|
PostLogOutUri = "https://www.example.com/logout",
|
||||||
|
State = "appState"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -99,10 +103,11 @@ namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(response);
|
Assert.NotNull(response);
|
||||||
var redirect = Assert.IsType<AutoRedirectEndSessionEndpoint.RedirectResult>(response);
|
var redirect = Assert.IsType<AutoRedirectEndSessionEndpoint.RedirectResult>(response);
|
||||||
Assert.Equal("https://www.example.com/logout", redirect.Url);
|
Assert.Equal("https://www.example.com/logout?state=appState", redirect.Url);
|
||||||
|
|
||||||
await response.ExecuteAsync(ctx);
|
await response.ExecuteAsync(ctx);
|
||||||
Assert.Equal(StatusCodes.Status302Found, ctx.Response.StatusCode);
|
Assert.Equal(StatusCodes.Status302Found, ctx.Response.StatusCode);
|
||||||
Assert.Equal("https://www.example.com/logout", ctx.Response.Headers[HeaderNames.Location]);
|
Assert.Equal("https://www.example.com/logout?state=appState", ctx.Response.Headers[HeaderNames.Location]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
// 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 IdentityServer4.Configuration;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer.Extensions
|
||||||
|
{
|
||||||
|
public class DefaultClientRequestParametersProviderTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void GetClientParameters_ReturnsParametersForExistingClients()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var absoluteUrlFactory = new Mock<IAbsoluteUrlFactory>();
|
||||||
|
absoluteUrlFactory.Setup(auf => auf.GetAbsoluteUrl(It.IsAny<HttpContext>(), It.IsAny<string>()))
|
||||||
|
.Returns<HttpContext, string>((_, s) => Uri.IsWellFormedUriString(s, UriKind.Absolute) ? s : new Uri(new Uri("http://localhost/"), s).ToString());
|
||||||
|
|
||||||
|
var options = Options.Create(new ApiAuthorizationOptions());
|
||||||
|
options.Value.Clients.AddIdentityServerSPA("SPA", cb =>
|
||||||
|
cb.WithScopes("a/b", "c/d")
|
||||||
|
.WithRedirectUri("authentication/login-callback")
|
||||||
|
.WithLogoutRedirectUri("authentication/logout-callback"));
|
||||||
|
|
||||||
|
var context = new DefaultHttpContext();
|
||||||
|
context.Request.Scheme = "http";
|
||||||
|
context.Request.Host = new HostString("localhost");
|
||||||
|
context.RequestServices = new ServiceCollection()
|
||||||
|
.AddSingleton(new IdentityServerOptions())
|
||||||
|
.BuildServiceProvider();
|
||||||
|
|
||||||
|
var clientRequestParametersProvider =
|
||||||
|
new DefaultClientRequestParametersProvider(
|
||||||
|
absoluteUrlFactory.Object,
|
||||||
|
options);
|
||||||
|
|
||||||
|
var expectedParameters = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["authority"] = "http://localhost",
|
||||||
|
["client_id"] = "SPA",
|
||||||
|
["redirect_uri"] = "http://localhost/authentication/login-callback",
|
||||||
|
["post_logout_redirect_uri"] = "http://localhost/authentication/logout-callback",
|
||||||
|
["response_type"] = "id_token token",
|
||||||
|
["scope"] = "a/b c/d"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = clientRequestParametersProvider.GetClientParameters(context, "SPA");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expectedParameters, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue