diff --git a/bitwarden_license/test/Sso.IntegrationTest/Endpoints/SsoConfigurationTests.cs b/bitwarden_license/test/Sso.IntegrationTest/Endpoints/SsoConfigurationTests.cs new file mode 100644 index 000000000000..1bbee62902ae --- /dev/null +++ b/bitwarden_license/test/Sso.IntegrationTest/Endpoints/SsoConfigurationTests.cs @@ -0,0 +1,35 @@ +using System.Text.Json; +using Bit.IntegrationTestCommon.Factories; +using Bit.Sso.IntegrationTest.Utilities; +using Bit.Test.Common.Helpers; +using Xunit; + +namespace Bit.Sso.IntegrationTest.Endpoints; + +public class SsoConfigurationTests : IClassFixture +{ + private readonly SsoApplicationFactory _factory; + + public SsoConfigurationTests(SsoApplicationFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task WellKnownEndpoint_Success() + { + var context = await _factory.Server.GetAsync("/.well-known/openid-configuration"); + + using var body = await AssertHelper.AssertResponseTypeIs(context); + var endpointRoot = body.RootElement; + + // WARNING: Edits to this file should NOT just be made to "get the test to work" they should be made when intentional + // changes were made to this endpoint and proper testing will take place to ensure clients are backwards compatible + // or loss of functionality is properly noted. + await using var fs = File.OpenRead("openid-configuration.json"); + using var knownConfiguration = await JsonSerializer.DeserializeAsync(fs); + var knownConfigurationRoot = knownConfiguration!.RootElement; + + AssertHelper.AssertEqualJson(endpointRoot, knownConfigurationRoot); + } +} diff --git a/bitwarden_license/test/Sso.IntegrationTest/openid-configuration.json b/bitwarden_license/test/Sso.IntegrationTest/openid-configuration.json new file mode 100644 index 000000000000..be88ecd19f97 --- /dev/null +++ b/bitwarden_license/test/Sso.IntegrationTest/openid-configuration.json @@ -0,0 +1,107 @@ +{ + "issuer": "http://localhost", + "jwks_uri": "http://localhost:51822/.well-known/openid-configuration/jwks", + "authorization_endpoint": "http://localhost:51822/connect/authorize", + "token_endpoint": "http://localhost:51822/connect/token", + "userinfo_endpoint": "http://localhost:51822/connect/userinfo", + "end_session_endpoint": "http://localhost:51822/connect/endsession", + "check_session_iframe": "http://localhost/connect/checksession", + "revocation_endpoint": "http://localhost:51822/connect/revocation", + "introspection_endpoint": "http://localhost:51822/connect/introspect", + "device_authorization_endpoint": "http://localhost:51822/connect/deviceauthorization", + "backchannel_authentication_endpoint": "http://localhost:51822/connect/ciba", + "pushed_authorization_request_endpoint": "http://localhost:51822/connect/par", + "require_pushed_authorization_requests": false, + "frontchannel_logout_supported": true, + "frontchannel_logout_session_supported": true, + "backchannel_logout_supported": true, + "backchannel_logout_session_supported": true, + "scopes_supported": [ + "openid", + "profile", + "offline_access" + ], + "claims_supported": [ + "sub", + "name", + "family_name", + "given_name", + "middle_name", + "nickname", + "preferred_username", + "profile", + "picture", + "website", + "gender", + "birthdate", + "zoneinfo", + "locale", + "updated_at" + ], + "grant_types_supported": [ + "authorization_code", + "client_credentials", + "refresh_token", + "implicit", + "urn:ietf:params:oauth:grant-type:device_code", + "urn:openid:params:grant-type:ciba" + ], + "response_types_supported": [ + "code", + "token", + "id_token", + "id_token token", + "code id_token", + "code token", + "code id_token token" + ], + "response_modes_supported": [ + "form_post", + "query", + "fragment" + ], + "token_endpoint_auth_methods_supported": [ + "client_secret_basic", + "client_secret_post" + ], + "id_token_signing_alg_values_supported": ["RS256"], + "userinfo_signing_alg_values_supported": ["RS256"], + "introspection_signing_alg_values_supported": ["RS256"], + "subject_types_supported": ["public"], + "code_challenge_methods_supported": [ + "plain", + "S256" + ], + "request_parameter_supported": true, + "request_object_signing_alg_values_supported": [ + "RS256", + "RS384", + "RS512", + "PS256", + "PS384", + "PS512", + "ES256", + "ES384", + "ES512" + ], + "prompt_values_supported": [ + "none", + "login", + "consent", + "select_account" + ], + "authorization_response_iss_parameter_supported": true, + "backchannel_token_delivery_modes_supported": ["poll"], + "backchannel_user_code_parameter_supported": true, + "dpop_signing_alg_values_supported": [ + "RS256", + "RS384", + "RS512", + "PS256", + "PS384", + "PS512", + "ES256", + "ES384", + "ES512" + ] +} diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj index 68c4cfe00077..7e7e8d9919ed 100644 --- a/src/Core/Core.csproj +++ b/src/Core/Core.csproj @@ -54,7 +54,7 @@ - + diff --git a/src/Core/Utilities/CoreHelpers.cs b/src/Core/Utilities/CoreHelpers.cs index c6815c31b0ba..d72d78d2badc 100644 --- a/src/Core/Utilities/CoreHelpers.cs +++ b/src/Core/Utilities/CoreHelpers.cs @@ -680,6 +680,11 @@ public static bool IsCorsOriginAllowed(string origin, GlobalSettings globalSetti public static Dictionary AdjustIdentityServerConfig(Dictionary configDict, string publicServiceUri, string internalServiceUri) { + // Remove metadata for endpoints/features we don't support + configDict.Remove("revocation_endpoint_auth_methods_supported"); + configDict.Remove("introspection_endpoint_auth_methods_supported"); + configDict.Remove("backchannel_authentication_request_signing_alg_values_supported"); + var dictReplace = new Dictionary(); foreach (var item in configDict) { diff --git a/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs b/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs index 1c7b035874ad..60814763c47b 100644 --- a/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs +++ b/test/Identity.IntegrationTest/Endpoints/IdentityServerSsoTests.cs @@ -702,7 +702,7 @@ await ssoConfigRepository.CreateAsync(new SsoConfig new Claim("organizationId", organization.Id.ToString()), new Claim(JwtClaimTypes.SessionId, "SOMETHING"), new Claim(JwtClaimTypes.AuthenticationMethod, "external"), - new Claim(JwtClaimTypes.AuthenticationTime, DateTime.UtcNow.AddMinutes(-1).ToEpochTime().ToString()) + new Claim(JwtClaimTypes.AuthenticationTime, new DateTimeOffset(DateTime.UtcNow.AddMinutes(-1)).ToUnixTimeSeconds().ToString()) }, "Duende.IdentityServer", JwtClaimTypes.Name, JwtClaimTypes.Role)); authorizationCode.Subject = subject; diff --git a/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs b/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs index d0d35f5d7bfe..ba2a551e15cd 100644 --- a/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs +++ b/test/Identity.IntegrationTest/Endpoints/IdentityServerTwoFactorTests.cs @@ -504,7 +504,7 @@ await ssoConfigRepository.CreateAsync(new SsoConfig new Claim("organizationId", organization.Id.ToString()), new Claim(JwtClaimTypes.SessionId, "SOMETHING"), new Claim(JwtClaimTypes.AuthenticationMethod, "external"), - new Claim(JwtClaimTypes.AuthenticationTime, DateTime.UtcNow.AddMinutes(-1).ToEpochTime().ToString()) + new Claim(JwtClaimTypes.AuthenticationTime, new DateTimeOffset(DateTime.UtcNow.AddMinutes(-1)).ToUnixTimeSeconds().ToString()) ], "Duende.IdentityServer", JwtClaimTypes.Name, JwtClaimTypes.Role)); authorizationCode.Subject = subject; diff --git a/test/Identity.IntegrationTest/openid-configuration.json b/test/Identity.IntegrationTest/openid-configuration.json index 96014764bd7b..739d7226065b 100644 --- a/test/Identity.IntegrationTest/openid-configuration.json +++ b/test/Identity.IntegrationTest/openid-configuration.json @@ -75,10 +75,7 @@ "PS512", "ES256", "ES384", - "ES512", - "HS256", - "HS384", - "HS512" + "ES512" ], "prompt_values_supported": ["none", "login", "consent", "select_account"], "authorization_response_iss_parameter_supported": true,