From 3b90ad926cde16b59a995cfb2d1ad3b687ef6e59 Mon Sep 17 00:00:00 2001 From: Simen Rekkedal <61084786+simen-rekkedal@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:47:12 +0200 Subject: [PATCH 1/5] unauth systemregister --- .../Controllers/SystemRegisterController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs index 59b636b7..b627dd22 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs @@ -17,7 +17,7 @@ public SystemRegisterController(ISystemRegisterService systemRegisterService) _systemRegisterService = systemRegisterService; } - [Authorize] + //[Authorize] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [HttpGet] public async Task GetListOfRegisteredSystems(CancellationToken cancellationToken = default) From 5cc0c79247c26dce0a1c1b661796731232e14ccf Mon Sep 17 00:00:00 2001 From: Simen Rekkedal <61084786+simen-rekkedal@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:34:34 +0200 Subject: [PATCH 2/5] reauth systemregister --- .../Controllers/SystemRegisterController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs index b627dd22..59b636b7 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Controllers/SystemRegisterController.cs @@ -17,7 +17,7 @@ public SystemRegisterController(ISystemRegisterService systemRegisterService) _systemRegisterService = systemRegisterService; } - //[Authorize] + [Authorize] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [HttpGet] public async Task GetListOfRegisteredSystems(CancellationToken cancellationToken = default) From 7aca52075cf89d9ce307068847cb3194757f8552 Mon Sep 17 00:00:00 2001 From: Simen Rekkedal <61084786+simen-rekkedal@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:03:36 +0200 Subject: [PATCH 3/5] add profileclient and it's dependencies --- .../Altinn.Authentication.UI.Core.csproj | 6 ++ .../Common/Extensions/HttpClientExtensions.cs | 2 +- .../UserProfiles/AccessTokenProvider.cs | 77 +++++++++++++++ .../UserProfiles/IAccessTokenProvider.cs | 7 +- .../UserProfiles/IUserProfileClient.cs | 8 ++ ...ltinn.Authentication.UI.Integration.csproj | 8 +- .../KeyVault/IKeyVaultService.cs | 18 ++++ .../KeyVault/KeyVaultService.cs | 37 ++++++++ .../KeyVault/LocalKeyVaultService.cs | 25 +++++ .../UserProfiles/UserProfileClient.cs | 95 +++++++++++++++---- 10 files changed, 260 insertions(+), 23 deletions(-) create mode 100644 bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/AccessTokenProvider.cs create mode 100644 bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs create mode 100644 bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs create mode 100644 bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj index cd703e65..0fd05baa 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj @@ -6,6 +6,12 @@ enable + + + + + + diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs index 7961aade..26e9df9a 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs @@ -1,4 +1,4 @@ -namespace Altinn.Authentication.UI.Core.Common; +namespace Altinn.Authentication.UI.Core.Extensions; public static class HttpClientExtensions { diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/AccessTokenProvider.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/AccessTokenProvider.cs new file mode 100644 index 00000000..f1b9ddaf --- /dev/null +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/AccessTokenProvider.cs @@ -0,0 +1,77 @@ +using Altinn.Authentication.UI.Core.AppConfiguration; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System.Security.Cryptography.X509Certificates; + +namespace Altinn.Authentication.UI.Core.UserProfiles +{ + /// + public class AccessTokenProvider : IAccessTokenProvider + { + private readonly IKeyVaultService _keyVaultService; + private readonly IAccessTokenGenerator _accessTokenGenerator; + private readonly AccessTokenSettings _accessTokenSettings; + private readonly ClientSettings _clientSettings; + private readonly KeyVaultSettings _keyVaultSettings; + private static readonly SemaphoreSlim Semaphore = new SemaphoreSlim(1, 1); + private static DateTime _cacheTokenUntil = DateTime.MinValue; + private string _accessToken; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// The key vault service. + /// The access token generator. + /// Then access token settings + /// The key vault settings. + /// The client settings for access token generation + /// the logger handler + public AccessTokenProvider( + IKeyVaultService keyVaultService, + IAccessTokenGenerator accessTokenGenerator, + IOptions accessTokenSettings, + IOptions keyVaultSettings, + IOptions clientSettings, + ILogger logger) + { + _keyVaultService = keyVaultService; + _accessTokenGenerator = accessTokenGenerator; + _accessTokenSettings = accessTokenSettings.Value; + _keyVaultSettings = keyVaultSettings.Value; + _clientSettings = clientSettings.Value; + _logger = logger; + } + + /// + public async Task GetAccessToken() + { + await Semaphore.WaitAsync(); + + try + { + if (_accessToken == null || _cacheTokenUntil < DateTime.UtcNow) + { + string certBase64 = await _keyVaultService.GetCertificateAsync(_keyVaultSettings.SecretUri, _clientSettings.CertificateName); + _accessToken = _accessTokenGenerator.GenerateAccessToken( + _clientSettings.Issuer, + _clientSettings.App, + new X509Certificate2(Convert.FromBase64String(certBase64), (string)null, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable)); + + _cacheTokenUntil = DateTime.UtcNow.AddSeconds(_accessTokenSettings.TokenLifetimeInSeconds - 2); // Add some slack to avoid tokens expiring in transit + } + + return _accessToken; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to generate access token."); + return null; + } + finally + { + Semaphore.Release(); + } + } + } +} diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IAccessTokenProvider.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IAccessTokenProvider.cs index 992bfa3f..2b220db7 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IAccessTokenProvider.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IAccessTokenProvider.cs @@ -1,5 +1,10 @@ namespace Altinn.Authentication.UI.Core.UserProfiles; -public class IAccessTokenProvider +public interface IAccessTokenProvider { + /// + /// Gets the access token. + /// + /// An access token as a printable string + public Task GetAccessToken(); } diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileClient.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileClient.cs index 873bcf23..1ed843aa 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileClient.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileClient.cs @@ -3,8 +3,16 @@ namespace Altinn.Authentication.UI.Core.UserProfiles; +/// +/// +/// public interface IUserProfileClient { + /// + /// Retrieves the userprofile by id from the Platforms Profile API + /// + /// + /// public Task GetUserProfile(int userid); } diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj index 8cee2bbf..37fa5d44 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -6,6 +6,12 @@ enable + + + + + + diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs new file mode 100644 index 00000000..34b84236 --- /dev/null +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; + +namespace Altinn.AccessManagement.UI.Core.Services.Interfaces +{ + /// + /// Interface for interacting with key vault + /// + public interface IKeyVaultService + { + /// + /// Gets the value of a secret from the given key vault. + /// + /// The URI of the key vault to ask for secret. + /// The id of the secret. + /// The secret value. + Task GetCertificateAsync(string vaultUri, string secretId); + } +} diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs new file mode 100644 index 00000000..ab120b2a --- /dev/null +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs @@ -0,0 +1,37 @@ +using System.Diagnostics.CodeAnalysis; +using Altinn.AccessManagement.UI.Core.Services.Interfaces; +using Azure; +using Azure.Identity; +using Azure.Security.KeyVault.Certificates; +using Azure.Security.KeyVault.Secrets; + +namespace Altinn.AccessManagement.UI.Core.Services +{ + /// + /// Wrapper implementation for a KeyVaultClient. The wrapped client is created with a principal obtained through configuration. + /// + /// This class is excluded from code coverage because it has no logic to be tested. + [ExcludeFromCodeCoverage] + public class KeyVaultService : IKeyVaultService + { + /// + public async Task GetCertificateAsync(string vaultUri, string secretId) + { + CertificateClient certificateClient = new CertificateClient(new Uri(vaultUri), new DefaultAzureCredential()); + AsyncPageable certificatePropertiesPage = certificateClient.GetPropertiesOfCertificateVersionsAsync(secretId); + await foreach (CertificateProperties certificateProperties in certificatePropertiesPage) + { + if (certificateProperties.Enabled == true && + (certificateProperties.ExpiresOn == null || certificateProperties.ExpiresOn >= DateTime.UtcNow)) + { + SecretClient secretClient = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential()); + + KeyVaultSecret secret = await secretClient.GetSecretAsync(certificateProperties.Name, certificateProperties.Version); + return secret.Value; + } + } + + return null; + } + } +} diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs new file mode 100644 index 00000000..79a52099 --- /dev/null +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs @@ -0,0 +1,25 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Altinn.AccessManagement.UI.Core.Services.Interfaces; +using Azure; +using Azure.Identity; +using Azure.Security.KeyVault.Certificates; +using Azure.Security.KeyVault.Secrets; + +namespace Altinn.AccessManagement.UI.Core.Services +{ + /// + /// Wrapper implementation for a KeyVaultClient. The wrapped client is created with a principal obtained through configuration. + /// + /// This class is excluded from code coverage because it has no logic to be tested. + [ExcludeFromCodeCoverage] + public class LocalKeyVaultService : IKeyVaultService + { + /// + public Task GetCertificateAsync(string vaultUri, string secretId) + { + string certBase64 = Convert.ToBase64String(Encoding.ASCII.GetBytes("-----BEGIN CERTIFICATE-----\r\nMIIDAzCCAeugAwIBAgIJANTdO8o3I8x5MA0GCSqGSIb3DQEBCwUAMA4xDDAKBgNV\r\nBAMTA3R0ZDAeFw0yMDA1MjUxMjIxMzdaFw0zMDA1MjQxMjIxMzdaMA4xDDAKBgNV\r\nBAMTA3R0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcfTsXwwLyC\r\nUkIz06eadWJvG3yrzT+ZB2Oy/WPaZosDnPcnZvCDueN+oy0zTx5TyH5gCi1FvzX2\r\n7G2eZEKwQaRPv0yuM+McHy1rXxMSOlH/ebP9KJj3FDMUgZl1DCAjJxSAANdTwdrq\r\nydVg1Crp37AQx8IIEjnBhXsfQh1uPGt1XwgeNyjl00IejxvQOPzd1CofYWwODVtQ\r\nl3PKn1SEgOGcB6wuHNRlnZPCIelQmqxWkcEZiu/NU+kst3NspVUQG2Jf2AF8UWgC\r\nrnrhMQR0Ra1Vi7bWpu6QIKYkN9q0NRHeRSsELOvTh1FgDySYJtNd2xDRSf6IvOiu\r\ntSipl1NZlV0CAwEAAaNkMGIwIAYDVR0OAQH/BBYEFIwq/KbSMzLETdo9NNxj0rz4\r\nqMqVMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgWgMCAGA1UdJQEB/wQWMBQG\r\nCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAE56UmH5gEYbe\r\n1kVw7nrfH0R9FyVZGeQQWBn4/6Ifn+eMS9mxqe0Lq74Ue1zEzvRhRRqWYi9JlKNf\r\n7QQNrc+DzCceIa1U6cMXgXKuXquVHLmRfqvKHbWHJfIkaY8Mlfy++77UmbkvIzly\r\nT1HVhKKp6Xx0r5koa6frBh4Xo/vKBlEyQxWLWF0RPGpGErnYIosJ41M3Po3nw3lY\r\nf7lmH47cdXatcntj2Ho/b2wGi9+W29teVCDfHn2/0oqc7K0EOY9c2ODLjUvQyPZR\r\nOD2yykpyh9x/YeYHFDYdLDJ76/kIdxN43kLU4/hTrh9tMb1PZF+/4DshpAlRoQuL\r\no8I8avQm/A==\r\n-----END CERTIFICATE-----")); + return Task.FromResult(certBase64); + } + } +} diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs index c24623a0..ef8ab305 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs @@ -1,34 +1,89 @@ -using Altinn.Authentication.UI.Core.UserProfiles; +using Altinn.Authentication.UI.Core.Authentication; +using Altinn.Authentication.UI.Core.UserProfiles; +using Altinn.Authentication.UI.Integration.Configuration; using Altinn.Platform.Profile.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using System.Text.Json; +using System.Text.Json.Serialization; +using Altinn.Authentication.UI.Core.Extensions; namespace Altinn.Authentication.UI.Integration.UserProfiles; +/// +/// Integration client towards the Profile API in Platform +/// public class UserProfileClient : IUserProfileClient { + private readonly ILogger _logger; + private readonly HttpClient _httpClient; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly PlatformSettings _platformSettings; + private readonly IAccessTokenProvider _accessTokenProvider; + + /// + /// Constructor + /// + /// + /// + /// + /// + /// + public UserProfileClient( + ILogger logger, + HttpClient httpClient, + IHttpContextAccessor httpContextAccessor, + PlatformSettings platformSettings, + IAccessTokenProvider accessTokenProvider) + { + _logger = logger; + _httpClient = httpClient; + _httpContextAccessor = httpContextAccessor; + _platformSettings = platformSettings; + _accessTokenProvider = accessTokenProvider; + } + + /// public async Task GetUserProfile(int userid) { - await Task.Delay(50); + UserProfile user; + try + { + string endpoint = $"users/{userid}"; + user = await GetUserProfileFromEndpoint(endpoint); + } + catch (Exception ex) + { + _logger.LogError(ex, "Authentication.UI // ProfileClient // GetUserProfile // Exception"); + throw; + } + + return user!; + } + + private async Task GetUserProfileFromEndpoint(string endpoint) + { + string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext!, _platformSettings.JwtCookieName!)!; + var accessToken = await _accessTokenProvider.GetAccessToken(); + + HttpResponseMessage response = await _httpClient.GetAsync(token, endpoint, accessToken ); - UserProfile user = new() + if(response.StatusCode == System.Net.HttpStatusCode.OK) { - UserId = 20004938, - Email = "1337@altinnstudiotestusers.com", - PhoneNumber = "90001337", - UserName = "Testur Testursson Jr", - PartyId = 50019992, - ExternalIdentity = "", - Party = new Platform.Register.Models.Party + string responseContent = await response.Content.ReadAsStringAsync(); + var options = new JsonSerializerOptions { - Name = "Test Organisasjon" - }, - ProfileSettingPreference = new() - { - Language = "nb" - }, - UserType = Platform.Profile.Enums.UserType.SSNIdentified - - }; + PropertyNameCaseInsensitive = true, + }; + options.Converters.Add(new JsonStringEnumConverter()); + UserProfile userProfile = JsonSerializer.Deserialize(responseContent, options)!; + return userProfile; + } + else + { + _logger.LogError($"Getting user profile information from platform failed with statuscode {response.StatusCode}"); + return null!; + } - return user; } } From f91ce10775eeeb864237cb8673b640870675d3ed Mon Sep 17 00:00:00 2001 From: Simen Rekkedal <61084786+simen-rekkedal@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:24:26 +0200 Subject: [PATCH 4/5] access token etc towards profile api --- .../Altinn.Authentication.UI.Core.csproj | 6 - .../Authentication/HttpClientExtensions.cs | 109 ------------ .../Common/Extensions/HttpClientExtensions.cs | 168 ++++++++---------- .../AccessToken}/AccessTokenProvider.cs | 7 +- .../AccessToken}/IAccessTokenProvider.cs | 2 +- ...ltinn.Authentication.UI.Integration.csproj | 1 + .../KeyVault/IKeyVaultService.cs | 2 +- .../KeyVault/KeyVaultService.cs | 3 +- .../KeyVault/LocalKeyVaultService.cs | 3 +- .../UserProfiles/UserProfileClient.cs | 1 + .../Altinn.Authentication.UI.csproj | 2 +- 11 files changed, 87 insertions(+), 217 deletions(-) delete mode 100644 bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Authentication/HttpClientExtensions.cs rename bff/src/Altinn.Authentication.UI/{Altinn.Authentication.UI.Core/UserProfiles => Altinn.Authentication.UI.Integration/AccessToken}/AccessTokenProvider.cs (94%) rename bff/src/Altinn.Authentication.UI/{Altinn.Authentication.UI.Core/UserProfiles => Altinn.Authentication.UI.Integration/AccessToken}/IAccessTokenProvider.cs (77%) diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj index 0fd05baa..cd703e65 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Altinn.Authentication.UI.Core.csproj @@ -6,12 +6,6 @@ enable - - - - - - diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Authentication/HttpClientExtensions.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Authentication/HttpClientExtensions.cs deleted file mode 100644 index da1361df..00000000 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Authentication/HttpClientExtensions.cs +++ /dev/null @@ -1,109 +0,0 @@ -namespace Altinn.Authentication.UI.Core.Authentication; - -public static class HttpClientExtensions -{ - - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task PostAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) - { - HttpRequestMessage request = new(HttpMethod.Post, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - if (platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } - - return httpClient.SendAsync(request, CancellationToken.None); - } - - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task PutAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) - { - HttpRequestMessage request = new(HttpMethod.Put, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - - if (platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } - - return httpClient.SendAsync(request, CancellationToken.None); - } - - - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task GetAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) - { - HttpRequestMessage request = new(HttpMethod.Get, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - - if (platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } - - return httpClient.SendAsync(request, CancellationToken.None); - } - - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task DeleteAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) - { - HttpRequestMessage request = new(HttpMethod.Delete, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - - if (platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } - - return httpClient.SendAsync(request, CancellationToken.None); - } -} diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs index 26e9df9a..9681c65b 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/Common/Extensions/HttpClientExtensions.cs @@ -1,109 +1,91 @@ namespace Altinn.Authentication.UI.Core.Extensions; -public static class HttpClientExtensions +/// +/// This extension is created to make it easy to add a bearer token to a HttpRequests. +/// +public static class HttpClientExtension { - - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task PostAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) +/// +/// Extension that add authorization header to request. +/// +/// The HttpClient. +/// the authorization token (jwt). +/// The request Uri. +/// The http content. +/// The platformAccess tokens. +/// A HttpResponseMessage. +public static Task PostAsync(this HttpClient httpClient, string authorizationToken, string requestUri, HttpContent content, string platformAccessToken = null) +{ + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + request.Content = content; + if (!string.IsNullOrEmpty(platformAccessToken)) { - HttpRequestMessage request = new(HttpMethod.Post, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - if(platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } - - return httpClient.SendAsync(request, CancellationToken.None); + request.Headers.Add("PlatformAccessToken", platformAccessToken); } - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task PutAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) - { - HttpRequestMessage request = new(HttpMethod.Put, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - - if(platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } + return httpClient.SendAsync(request, CancellationToken.None); +} - return httpClient.SendAsync(request, CancellationToken.None); +/// +/// Extension that add authorization header to request. +/// +/// The HttpClient. +/// the authorization token (jwt). +/// The request Uri. +/// The http content. +/// The platformAccess tokens. +/// A HttpResponseMessage. +public static Task PutAsync(this HttpClient httpClient, string authorizationToken, string requestUri, HttpContent content, string platformAccessToken = null) +{ + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Put, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + request.Content = content; + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); } + return httpClient.SendAsync(request, CancellationToken.None); +} - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task GetAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) +/// +/// Extension that add authorization header to request. +/// +/// The HttpClient. +/// the authorization token (jwt). +/// The request Uri. +/// The platformAccess tokens. +/// A HttpResponseMessage. +public static Task GetAsync(this HttpClient httpClient, string authorizationToken, string requestUri, string platformAccessToken = null) +{ + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + if (!string.IsNullOrEmpty(platformAccessToken)) { - HttpRequestMessage request = new(HttpMethod.Get, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - - if(platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } - - return httpClient.SendAsync(request, CancellationToken.None); + request.Headers.Add("PlatformAccessToken", platformAccessToken); } - /// - /// Extensionmethod to add Authorization token and access token to the header - /// - /// - /// - /// - /// - /// - /// - public static Task DeleteAsync( - this HttpClient httpClient, - string authorizationToken, string requestURI, - HttpContent content, string? platformAccessToken = null) - { - HttpRequestMessage request = new(HttpMethod.Delete, requestURI); - request.Headers.Add("Authorization", "Bearer " + authorizationToken); - request.Content = content; - - if(platformAccessToken is not null && platformAccessToken.Length > 0) - { - request.Headers.Add("PlatformAccessToken", platformAccessToken); - } + return httpClient.SendAsync(request, HttpCompletionOption.ResponseContentRead, CancellationToken.None); +} - return httpClient.SendAsync(request, CancellationToken.None); +/// +/// Extension that add authorization header to request. +/// +/// The HttpClient. +/// the authorization token (jwt). +/// The request Uri. +/// The platformAccess tokens. +/// A HttpResponseMessage. +public static Task DeleteAsync(this HttpClient httpClient, string authorizationToken, string requestUri, string platformAccessToken = null) +{ + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, requestUri); + request.Headers.Add("Authorization", "Bearer " + authorizationToken); + if (!string.IsNullOrEmpty(platformAccessToken)) + { + request.Headers.Add("PlatformAccessToken", platformAccessToken); } + + return httpClient.SendAsync(request, CancellationToken.None); +} } diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/AccessTokenProvider.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/AccessToken/AccessTokenProvider.cs similarity index 94% rename from bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/AccessTokenProvider.cs rename to bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/AccessToken/AccessTokenProvider.cs index f1b9ddaf..f1f72438 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/AccessTokenProvider.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/AccessToken/AccessTokenProvider.cs @@ -2,9 +2,12 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Security.Cryptography.X509Certificates; +using Altinn.Authentication.UI.Integration.KeyVault; +using Altinn.Common.AccessTokenClient.Services; +using Altinn.Common.AccessTokenClient.Configuration; -namespace Altinn.Authentication.UI.Core.UserProfiles -{ +namespace Altinn.Authentication.UI.Integration.AccessToken +{ /// public class AccessTokenProvider : IAccessTokenProvider { diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IAccessTokenProvider.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/AccessToken/IAccessTokenProvider.cs similarity index 77% rename from bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IAccessTokenProvider.cs rename to bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/AccessToken/IAccessTokenProvider.cs index 2b220db7..6cf9c131 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IAccessTokenProvider.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/AccessToken/IAccessTokenProvider.cs @@ -1,4 +1,4 @@ -namespace Altinn.Authentication.UI.Core.UserProfiles; +namespace Altinn.Authentication.UI.Integration.AccessToken; public interface IAccessTokenProvider { diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj index 37fa5d44..4a84849c 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/Altinn.Authentication.UI.Integration.csproj @@ -7,6 +7,7 @@ + diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs index 34b84236..53d0473a 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/IKeyVaultService.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; -namespace Altinn.AccessManagement.UI.Core.Services.Interfaces +namespace Altinn.Authentication.UI.Integration.KeyVault { /// /// Interface for interacting with key vault diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs index ab120b2a..e1c77fed 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/KeyVaultService.cs @@ -1,11 +1,10 @@ using System.Diagnostics.CodeAnalysis; -using Altinn.AccessManagement.UI.Core.Services.Interfaces; using Azure; using Azure.Identity; using Azure.Security.KeyVault.Certificates; using Azure.Security.KeyVault.Secrets; -namespace Altinn.AccessManagement.UI.Core.Services +namespace Altinn.Authentication.UI.Integration.KeyVault { /// /// Wrapper implementation for a KeyVaultClient. The wrapped client is created with a principal obtained through configuration. diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs index 79a52099..f9372cbf 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/KeyVault/LocalKeyVaultService.cs @@ -1,12 +1,11 @@ using System.Diagnostics.CodeAnalysis; using System.Text; -using Altinn.AccessManagement.UI.Core.Services.Interfaces; using Azure; using Azure.Identity; using Azure.Security.KeyVault.Certificates; using Azure.Security.KeyVault.Secrets; -namespace Altinn.AccessManagement.UI.Core.Services +namespace Altinn.Authentication.UI.Integration.KeyVault { /// /// Wrapper implementation for a KeyVaultClient. The wrapped client is created with a principal obtained through configuration. diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs index ef8ab305..159ba554 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Integration/UserProfiles/UserProfileClient.cs @@ -7,6 +7,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Altinn.Authentication.UI.Core.Extensions; +using Altinn.Authentication.UI.Integration.AccessToken; namespace Altinn.Authentication.UI.Integration.UserProfiles; diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Altinn.Authentication.UI.csproj b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Altinn.Authentication.UI.csproj index 3414291c..83d59e61 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Altinn.Authentication.UI.csproj +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI/Altinn.Authentication.UI.csproj @@ -15,7 +15,7 @@ - + From 31c62eed76c185a0ac0794b17bb29b80b340bf90 Mon Sep 17 00:00:00 2001 From: Simen Rekkedal <61084786+simen-rekkedal@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:48:05 +0200 Subject: [PATCH 5/5] fix comment --- .../UserProfiles/IUserProfileService.cs | 5 +++++ .../UserProfiles/UserProfileService.cs | 1 + 2 files changed, 6 insertions(+) diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileService.cs index 5d690267..b077ea93 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileService.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/IUserProfileService.cs @@ -4,5 +4,10 @@ namespace Altinn.Authentication.UI.Core.UserProfiles; public interface IUserProfileService { + /// + /// Get the userprofile from the Platform Profile API + /// + /// + /// Task GetUserProfile(int userid); } diff --git a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/UserProfileService.cs b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/UserProfileService.cs index cb2ae31b..fe9c9ec8 100644 --- a/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/UserProfileService.cs +++ b/bff/src/Altinn.Authentication.UI/Altinn.Authentication.UI.Core/UserProfiles/UserProfileService.cs @@ -16,6 +16,7 @@ public UserProfileService( _profileClient = profileClient; } + /// public async Task GetUserProfile(int userid) { UserProfile userProfile = await _profileClient.GetUserProfile(userid);