From d1c861f286494510a480f8ec17468defd896636f Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Thu, 10 Aug 2023 15:41:28 -0400 Subject: [PATCH 01/29] fix: cert to keys --- .github/workflows/test.yaml | 57 +++++++++++++++++++ Bulwark.Auth.Guard.sln | 1 + src/Bulwark.Auth.Guard/Authenticate.cs | 37 ++++++------ src/Bulwark.Auth.Guard/Cert.cs | 16 ------ src/Bulwark.Auth.Guard/Key.cs | 25 ++++++++ .../AuthenticateTests.cs | 2 +- 6 files changed, 103 insertions(+), 35 deletions(-) create mode 100644 .github/workflows/test.yaml delete mode 100644 src/Bulwark.Auth.Guard/Cert.cs create mode 100644 src/Bulwark.Auth.Guard/Key.cs diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..210cb10 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,57 @@ +name: Tests + +on: + pull_request: +jobs: + build: + runs-on: ubuntu-latest + services: + mongodb: + image: mongo:latest + ports: + - 27017:27017 + mailhog: + image: mailhog/mailhog:latest + ports: + - 1025:1025 + - 8025:8025 + bulwark.auth: + image: "lateflip/bulwark.auth:latest" + env: + DB_CONNECTION: mongodb://localhost:27017 + GOOGLE_CLIENT_ID: 651882111548-0hrg7e4o90q1iutmfn02qkf9m90k3d3g.apps.googleusercontent.com + MICROSOFT_CLIENT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b + MICROSOFT_TENANT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b + GITHUB_APP_NAME: lateflip.io + DOMAIN: lateflip.io + WEBSITE_NAME: Lateflip + EMAIL_TEMPLATE_DIR: src/bulwark-admin-api/email-templates + EMAIL_SEND_ADDRESS: admin@lateflip.io + EMAIL_SMTP: true + EMAIL_SMTP_HOST: localhost + EMAIL_SMTP_PORT: 1025 + EMAIL_SMTP_USER: user + EMAIL_SMTP_PASS: pass + EMAIL_SMTP_SECURE: false + VERIFICATION_URL: https://localhost:3000/verify + FORGOT_PASSWORD_URL: https://localhost:3000/reset-password + MAGIC_LINK_URL: https://localhost:3000/magic-link + MAGIC_CODE_EXPIRE_IN_MINUTES: 10 + SERVICE_MODE: test + ports: + - 8080:80 + strategy: + matrix: + dotnet-version: ['7.0.x'] + steps: + - uses: actions/checkout@v3 + - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ matrix.dotnet-version }} + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + - name: Test + run: dotnet test --no-restore --verbosity normal \ No newline at end of file diff --git a/Bulwark.Auth.Guard.sln b/Bulwark.Auth.Guard.sln index 69fd8bb..21c2b46 100644 --- a/Bulwark.Auth.Guard.sln +++ b/Bulwark.Auth.Guard.sln @@ -16,6 +16,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{FE243A42-1EE4-4E88-BFEC-C8864948DE10}" ProjectSection(SolutionItems) = preProject .github\workflows\release.yaml = .github\workflows\release.yaml + .github\workflows\test.yaml = .github\workflows\test.yaml EndProjectSection EndProject Global diff --git a/src/Bulwark.Auth.Guard/Authenticate.cs b/src/Bulwark.Auth.Guard/Authenticate.cs index 998e827..e1ccd2c 100644 --- a/src/Bulwark.Auth.Guard/Authenticate.cs +++ b/src/Bulwark.Auth.Guard/Authenticate.cs @@ -12,20 +12,20 @@ namespace Bulwark.Auth.Guard; public class Authenticate { private readonly RestClient _client; - private Dictionary _certs; + private Dictionary _keys; public Authenticate(string baseUri) { _client = new RestClient(baseUri); _client.AddDefaultHeader("Content-Type", "application/json"); _client.AddDefaultHeader("Accept", "application/json"); - _certs = new Dictionary(); + _keys = new Dictionary(); } public Authenticate(RestClient client) { _client = client; - _certs = new Dictionary(); + _keys = new Dictionary(); } /// @@ -243,13 +243,14 @@ public async Task ValidateAccessToken(string email, string accessTo { var handler = new JwtSecurityTokenHandler(); var decodedValue = handler.ReadJwtToken(accessToken); - var generation = int.Parse(decodedValue.Header["gen"].ToString() ?? - throw new BulwarkException("No generation claim")); - Cert cert; + var keyId = decodedValue.Header["kid"].ToString() ?? + throw new BulwarkException("No kid claim"); + Key key; - if (_certs.ContainsKey(generation)) + + if (_keys.ContainsKey(keyId)) { - cert = _certs[generation]; + key = _keys[keyId]; } else { @@ -258,7 +259,7 @@ public async Task ValidateAccessToken(string email, string accessTo var publicKey = RSA.Create(); - publicKey.ImportFromPem(cert.PublicKey.ToCharArray()); + publicKey.ImportFromPem(key.PublicKey.ToCharArray()); var json = JwtBuilder.Create() .WithAlgorithm(new RS256Algorithm(publicKey)) @@ -270,22 +271,22 @@ public async Task ValidateAccessToken(string email, string accessTo return token; } - public async Task InitializeLocalCertValidation() + public async Task InitializeLocalKeyValidation() { - var request = new RestRequest("certs"); + var request = new RestRequest("keys"); var response = await _client.ExecuteGetAsync(request); if (response.Content != null) { - var certs = JsonSerializer.Deserialize>(response.Content); + var keys = JsonSerializer.Deserialize>(response.Content); - if (certs != null) + if (keys != null) { - _certs = new Dictionary(); - foreach (var cert in certs) + _keys = new Dictionary(); + foreach (var key in keys) { - _certs.Add(cert.Generation, cert); + _keys.Add(key.KeyId, key); } } } @@ -298,7 +299,7 @@ public async Task Renew(string refreshToken, { Email = email, DeviceId = deviceId, - RefreshToken = refreshToken + Token = refreshToken }; var request = new RestRequest("authentication/renew") @@ -333,7 +334,7 @@ public async Task Revoke(string accessToken, { Email = email, DeviceId = deviceId, - AccessToken = accessToken + Token = accessToken }; var request = new RestRequest("authentication/revoke") diff --git a/src/Bulwark.Auth.Guard/Cert.cs b/src/Bulwark.Auth.Guard/Cert.cs deleted file mode 100644 index 009584e..0000000 --- a/src/Bulwark.Auth.Guard/Cert.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Bulwark.Auth.Guard; - -public class Cert -{ - [JsonPropertyName("generation")] - public int Generation { get; set; } - [JsonPropertyName("publicKey")] - public string PublicKey { get; set; } - - public Cert() - { - PublicKey = string.Empty; - } -} \ No newline at end of file diff --git a/src/Bulwark.Auth.Guard/Key.cs b/src/Bulwark.Auth.Guard/Key.cs new file mode 100644 index 0000000..6161f4b --- /dev/null +++ b/src/Bulwark.Auth.Guard/Key.cs @@ -0,0 +1,25 @@ +using System; +using System.Text.Json.Serialization; + +namespace Bulwark.Auth.Guard; + +/// +/// "keyId": "6d9f6ec7-ca08-48d6-b783-059b43ef12d9", +/// "format": "PKCS#1", +/// "publicKey": "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAzbh/4VW0pvatNbno8t+JGylmfq3ZotMspetDyg0ikVAOPypqnEtRpIfc+ugZ3udU\r\nwIpDBdTXziwAmL/v0r4l0areOHzVmTZgFHcN+rdTrzcn2kO7bafWgvsHpQROeq/4H6r6pzSnj/5B\r\nTohKPLdRohDbONzdaDx3m2NOt2cyUrmCOJKxY59Fv/dPzm692vRy3BveKsOeiua2kV/LH5X7dBrS\r\nIENxVmd5oaWUEJ3s/2DZnLPwFvGB7U1vLmeGF8yLJFrOP/Q/SThUtUiQYQZ9s1Cog1btbOyWB29E\r\nB8dYXEh5bCkv+Z2u5TnblSxhT54fIFKMKFhInk/HHhb0+6psiQIDAQAB\n-----END RSA PUBLIC KEY-----", +/// "algorithm": "RS256", +/// "created": "2023-08-01T22:59:27.989Z" +/// +public class Key +{ + [JsonPropertyName("keyId")] + public string KeyId { get; set; } + [JsonPropertyName("format")] + public string Format { get; set; } + [JsonPropertyName("publicKey")] + public string PublicKey { get; set; } + [JsonPropertyName("algorithm")] + public string Algorithm { get; set; } + [JsonPropertyName("created")] + public DateTime Created { get; set; } +} \ No newline at end of file diff --git a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs index ce690be..bba7ca3 100644 --- a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs +++ b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs @@ -50,7 +50,7 @@ await _guard.Authenticate.Password(_testEmail, [Fact] public async Task AuthenticatePasswordAndAcknowledgeValidateLocal() { - await _guard.Authenticate.InitializeLocalCertValidation(); + await _guard.Authenticate.InitializeLocalKeyValidation(); await _guard.Account.Create(_testEmail, _testPassword); var messages = await _mailHog.GetMessagesAsync(); var message = messages.Items From 4ac5924b9f497a62786fbb5d335be84f91c6d616 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Mon, 14 Aug 2023 13:12:44 -0400 Subject: [PATCH 02/29] fix: tests and update Auth on docker compose --- docker-compose.yaml | 2 +- tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 7e88a48..46fc8ec 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: bulwark.auth: - image: "lateflip/bulwark.auth:1.0.11-beta.2" + image: "lateflip/bulwark.auth:latest" env_file: - .env ports: diff --git a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs index bba7ca3..15d3220 100644 --- a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs +++ b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs @@ -217,7 +217,14 @@ public async Task RequestMagicLinkAndAuthenticate() public async Task GoogleLoginAndAuthenticate() { var googleToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjI3NDA1MmEyYjY0NDg3NDU3NjRlNzJjMzU5MDk3MWQ5MGNmYjU4NWEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2NzUwMjk5NzcsImF1ZCI6IjY1MTg4MjExMTU0OC0waHJnN2U0bzkwcTFpdXRtZm4wMnFrZjltOTBrM2QzZy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjEwMjIzODE1MDc1NDU1ODI4NTM3MyIsImhkIjoibGF0ZWZsaXAuaW8iLCJlbWFpbCI6ImZyaXR6QGxhdGVmbGlwLmlvIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF6cCI6IjY1MTg4MjExMTU0OC0waHJnN2U0bzkwcTFpdXRtZm4wMnFrZjltOTBrM2QzZy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsIm5hbWUiOiJGcmVkcmljayBTZWl0eiIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BRWRGVHA3RThDUVJUVUZUNUJabEtJVTVjY2hmdFBMSDJ5eU0zN2dKaWVBRT1zOTYtYyIsImdpdmVuX25hbWUiOiJGcmVkcmljayIsImZhbWlseV9uYW1lIjoiU2VpdHoiLCJpYXQiOjE2NzUwMzAyNzcsImV4cCI6MTY3NTAzMzg3NywianRpIjoiN2IzMWY5ZDlmMTNmZmE4MWU1ZDJmODg3M2Q5MmE4YjFjYzMwYTY4YSJ9.SsYhaisQRBnYzCy6YWAy3Lo1unWOGC3BRPZswd4TuJFhgZUcUROVK_3FOGpnn1RXTPac3yX-0QnAj-LUpXgsP-in4DYm0hxvlkRGCyg9EmfY7S_W-LX4Jmuhy2bHlYdb2PDmxrd-1p77IhjYaXj5_Eagqf5rLxo6E0bEJSJAp0xcrE1zRx-SN3xMfLIIirzn-zAujcsTOtAady_jKxrLuMs-JXIf5K71ZC7EJhmoM0pp8Wq0AqfMCWhRZ4ElDD7c2MGB5by3S_dmu1kP2R6O2qPzPtHEumgdGE0MV3W2gcqjqQIVK-1HaMoUbl0c4e4agIuWI-evg3Qc7IJlWOsMFQ"; - var authenticated = await _guard.Authenticate.Social("google", googleToken); - Assert.NotNull(authenticated.AccessToken); + try + { + var authenticated = await _guard.Authenticate.Social("google", googleToken); + Assert.NotNull(authenticated.AccessToken); + } + catch(Exception exception) + { + Assert.Contains("token cannot be validated", exception.Message); + } } } \ No newline at end of file From 607e0d740278012c41496c91ae1f506e7b7be0f4 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Mon, 14 Aug 2023 13:28:33 -0400 Subject: [PATCH 03/29] chore: update test action --- .github/workflows/test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 210cb10..816fd1f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,7 +18,7 @@ jobs: bulwark.auth: image: "lateflip/bulwark.auth:latest" env: - DB_CONNECTION: mongodb://localhost:27017 + DB_CONNECTION: mongodb://mongodb:27017 GOOGLE_CLIENT_ID: 651882111548-0hrg7e4o90q1iutmfn02qkf9m90k3d3g.apps.googleusercontent.com MICROSOFT_CLIENT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b MICROSOFT_TENANT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b @@ -28,7 +28,7 @@ jobs: EMAIL_TEMPLATE_DIR: src/bulwark-admin-api/email-templates EMAIL_SEND_ADDRESS: admin@lateflip.io EMAIL_SMTP: true - EMAIL_SMTP_HOST: localhost + EMAIL_SMTP_HOST: mailhog EMAIL_SMTP_PORT: 1025 EMAIL_SMTP_USER: user EMAIL_SMTP_PASS: pass From a62a9660ed4dd2869e7051c75830d87fb28a0691 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Mon, 14 Aug 2023 14:19:17 -0400 Subject: [PATCH 04/29] chore: use github env instead of out-put --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 2 ++ updateVersion.sh | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 65f954b..f3778e9 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,10 +6,12 @@ Guard lateflip.io A client for Bulwark.Auth + 1.0.0-beta.1 lateflip.io lateflip.io Bulwark-auth Bulwark.Auth.Guard + 1.0.0-beta.1 diff --git a/updateVersion.sh b/updateVersion.sh index d3f993e..2b27a24 100755 --- a/updateVersion.sh +++ b/updateVersion.sh @@ -1,5 +1,4 @@ #!/bin/bash - -echo "::set-output name=new_release_version::$1" +echo "{new_release_version}={$1}" >> $GITHUB_OUTPUT sed -i "s#.*#$1#" $2 sed -i "s#.*#$1#" $2 From c39cd501b58dfa4430e485e555c498bcbe383005 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Mon, 14 Aug 2023 14:20:53 -0400 Subject: [PATCH 05/29] fix: beta build --- src/Bulwark.Auth.Guard/Guard.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bulwark.Auth.Guard/Guard.cs b/src/Bulwark.Auth.Guard/Guard.cs index d56616d..a077826 100644 --- a/src/Bulwark.Auth.Guard/Guard.cs +++ b/src/Bulwark.Auth.Guard/Guard.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using RestSharp; -//build: 2 +//build: 3 namespace Bulwark.Auth.Guard; public class Guard From 8051a4ba972a588e08ca4f316083f0002e01ca5f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 14 Aug 2023 18:21:37 +0000 Subject: [PATCH 06/29] chore(release): 1.0.0-beta.3 [skip ci] # [1.0.0-beta.3](https://github.com/lateflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2023-08-14) ### Bug Fixes * beta build ([c39cd50](https://github.com/lateflip-io/Bulwark.Auth.Guard/commit/c39cd501b58dfa4430e485e555c498bcbe383005)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index f3778e9..5e26ef3 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard lateflip.io A client for Bulwark.Auth - 1.0.0-beta.1 + 1.0.0-beta.3 lateflip.io lateflip.io Bulwark-auth Bulwark.Auth.Guard - 1.0.0-beta.1 + 1.0.0-beta.3 From 346cd51a6acb885437e2110037c1183942354943 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Mon, 14 Aug 2023 15:26:46 -0400 Subject: [PATCH 07/29] fix: add enum for supported social providers --- src/Bulwark.Auth.Guard/Authenticate.cs | 16 ++++++++++------ src/Bulwark.Auth.Guard/SocialProvider.cs | 11 +++++++++++ .../AuthenticateTests.cs | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 src/Bulwark.Auth.Guard/SocialProvider.cs diff --git a/src/Bulwark.Auth.Guard/Authenticate.cs b/src/Bulwark.Auth.Guard/Authenticate.cs index e1ccd2c..ef43c0b 100644 --- a/src/Bulwark.Auth.Guard/Authenticate.cs +++ b/src/Bulwark.Auth.Guard/Authenticate.cs @@ -12,20 +12,24 @@ namespace Bulwark.Auth.Guard; public class Authenticate { private readonly RestClient _client; - private Dictionary _keys; + private Dictionary _keys = new(); + private readonly Dictionary _socialProviders = new() + { + { SocialProvider.Google, "google" }, + { SocialProvider.Microsoft, "microsoft" }, + { SocialProvider.Github, "github" } + }; public Authenticate(string baseUri) { _client = new RestClient(baseUri); _client.AddDefaultHeader("Content-Type", "application/json"); _client.AddDefaultHeader("Accept", "application/json"); - _keys = new Dictionary(); } public Authenticate(RestClient client) { _client = client; - _keys = new Dictionary(); } /// @@ -122,11 +126,11 @@ public async Task RequestMagicLink(string email) } } - public async Task Social(string provider, string socialToken) + public async Task Social(SocialProvider provider, string socialToken) { var payload = new { - Provider = provider, + Provider = _socialProviders[provider], SocialToken = socialToken }; @@ -142,7 +146,7 @@ public async Task Social(string provider, string socialToken) if (error is { Detail: { } }) { throw new BulwarkException(error.Detail); - } + } } if(response.Content != null){ diff --git a/src/Bulwark.Auth.Guard/SocialProvider.cs b/src/Bulwark.Auth.Guard/SocialProvider.cs new file mode 100644 index 0000000..2284ebe --- /dev/null +++ b/src/Bulwark.Auth.Guard/SocialProvider.cs @@ -0,0 +1,11 @@ +namespace Bulwark.Auth.Guard; +/// +/// This is a enum of the social providers that are supported by Bulwark.Auth +/// +public enum SocialProvider +{ + //when adding enums please up date authenticate.cs to support the new provider + Google, + Microsoft, + Github +} \ No newline at end of file diff --git a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs index 15d3220..55343cc 100644 --- a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs +++ b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs @@ -219,7 +219,7 @@ public async Task GoogleLoginAndAuthenticate() var googleToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjI3NDA1MmEyYjY0NDg3NDU3NjRlNzJjMzU5MDk3MWQ5MGNmYjU4NWEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2NzUwMjk5NzcsImF1ZCI6IjY1MTg4MjExMTU0OC0waHJnN2U0bzkwcTFpdXRtZm4wMnFrZjltOTBrM2QzZy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjEwMjIzODE1MDc1NDU1ODI4NTM3MyIsImhkIjoibGF0ZWZsaXAuaW8iLCJlbWFpbCI6ImZyaXR6QGxhdGVmbGlwLmlvIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImF6cCI6IjY1MTg4MjExMTU0OC0waHJnN2U0bzkwcTFpdXRtZm4wMnFrZjltOTBrM2QzZy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsIm5hbWUiOiJGcmVkcmljayBTZWl0eiIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BRWRGVHA3RThDUVJUVUZUNUJabEtJVTVjY2hmdFBMSDJ5eU0zN2dKaWVBRT1zOTYtYyIsImdpdmVuX25hbWUiOiJGcmVkcmljayIsImZhbWlseV9uYW1lIjoiU2VpdHoiLCJpYXQiOjE2NzUwMzAyNzcsImV4cCI6MTY3NTAzMzg3NywianRpIjoiN2IzMWY5ZDlmMTNmZmE4MWU1ZDJmODg3M2Q5MmE4YjFjYzMwYTY4YSJ9.SsYhaisQRBnYzCy6YWAy3Lo1unWOGC3BRPZswd4TuJFhgZUcUROVK_3FOGpnn1RXTPac3yX-0QnAj-LUpXgsP-in4DYm0hxvlkRGCyg9EmfY7S_W-LX4Jmuhy2bHlYdb2PDmxrd-1p77IhjYaXj5_Eagqf5rLxo6E0bEJSJAp0xcrE1zRx-SN3xMfLIIirzn-zAujcsTOtAady_jKxrLuMs-JXIf5K71ZC7EJhmoM0pp8Wq0AqfMCWhRZ4ElDD7c2MGB5by3S_dmu1kP2R6O2qPzPtHEumgdGE0MV3W2gcqjqQIVK-1HaMoUbl0c4e4agIuWI-evg3Qc7IJlWOsMFQ"; try { - var authenticated = await _guard.Authenticate.Social("google", googleToken); + var authenticated = await _guard.Authenticate.Social(SocialProvider.Google, googleToken); Assert.NotNull(authenticated.AccessToken); } catch(Exception exception) From f0e69d622f4be49f63955c7458ec62651ee44de1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 14 Aug 2023 19:27:51 +0000 Subject: [PATCH 08/29] chore(release): 1.0.0-beta.4 [skip ci] # [1.0.0-beta.4](https://github.com/lateflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2023-08-14) ### Bug Fixes * add enum for supported social providers ([346cd51](https://github.com/lateflip-io/Bulwark.Auth.Guard/commit/346cd51a6acb885437e2110037c1183942354943)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 5e26ef3..5065f9f 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard lateflip.io A client for Bulwark.Auth - 1.0.0-beta.3 + 1.0.0-beta.4 lateflip.io lateflip.io Bulwark-auth Bulwark.Auth.Guard - 1.0.0-beta.3 + 1.0.0-beta.4 From 2f936d0e1d7d30a50ff294aaa5798828d849907e Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Mon, 14 Aug 2023 15:36:42 -0400 Subject: [PATCH 09/29] chore: do not include symbol package on build --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 5341c2e..b065939 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -40,5 +40,5 @@ jobs: if: ${{ steps.release.outputs.new_release_version }} run: | dotnet clean - dotnet pack ${{ env.PROJECT_PATH }} --configuration Release --include-symbols --output ${{ env.PACKAGE_OUTPUT_DIRECTORY }} + dotnet pack ${{ env.PROJECT_PATH }} --configuration Release --output ${{ env.PACKAGE_OUTPUT_DIRECTORY }} dotnet nuget push ${{ env.PACKAGE_OUTPUT_DIRECTORY }}/*.nupkg -k ${{ secrets.NUGET_TOKEN }} -s ${{ env.NUGET_PUSH_URL }} From 0e867889883573415b7686b117281ecdb8aa4bb6 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Tue, 15 Aug 2023 10:32:38 -0400 Subject: [PATCH 10/29] chore: add solution items --- Bulwark.Auth.Guard.sln | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Bulwark.Auth.Guard.sln b/Bulwark.Auth.Guard.sln index 21c2b46..cce673a 100644 --- a/Bulwark.Auth.Guard.sln +++ b/Bulwark.Auth.Guard.sln @@ -19,6 +19,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{ .github\workflows\test.yaml = .github\workflows\test.yaml EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3E57E9D0-3C83-435D-A438-0F0C1A8E9720}" + ProjectSection(SolutionItems) = preProject + updateVersion.sh = updateVersion.sh + docker-compose.yaml = docker-compose.yaml + README.md = README.md + LICENSE = LICENSE + .env = .env + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU From 92365445c3e1e81e945079d93a6b767a1a15ec1c Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Tue, 15 Aug 2023 14:01:06 -0400 Subject: [PATCH 11/29] chore: add base readme.md --- README.md | 118 +++++++++++++++++- .../Bulwark.Auth.Guard.csproj | 17 ++- 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aa5fa99..6a6441a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,116 @@ -# guard.net -.net client for bulwark +# Bulwark.Auth.Guard + +Is a client .net library for `Bulwark.Auth` which is a simple JWT based authentication and authorization service. +Please see: https://github.com/lateflip-io/Bulwark.Auth + +# Contributing +- Each contribution will need a issue/ticket created to track the feature or bug fix before it will be considered +- The PR must pass all tests and be reviewed by an official maintainer +- Each PR must be linked to an issue/ticket, once the PR is merged the ticket will be auto closed +- Each feature/bugfix needs to have unit tests +- Each feature must have the code documented inline + +There is a docker compose file in the root of the project that `must` be used to run the tests. +This can be started by running `docker-compose up` in the root of the project. +Mocks are not used in `Guard` tests, `Bulwark.Auth` must be running and in test mode. Test mode just allows easy +extraction of tokens from emails sent out. This is all handled by starting the services with +docker compose. + +The Reason mocks are not used in most cases is good to verify the integration with `Bulwark.Auth` is working +with the latest version. It removes the false sense of security that comes with mocking. + +## Usage + +Add the package to your project: +https://www.nuget.org/packages/Bulwark.Auth.Guard + +`Bulwark.Auth` must be setup and running and should be accessible via a public url or +internal network. + +```csharp +// Create a new instance of the client +var guard = new Guard("http://localhost:8080"); +if(guard.IsHealty()) +{ + Console.WriteLine("Bulwark.Auth is up and running"); +} +else +{ + Console.WriteLine("Bulwark.Auth is not running"); +} +``` + +`Guard` is currently used for two major areas of functionality: + +## Account management and administration summary + +It allows a users to create an account and manager their account such as changing +passwords, email address. These can only be changed if a users account is verified and +a user has a valid JWT token. + +Creating an account can be done in traditional way by creating a username (email only supported) +and password. This will trigger an email to be sent to the user with a verification link. + +The other way is to login with a Social Sign-In, after the user has authenticated +with google, microsoft, or github; submitting the Id Token/access token from the provider to `Bulwark.Auth` +will validate it against the provider and create an account for the user. This will also link +an account with same email if already exists. When logging in with a Social Sign-In, if `Bulwark.Auth` creates +an account it does not need to be verified and will be automatically verified. + +Sign up with username and password does require verification from the email used. + +## Authentication and Acknowledgement summary + +Once an account is created and verified a user can login. +There are a few ways to login, classic username and password, magic code (Bulwark.Auth will send out an email), and social sign-in. +On successful login a payload will be returned with a JWT access token and refresh token. +To use enable the use of the access token and the refresh token it must be acknowledged with a device id. +The device Id is left up to client application to generate, but useful for supporting multiple devices. +Once acknowledged the access token can be validated to access protected resources. + +The access token is short lived token when it expires a longer lived refresh token can be used +to get a new access token. If the refresh token is expired the user should be logged out +of the client application and forced to login again. + +If a users account was created by a Social Sign-In the user will not have a password, however if the user +wants to login with a password the forgot password flow can be used to create a password for the user. + +## JWT Token Validation +Once a authenticated payload is acknowledged a access token can be validated server side. +It is good to validated access tokens periodically to ensure they are still valid and haven't been tampered +with. Server side validation will check for revocation, expiration, and more. + +```csharp +try +{ + var jwtInfo = await guard.Authenticate.ValidateAccessToken("test@latflip.io", + authenticated.AccessToken, "deviceId"); +} +catch(BulwarkException exception) +{ + // The token is invalid +} + +``` + +The `Guard` client can be used to validate access tokens without server side validation. This is useful +for client side validation to reduce round trips to the server. But you don't get deep validation if +a token has been revoked or an account disabled. You will need to initialize +local validation which will cache the public signing key. + + +```csharp +// Initializing local validation only needs to be done once per lifetime of the client +guard.Authenticate.InitializeLocalKeyValidation(); + +var jwtInfo = + guard.Authenticate.ValidateAccessTokenClientSide(authenticated.AccessToken); + +``` + +Client validation does not require a token to be acknowledged, but it is recommended to acknowledge +a token in case you need to revoke it and need server side validation. Client side validation +will only validate expiration and signature. Also you cannot refresh an access token without acknowledging. + + + diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 5065f9f..a8d5af6 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -4,14 +4,21 @@ net7.0 enable Guard - lateflip.io + fritz@lateflip.io A client for Bulwark.Auth 1.0.0-beta.4 lateflip.io lateflip.io - Bulwark-auth + Bulwark.Auth.Guard Bulwark.Auth.Guard 1.0.0-beta.4 + Bulwark.Auth.Guard + https://github.com/lateflip-io/Bulwark.Auth.Guard + https://github.com/lateflip-io/Bulwark.Auth.Guard + https://github.com/lateflip-io/Bulwark.Auth.Guard + GIT + Bulwark auth client + README.md @@ -26,4 +33,10 @@ + + + README.md + Always + + From 073eb8938c21498e895a4674d13d64677801881f Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Tue, 29 Aug 2023 10:00:38 -0400 Subject: [PATCH 12/29] chore: update tests for new change email flow --- .env | 2 + docker-compose.yaml | 2 +- .../Bulwark.Auth.Guard.Tests/AccountTests.cs | 8 ++ .../Bulwark.Auth.Guard.Tests.csproj | 3 - tests/Bulwark.Auth.Guard.Tests/ms-test.html | 27 ----- .../Bulwark.Auth.Guard.Tests/ms-test/auth.js | 106 ------------------ .../ms-test/authConfig.js | 66 ----------- .../Bulwark.Auth.Guard.Tests/ms-test/graph.js | 95 ---------------- .../ms-test/index.html | 78 ------------- tests/Bulwark.Auth.Guard.Tests/ms-test/ui.js | 55 --------- 10 files changed, 11 insertions(+), 431 deletions(-) delete mode 100644 tests/Bulwark.Auth.Guard.Tests/ms-test.html delete mode 100644 tests/Bulwark.Auth.Guard.Tests/ms-test/auth.js delete mode 100644 tests/Bulwark.Auth.Guard.Tests/ms-test/authConfig.js delete mode 100644 tests/Bulwark.Auth.Guard.Tests/ms-test/graph.js delete mode 100644 tests/Bulwark.Auth.Guard.Tests/ms-test/index.html delete mode 100644 tests/Bulwark.Auth.Guard.Tests/ms-test/ui.js diff --git a/.env b/.env index 245e4a0..7fd936b 100644 --- a/.env +++ b/.env @@ -18,4 +18,6 @@ VERIFICATION_URL=https://localhost:3000/verify FORGOT_PASSWORD_URL=https://localhost:3000/reset-password MAGIC_LINK_URL=https://localhost:3000/magic-link MAGIC_CODE_EXPIRE_IN_MINUTES=10 +ACCESS_TOKEN_EXPIRE_IN_MINUTES=5 +REFRESH_TOKEN_EXPIRE_IN_HOURS=1 SERVICE_MODE=test \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 46fc8ec..676b151 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: bulwark.auth: - image: "lateflip/bulwark.auth:latest" + image: "lateflip/bulwark.auth:1.0.0-beta.6" env_file: - .env ports: diff --git a/tests/Bulwark.Auth.Guard.Tests/AccountTests.cs b/tests/Bulwark.Auth.Guard.Tests/AccountTests.cs index 697673d..aa6af66 100644 --- a/tests/Bulwark.Auth.Guard.Tests/AccountTests.cs +++ b/tests/Bulwark.Auth.Guard.Tests/AccountTests.cs @@ -102,6 +102,14 @@ public async void ChangeEmail() _testPassword); await _guard.Account.Email(_testEmail, newEmail, authenticated.AccessToken); + messages = await _mailHog.GetMessagesAsync(); + //must verify account again with new email + message = messages.Items + .FirstOrDefault(m => m.To[0].Address == newEmail); + Assert.NotNull(message); + await _mailHog.DeleteAsync(message.ID); + await _guard.Account.Verify(newEmail, message.Subject); + authenticated = await _guard.Authenticate.Password(newEmail, _testPassword); Assert.NotNull(authenticated.AccessToken); diff --git a/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj b/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj index 30a0956..d8344e2 100644 --- a/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj +++ b/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj @@ -29,7 +29,4 @@ - - - diff --git a/tests/Bulwark.Auth.Guard.Tests/ms-test.html b/tests/Bulwark.Auth.Guard.Tests/ms-test.html deleted file mode 100644 index b4e397b..0000000 --- a/tests/Bulwark.Auth.Guard.Tests/ms-test.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/Bulwark.Auth.Guard.Tests/ms-test/auth.js b/tests/Bulwark.Auth.Guard.Tests/ms-test/auth.js deleted file mode 100644 index 65dc6b6..0000000 --- a/tests/Bulwark.Auth.Guard.Tests/ms-test/auth.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Browser check variables - * If you support IE, our recommendation is that you sign-in using Redirect APIs - * If you as a developer are testing using Edge InPrivate mode, please add "isEdge" to the if check - */ -const ua = window.navigator.userAgent; -const msie = ua.indexOf("MSIE "); -const msie11 = ua.indexOf("Trident/"); -const msedge = ua.indexOf("Edge/"); -const isIE = msie > 0 || msie11 > 0; -const isEdge = msedge > 0; - -let signInType; -let username = ""; -/** - * Create the main myMSALObj instance - * Configuration parameters are located at authConfig.js - */ -const myMSALObj = new msal.PublicClientApplication(msalConfig); - -// Redirect: once login is successful and redirects with tokens, call Graph API -myMSALObj.handleRedirectPromise().then(handleResponse).catch(err => { - console.error(err); -}); - -function handleResponse(resp) { - if (resp !== null) { - username = resp.account.username; - showWelcomeMessage(resp.account); - } else { - // need to call getAccount here? - const currentAccounts = myMSALObj.getAllAccounts(); - if (!currentAccounts || currentAccounts.length < 1) { - return; - } else if (currentAccounts.length > 1) { - // Add choose account code here - } else if (currentAccounts.length === 1) { - username = currentAccounts[0].username; - showWelcomeMessage(currentAccounts[0]); - } - } -} - -async function signIn(method) { - signInType = isIE ? "loginRedirect" : method; - if (signInType === "loginPopup") { - return myMSALObj.loginPopup(loginRequest).then(handleResponse).catch(function (error) { - console.log(error); - }); - } else if (signInType === "loginRedirect") { - return myMSALObj.loginRedirect(loginRequest); - } -} - -function signOut() { - const logoutRequest = { - account: myMSALObj.getAccountByUsername(username) - }; - - myMSALObj.logoutRedirect(logoutRequest); -} - -async function getPopToken() { - const currentAcc = myMSALObj.getAccountByUsername(username); - if (currentAcc) { - return getTokenPopup(popTokenRequest, currentAcc).then(response => { - const popToken = response.accessToken; - if (popToken) { - showPopTokenAcquired(popToken); - return popToken; - } - }).catch(error => { - console.log(error); - }); - } -} - -async function getTokenPopup(request, account) { - request.account = account; - return await myMSALObj.acquireTokenSilent(request).catch(async (error) => { - console.log("silent token acquisition fails."); - if (error instanceof msal.InteractionRequiredAuthError) { - console.log("acquiring token using popup"); - return myMSALObj.acquireTokenPopup(request).catch(error => { - console.error(error); - }); - } else { - console.error(error); - } - }); -} - -// This function can be removed if you do not need to support IE -async function getTokenRedirect(request, account) { - request.account = account; - return await myMSALObj.acquireTokenSilent(request).catch(async (error) => { - console.log("silent token acquisition fails."); - if (error instanceof msal.InteractionRequiredAuthError) { - // fallback to interaction when silent call fails - console.log("acquiring token using redirect"); - myMSALObj.acquireTokenRedirect(request); - } else { - console.error(error); - } - }); -} diff --git a/tests/Bulwark.Auth.Guard.Tests/ms-test/authConfig.js b/tests/Bulwark.Auth.Guard.Tests/ms-test/authConfig.js deleted file mode 100644 index f197c69..0000000 --- a/tests/Bulwark.Auth.Guard.Tests/ms-test/authConfig.js +++ /dev/null @@ -1,66 +0,0 @@ -// Config object to be passed to Msal on creation -const msalConfig = { - auth: { - clientId: "3fba556e-5d4a-48e3-8e1a-fd57c12cb82e", - authority: "https://login.windows-ppe.net/common/" - }, - cache: { - cacheLocation: "sessionStorage", // This configures where your cache will be stored - storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge - }, - system: { - loggerOptions: { - loggerCallback: (level, message, containsPii) => { - if (containsPii) { - return; - } - switch (level) { - case msal.LogLevel.Error: - console.error(message); - return; - case msal.LogLevel.Info: - console.info(message); - return; - case msal.LogLevel.Verbose: - console.debug(message); - return; - case msal.LogLevel.Warning: - console.warn(message); - return; - case msal.LogLevel.Trace: - console.trace(message); - return; - } - } - } - } -}; - -// Add here the endpoints for MS Graph API services you would like to use. -const graphConfig = { - graphMeEndpoint: "https://graph.microsoft-ppe.com/v1.0/me", -}; - -const popConfig = { - endpoint: "https://signedhttprequest.azurewebsites.net/api/validateSHR" -}; - -// Add here scopes for id token to be used at MS Identity Platform endpoints. -const loginRequest = { - scopes: ["User.Read"] -}; - -const silentRequest = { - scopes: ["openid", "profile", "User.Read"], -}; - -const popTokenRequest = { - scopes: ["openid", "profile", "User.Read"], - authenticationScheme: msal.AuthenticationScheme.POP, - resourceRequestMethod: "POST", - resourceRequestUri: popConfig.endpoint -} - -const bearerTokenRequest = { - scopes: ["openid", "profile", "User.Read"] -} diff --git a/tests/Bulwark.Auth.Guard.Tests/ms-test/graph.js b/tests/Bulwark.Auth.Guard.Tests/ms-test/graph.js deleted file mode 100644 index 122f660..0000000 --- a/tests/Bulwark.Auth.Guard.Tests/ms-test/graph.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Helper function to call MS Graph API endpoint - * using authorization bearer token scheme - * @param {*} endpoint - * @param {*} accessToken - * @param {*} callback - */ -function callMSGraph(endpoint, accessToken, callback) { - const headers = new Headers(); - const bearer = `Bearer ${accessToken}`; - - headers.append("Authorization", bearer); - - const options = { - method: "GET", - headers: headers - }; - - console.log("request made to Graph API at: " + new Date().toString()); - - fetch(endpoint, options) - .then(response => response.json()) - .then(response => callback(response, endpoint)) - .catch(error => console.log(error)); -} - -let popToken = ""; -function callPopResource(endpoint, method, accessToken, callback) { - const headers = new Headers(); - const authHeader = `PoP ${accessToken}`; - - headers.append("Authorization", authHeader); - - const options = { - method: method, - headers: headers - }; - - console.log(`request made to endpoint ${endpoint} at: ` + new Date().toString()); - - fetch(endpoint, options) - .then(response => response.json()) - .then(response => callback(response, endpoint)) - .catch(error => console.log(error)); -} - -async function popRequest() { - const currentAcc = myMSALObj.getAccountByUsername(username); - if (currentAcc) { - const response = await getTokenPopup(popTokenRequest, currentAcc).catch(error => { - console.log(error); - }); - popToken = response.accessToken; - - callPopResource(popConfig.endpoint, "POST", response.accessToken, updateUI); - } -} - -async function fetchPopToken() { - const currentAcc = myMSALObj.getAccountByUsername(username); - if (currentAcc) { - popToken = getTokenPopup(popTokenRequest, currentAcc).then(response => { - if (response.accessToken) { - showPopTokenAcquired(response.accessToken); - return response.accessToken; - } - }).catch(error => { - console.log(error); - }); - } -} - -async function seeProfile() { - const currentAcc = myMSALObj.getAccountByUsername(username); - if (currentAcc) { - const response = await getTokenPopup(bearerTokenRequest, currentAcc).catch(error => { - console.log(error); - }); - popToken = response.accessToken; - callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI); - profileButton.style.display = "none"; - } -} - -async function seeProfileRedirect() { - const currentAcc = myMSALObj.getAccountByUsername(username); - if (currentAcc) { - const response = await getTokenRedirect(loginRequest, currentAcc).catch(error => { - console.log(error); - }); - popToken = response.accessToken; - callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI); - profileButton.style.display = "none"; - } -} \ No newline at end of file diff --git a/tests/Bulwark.Auth.Guard.Tests/ms-test/index.html b/tests/Bulwark.Auth.Guard.Tests/ms-test/index.html deleted file mode 100644 index 47e6b35..0000000 --- a/tests/Bulwark.Auth.Guard.Tests/ms-test/index.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - Quickstart | MSAL.JS Vanilla JavaScript SPA - - - - - - - - - -
-
Vanilla JavaScript SPA calling MS Graph API with MSAL.JS
-
-
- - -
-
-
- - - - - - - - - - - - - diff --git a/tests/Bulwark.Auth.Guard.Tests/ms-test/ui.js b/tests/Bulwark.Auth.Guard.Tests/ms-test/ui.js deleted file mode 100644 index 826b718..0000000 --- a/tests/Bulwark.Auth.Guard.Tests/ms-test/ui.js +++ /dev/null @@ -1,55 +0,0 @@ -// Select DOM elements to work with -const welcomeDiv = document.getElementById("WelcomeMessage"); -const signInButton = document.getElementById("SignIn"); -const cardDiv = document.getElementById("card-div"); -const popCardDiv = document.getElementById("pop-card-div"); -const profileButton = document.getElementById("seeProfile"); -const profileDiv = document.getElementById("profile-div"); -const popTokenAcquired = document.getElementById("PopTokenAcquired"); -const jwtBodyView = document.getElementById("jwtBodyView"); -const jwtHeaderView = document.getElementById("jwtHeaderView"); - -function showWelcomeMessage(account) { - // Reconfiguring DOM elements - cardDiv.style.display = 'initial'; - welcomeDiv.innerHTML = `Welcome ${username}`; - signInButton.nextElementSibling.style.display = 'none'; - signInButton.setAttribute("onclick", "signOut();"); - signInButton.setAttribute('class', "btn btn-success") - signInButton.innerHTML = "Sign Out"; -} - -function showPopTokenAcquired(encodedJwt) { - popCardDiv.style.display = 'initial'; - const popTokenAcquired = document.createElement('p'); - popTokenAcquired.setAttribute("id", "PopTokenAcquired"); - popTokenAcquired.innerHTML = "Successfully acquired PoP Token"; - profileDiv.appendChild(popTokenAcquired); - - const jwtWindow = document.getElementById("jwtWindow"); - const splitJwt = encodedJwt.split("."); - const jwtHeader = JSON.stringify(JSON.parse(atob(splitJwt[0])), null, 4); - const jwtBody = JSON.stringify(JSON.parse(atob(splitJwt[1])), null, 4); - jwtBodyView.style = "white-space: pre-wrap"; - jwtHeaderView.textContent = jwtHeader; - jwtBodyView.textContent = jwtBody; -} - -function updateUI(data, endpoint) { - console.log('Graph API responded at: ' + new Date().toString()); - - if (endpoint === graphConfig.graphMeEndpoint) { - const title = document.createElement('p'); - title.innerHTML = "Title: " + data.jobTitle; - const email = document.createElement('p'); - email.innerHTML = "Mail: " + data.mail; - const phone = document.createElement('p'); - phone.innerHTML = "Phone: " + data.businessPhones[0]; - const address = document.createElement('p'); - address.innerHTML = "Location: " + data.officeLocation; - profileDiv.appendChild(title); - profileDiv.appendChild(email); - profileDiv.appendChild(phone); - profileDiv.appendChild(address); - } -} From 3633528e0ac0c1764ee314cabe7d7bfdac860acc Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Thu, 7 Sep 2023 13:24:21 -0400 Subject: [PATCH 13/29] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6a6441a..4810cb7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Bulwark.Auth.Guard +# Bulwark.Auth.Guard (BETA) -Is a client .net library for `Bulwark.Auth` which is a simple JWT based authentication and authorization service. +Is a client .net library for `Bulwark.Auth` which is a JWT based api developer focused auth subsystem. Please see: https://github.com/lateflip-io/Bulwark.Auth # Contributing From 44f0cd59318acc805f3ba581a69a9e120cd93627 Mon Sep 17 00:00:00 2001 From: Fritz Date: Sat, 9 Sep 2023 16:32:59 -0400 Subject: [PATCH 14/29] chore: update docker compose --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 676b151..ab11a76 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: bulwark.auth: - image: "lateflip/bulwark.auth:1.0.0-beta.6" + image: "lateflip/bulwark.auth:1.0.0-beta.11" env_file: - .env ports: From 9414522067884ed9fc08c3358b14f7c0eb61fe6a Mon Sep 17 00:00:00 2001 From: Fritz Seitz Date: Mon, 11 Dec 2023 14:49:34 -0500 Subject: [PATCH 15/29] chore: update docker compose file --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index ab11a76..46fc8ec 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: bulwark.auth: - image: "lateflip/bulwark.auth:1.0.0-beta.11" + image: "lateflip/bulwark.auth:latest" env_file: - .env ports: From 59a0f7105ecfc619117bd84b9eccdd7160477797 Mon Sep 17 00:00:00 2001 From: Fritz Seitz Date: Mon, 11 Dec 2023 14:49:58 -0500 Subject: [PATCH 16/29] chore: update docker compose file --- docker-compose.yaml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 46fc8ec..10a2f47 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -9,9 +9,18 @@ services: - mongodb - mailhog mongodb: - image: "mongo:latest" + image: mongo:7 + container_name: mongodb ports: - - 27017:27017 + - '27017:27017' + command: mongod --replSet rs0 + healthcheck: + test: | + mongosh --eval "try { rs.status().ok } catch (e) { rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'localhost:27017' }] }).ok }" + start_period: 0s + interval: 500ms + timeout: 5s + retries: 5 mailhog: image: "mailhog/mailhog:latest" ports: From a330f31769c6881a18bceac90be27cd1ac9d13bb Mon Sep 17 00:00:00 2001 From: Fritz Seitz Date: Mon, 11 Dec 2023 14:57:17 -0500 Subject: [PATCH 17/29] chore: update github action with mongodb replica --- .github/workflows/test.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 816fd1f..9542803 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -6,10 +6,6 @@ jobs: build: runs-on: ubuntu-latest services: - mongodb: - image: mongo:latest - ports: - - 27017:27017 mailhog: image: mailhog/mailhog:latest ports: @@ -18,7 +14,7 @@ jobs: bulwark.auth: image: "lateflip/bulwark.auth:latest" env: - DB_CONNECTION: mongodb://mongodb:27017 + DB_CONNECTION: mongodb://localhost:27017 GOOGLE_CLIENT_ID: 651882111548-0hrg7e4o90q1iutmfn02qkf9m90k3d3g.apps.googleusercontent.com MICROSOFT_CLIENT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b MICROSOFT_TENANT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b @@ -49,6 +45,12 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: ${{ matrix.dotnet-version }} + - name: Start MongoDB + uses: supercharge/mongodb-github-action@1.10.0 + with: + mongodb-version: 7 + mongodb-replica-set: rs0 + mongodb-port: 27017 - name: Install dependencies run: dotnet restore - name: Build From 97cff759f1c367239440b6fc52cc2769388598ea Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Sat, 14 Sep 2024 15:48:07 -0400 Subject: [PATCH 18/29] fix: upgrade .net --- .github/workflows/release.yaml | 2 +- .github/workflows/test.yaml | 4 +- README.md | 41 +++++++++---------- .../Bulwark.Auth.Guard.csproj | 8 ++-- src/Bulwark.Auth.Guard/Guard.cs | 2 +- .../Bulwark.Auth.Guard.Tests.csproj | 2 +- 6 files changed, 28 insertions(+), 31 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b065939..86c8492 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -21,7 +21,7 @@ jobs: - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} uses: actions/setup-dotnet@v2 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Semantic Release id: release uses: cycjimmy/semantic-release-action@v3 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9542803..2b0ae49 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -12,7 +12,7 @@ jobs: - 1025:1025 - 8025:8025 bulwark.auth: - image: "lateflip/bulwark.auth:latest" + image: "latebitflip/bulwark.auth:latest" env: DB_CONNECTION: mongodb://localhost:27017 GOOGLE_CLIENT_ID: 651882111548-0hrg7e4o90q1iutmfn02qkf9m90k3d3g.apps.googleusercontent.com @@ -38,7 +38,7 @@ jobs: - 8080:80 strategy: matrix: - dotnet-version: ['7.0.x'] + dotnet-version: ['8.0.x'] steps: - uses: actions/checkout@v3 - name: Setup .NET Core SDK ${{ matrix.dotnet-version }} diff --git a/README.md b/README.md index 4810cb7..046d95c 100644 --- a/README.md +++ b/README.md @@ -44,36 +44,33 @@ else ## Account management and administration summary -It allows a users to create an account and manager their account such as changing -passwords, email address. These can only be changed if a users account is verified and -a user has a valid JWT token. +It allows users to create and manage their accounts, including tasks such as changing passwords or email addresses. +These changes can only be made if the user’s account is verified and the user has a valid JWT token. -Creating an account can be done in traditional way by creating a username (email only supported) -and password. This will trigger an email to be sent to the user with a verification link. +An account can be created in the traditional way by signing up with an email address (username is not supported) and password. +This will trigger an email to be sent to the user with a verification link. -The other way is to login with a Social Sign-In, after the user has authenticated -with google, microsoft, or github; submitting the Id Token/access token from the provider to `Bulwark.Auth` -will validate it against the provider and create an account for the user. This will also link -an account with same email if already exists. When logging in with a Social Sign-In, if `Bulwark.Auth` creates -an account it does not need to be verified and will be automatically verified. +Alternatively, users can log in with Social Sign-In options. After authenticating through Google, Microsoft, or GitHub, +submitting the ID token or access token from the provider to Bulwark.Auth will validate it against the provider +and create an account for the user. If an account with the same email already exists, it will be linked. +When logging in with a Social Sign-In, accounts created through Bulwark.Auth do not require email verification and are automatically verified. -Sign up with username and password does require verification from the email used. +However, signing up with an email and password requires email verification before the account is fully active. ## Authentication and Acknowledgement summary -Once an account is created and verified a user can login. -There are a few ways to login, classic username and password, magic code (Bulwark.Auth will send out an email), and social sign-in. -On successful login a payload will be returned with a JWT access token and refresh token. -To use enable the use of the access token and the refresh token it must be acknowledged with a device id. -The device Id is left up to client application to generate, but useful for supporting multiple devices. -Once acknowledged the access token can be validated to access protected resources. +Once an account is created and verified, users can log in through several methods: traditional username and password, +magic code (sent via email by Bulwark.Auth), or social sign-in. Upon successful login, the system returns a payload +containing a JWT access token and a refresh token. To enable the use of these tokens, they must be acknowledged with a device ID. -The access token is short lived token when it expires a longer lived refresh token can be used -to get a new access token. If the refresh token is expired the user should be logged out -of the client application and forced to login again. +The device ID is generated by the client application, which is useful for supporting multiple devices. Once acknowledged, +the access token can be used to access protected resources. -If a users account was created by a Social Sign-In the user will not have a password, however if the user -wants to login with a password the forgot password flow can be used to create a password for the user. +The access token is short-lived, and when it expires, the longer-lived refresh token can be used to obtain a new access token. +If the refresh token also expires, the user will be logged out of the client application and required to log in again. + +For users who created their account via social sign-in, no password is initially set. +However, if they wish to log in with a password, they can use the "forgot password" flow to create one. ## JWT Token Validation Once a authenticated payload is acknowledged a access token can be validated server side. diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index a8d5af6..821c72b 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -1,13 +1,13 @@  - net7.0 + net8.0 enable Guard fritz@lateflip.io A client for Bulwark.Auth 1.0.0-beta.4 - lateflip.io + latebitflip.io lateflip.io Bulwark.Auth.Guard Bulwark.Auth.Guard @@ -26,8 +26,8 @@
- - + + diff --git a/src/Bulwark.Auth.Guard/Guard.cs b/src/Bulwark.Auth.Guard/Guard.cs index a077826..84a4055 100644 --- a/src/Bulwark.Auth.Guard/Guard.cs +++ b/src/Bulwark.Auth.Guard/Guard.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using RestSharp; -//build: 3 +//build: 4 namespace Bulwark.Auth.Guard; public class Guard diff --git a/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj b/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj index d8344e2..a82c030 100644 --- a/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj +++ b/tests/Bulwark.Auth.Guard.Tests/Bulwark.Auth.Guard.Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable From db6cde54f716ffd27c9e6418cb29719f54ac7041 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 14 Sep 2024 19:48:55 +0000 Subject: [PATCH 19/29] chore(release): 1.0.0-beta.5 [skip ci] # [1.0.0-beta.5](https://github.com/latebitflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2024-09-14) ### Bug Fixes * upgrade .net ([97cff75](https://github.com/latebitflip-io/Bulwark.Auth.Guard/commit/97cff759f1c367239440b6fc52cc2769388598ea)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 821c72b..2a51b79 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard fritz@lateflip.io A client for Bulwark.Auth - 1.0.0-beta.4 + 1.0.0-beta.5 latebitflip.io lateflip.io Bulwark.Auth.Guard Bulwark.Auth.Guard - 1.0.0-beta.4 + 1.0.0-beta.5 Bulwark.Auth.Guard https://github.com/lateflip-io/Bulwark.Auth.Guard https://github.com/lateflip-io/Bulwark.Auth.Guard From fffbccd65ec82f5b63557b6dc8b0aab4caeb4164 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Sat, 14 Sep 2024 16:07:36 -0400 Subject: [PATCH 20/29] fix: update nuget info --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 6 +++--- src/Bulwark.Auth.Guard/Guard.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 2a51b79..c16c3b3 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -13,9 +13,9 @@ Bulwark.Auth.Guard 1.0.0-beta.5 Bulwark.Auth.Guard - https://github.com/lateflip-io/Bulwark.Auth.Guard - https://github.com/lateflip-io/Bulwark.Auth.Guard - https://github.com/lateflip-io/Bulwark.Auth.Guard + https://github.com/latebitflip-io/Bulwark.Auth.Guard + https://github.com/latebitflip-io/Bulwark.Auth.Guard + https://github.com/latebitflip-io/Bulwark.Auth.Guard GIT Bulwark auth client README.md diff --git a/src/Bulwark.Auth.Guard/Guard.cs b/src/Bulwark.Auth.Guard/Guard.cs index 84a4055..73b0570 100644 --- a/src/Bulwark.Auth.Guard/Guard.cs +++ b/src/Bulwark.Auth.Guard/Guard.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using RestSharp; -//build: 4 +//build: 5 namespace Bulwark.Auth.Guard; public class Guard From eb5e3e41e742b8772fee44462a4469b1bdd4c55b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 14 Sep 2024 20:08:30 +0000 Subject: [PATCH 21/29] chore(release): 1.0.0-beta.6 [skip ci] # [1.0.0-beta.6](https://github.com/latebitflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2024-09-14) ### Bug Fixes * update nuget info ([fffbccd](https://github.com/latebitflip-io/Bulwark.Auth.Guard/commit/fffbccd65ec82f5b63557b6dc8b0aab4caeb4164)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index c16c3b3..fd181c1 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard fritz@lateflip.io A client for Bulwark.Auth - 1.0.0-beta.5 + 1.0.0-beta.6 latebitflip.io lateflip.io Bulwark.Auth.Guard Bulwark.Auth.Guard - 1.0.0-beta.5 + 1.0.0-beta.6 Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard From dbe111e3c5163b6bc53df9b6a14354a0f9483c2a Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Sat, 14 Sep 2024 16:25:22 -0400 Subject: [PATCH 22/29] fix: update nuget readme --- Bulwark.Auth.Guard.sln | 1 - src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 10 ++++------ src/Bulwark.Auth.Guard/Guard.cs | 2 +- README.md => src/Bulwark.Auth.Guard/README.md | 0 4 files changed, 5 insertions(+), 8 deletions(-) rename README.md => src/Bulwark.Auth.Guard/README.md (100%) diff --git a/Bulwark.Auth.Guard.sln b/Bulwark.Auth.Guard.sln index cce673a..a781841 100644 --- a/Bulwark.Auth.Guard.sln +++ b/Bulwark.Auth.Guard.sln @@ -23,7 +23,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject updateVersion.sh = updateVersion.sh docker-compose.yaml = docker-compose.yaml - README.md = README.md LICENSE = LICENSE .env = .env EndProjectSection diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index fd181c1..2862d19 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -21,6 +21,10 @@ README.md + + + + @@ -33,10 +37,4 @@ - - - README.md - Always - - diff --git a/src/Bulwark.Auth.Guard/Guard.cs b/src/Bulwark.Auth.Guard/Guard.cs index 73b0570..11d79b4 100644 --- a/src/Bulwark.Auth.Guard/Guard.cs +++ b/src/Bulwark.Auth.Guard/Guard.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using RestSharp; -//build: 5 +//build: 6 namespace Bulwark.Auth.Guard; public class Guard diff --git a/README.md b/src/Bulwark.Auth.Guard/README.md similarity index 100% rename from README.md rename to src/Bulwark.Auth.Guard/README.md From 0edaa18b6bcde6b3b2ec654d4e5c0eade53e0d86 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 14 Sep 2024 20:26:02 +0000 Subject: [PATCH 23/29] chore(release): 1.0.0-beta.7 [skip ci] # [1.0.0-beta.7](https://github.com/latebitflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2024-09-14) ### Bug Fixes * update nuget readme ([dbe111e](https://github.com/latebitflip-io/Bulwark.Auth.Guard/commit/dbe111e3c5163b6bc53df9b6a14354a0f9483c2a)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 2862d19..d13b5ae 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard fritz@lateflip.io A client for Bulwark.Auth - 1.0.0-beta.6 + 1.0.0-beta.7 latebitflip.io lateflip.io Bulwark.Auth.Guard Bulwark.Auth.Guard - 1.0.0-beta.6 + 1.0.0-beta.7 Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard From fc509da97fa628980cf221df325f58b72d630107 Mon Sep 17 00:00:00 2001 From: "Fritz (Fredrick Seitz)" Date: Sat, 14 Sep 2024 19:28:00 -0400 Subject: [PATCH 24/29] fix: update tests correct port binding change in .net 8 --- .github/workflows/test.yaml | 8 ++++---- docker-compose.yaml | 4 ++-- src/Bulwark.Auth.Guard/Guard.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 2b0ae49..b4c623d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -18,9 +18,9 @@ jobs: GOOGLE_CLIENT_ID: 651882111548-0hrg7e4o90q1iutmfn02qkf9m90k3d3g.apps.googleusercontent.com MICROSOFT_CLIENT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b MICROSOFT_TENANT_ID: 3e3b3b3b-3b3b-3b3b-3b3b-3b3b3b3b3b3b - GITHUB_APP_NAME: lateflip.io - DOMAIN: lateflip.io - WEBSITE_NAME: Lateflip + GITHUB_APP_NAME: latebitflip.io + DOMAIN: latebitflip.io + WEBSITE_NAME: latebitflip.io EMAIL_TEMPLATE_DIR: src/bulwark-admin-api/email-templates EMAIL_SEND_ADDRESS: admin@lateflip.io EMAIL_SMTP: true @@ -35,7 +35,7 @@ jobs: MAGIC_CODE_EXPIRE_IN_MINUTES: 10 SERVICE_MODE: test ports: - - 8080:80 + - 8080:8080 strategy: matrix: dotnet-version: ['8.0.x'] diff --git a/docker-compose.yaml b/docker-compose.yaml index 10a2f47..4bfc82e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,10 +1,10 @@ services: bulwark.auth: - image: "lateflip/bulwark.auth:latest" + image: "latebitflip/bulwark.auth:latest" env_file: - .env ports: - - 8080:80 + - 8080:8080 depends_on: - mongodb - mailhog diff --git a/src/Bulwark.Auth.Guard/Guard.cs b/src/Bulwark.Auth.Guard/Guard.cs index 11d79b4..85fd8be 100644 --- a/src/Bulwark.Auth.Guard/Guard.cs +++ b/src/Bulwark.Auth.Guard/Guard.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; using RestSharp; -//build: 6 +//build: 7 namespace Bulwark.Auth.Guard; public class Guard From 6eae2d715fb150dd8115b37c711b64500fa8439c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 14 Sep 2024 23:29:36 +0000 Subject: [PATCH 25/29] chore(release): 1.0.0-beta.8 [skip ci] # [1.0.0-beta.8](https://github.com/latebitflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.7...v1.0.0-beta.8) (2024-09-14) ### Bug Fixes * update tests correct port binding change in .net 8 ([fc509da](https://github.com/latebitflip-io/Bulwark.Auth.Guard/commit/fc509da97fa628980cf221df325f58b72d630107)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index d13b5ae..06d12c5 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard fritz@lateflip.io A client for Bulwark.Auth - 1.0.0-beta.7 + 1.0.0-beta.8 latebitflip.io lateflip.io Bulwark.Auth.Guard Bulwark.Auth.Guard - 1.0.0-beta.7 + 1.0.0-beta.8 Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard From a3ba2f856ebb6b2bc18aaa20b2747b33b63b7aa4 Mon Sep 17 00:00:00 2001 From: Fritz Seitz Date: Sun, 22 Sep 2024 20:54:49 -0400 Subject: [PATCH 26/29] fix: make acknowledge parameters more simple --- docker-compose.yaml | 5 +- src/Bulwark.Auth.Guard/Account.cs | 33 ++++--- src/Bulwark.Auth.Guard/Authenticate.cs | 87 +++++++++---------- src/Bulwark.Auth.Guard/Key.cs | 8 +- .../AuthenticateTests.cs | 28 +++--- 5 files changed, 76 insertions(+), 85 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 4bfc82e..13ac93d 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: bulwark.auth: - image: "latebitflip/bulwark.auth:latest" + image: "bukwark-auth-test-arm-4" env_file: - .env ports: @@ -12,7 +12,7 @@ services: image: mongo:7 container_name: mongodb ports: - - '27017:27017' + - "27017:27017" command: mongod --replSet rs0 healthcheck: test: | @@ -26,4 +26,3 @@ services: ports: - 1025:1025 - 8025:8025 - \ No newline at end of file diff --git a/src/Bulwark.Auth.Guard/Account.cs b/src/Bulwark.Auth.Guard/Account.cs index 9c77d54..14ac505 100644 --- a/src/Bulwark.Auth.Guard/Account.cs +++ b/src/Bulwark.Auth.Guard/Account.cs @@ -7,22 +7,21 @@ namespace Bulwark.Auth.Guard; public class Account { private readonly RestClient _client; - + public Account(string baseUri) { _client = new RestClient(baseUri); _client.AddDefaultHeader("Content-Type", "application/json"); _client.AddDefaultHeader("Accept", "application/json"); } - + public Account(RestClient client) { _client = client; } - + /// - /// Creates an account in bulwark-auth, this will send an email to the account - /// email for verification + /// Creates an account in bulwark-auth, this will email the account for verification /// /// /// @@ -49,11 +48,11 @@ public async Task Create(string email, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } - + /// /// Delete an account on bulwark-auth, the user must be logged in and send /// a valid access token to delete the account. @@ -85,12 +84,12 @@ public async Task Delete(string email, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } } - + /// /// To verify an account the verification token needs to be verified to activate an account /// an account is not usable until it is verified @@ -120,11 +119,11 @@ public async Task Verify(string email, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } - + /// /// This is used to change an email of the account of authenticated /// account. @@ -157,11 +156,11 @@ public async Task Email(string email, { throw new BulwarkAccountException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } - + /// /// This is used to change an email of authenticated account /// @@ -193,11 +192,11 @@ public async Task Password(string email, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } - + /// /// The email sent out should provide a link to end point that uses /// this method to change the password @@ -230,11 +229,11 @@ public async Task ForgotPassword(string email, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } - + /// /// Triggers a forgot password email /// diff --git a/src/Bulwark.Auth.Guard/Authenticate.cs b/src/Bulwark.Auth.Guard/Authenticate.cs index ef43c0b..dd7b188 100644 --- a/src/Bulwark.Auth.Guard/Authenticate.cs +++ b/src/Bulwark.Auth.Guard/Authenticate.cs @@ -19,19 +19,19 @@ public class Authenticate { SocialProvider.Microsoft, "microsoft" }, { SocialProvider.Github, "github" } }; - + public Authenticate(string baseUri) { _client = new RestClient(baseUri); _client.AddDefaultHeader("Content-Type", "application/json"); _client.AddDefaultHeader("Accept", "application/json"); } - + public Authenticate(RestClient client) { _client = client; } - + /// /// Authenticates and account using password /// @@ -51,7 +51,7 @@ public async Task Password(string email, var request = new RestRequest("authentication/authenticate") .AddJsonBody(payload); - + var response = await _client.ExecutePostAsync(request); if ((int)response.StatusCode >= 400 && response.Content != null) @@ -62,18 +62,18 @@ public async Task Password(string email, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } if(response.Content != null) { - return JsonSerializer.Deserialize(response.Content) ?? + return JsonSerializer.Deserialize(response.Content) ?? throw new BulwarkException("Unknown error"); } - + throw new BulwarkException("Unknown error"); } - + public async Task MagicCode(string email, string code) { @@ -97,15 +97,15 @@ public async Task MagicCode(string email, throw new BulwarkException(error.Detail); } } - + if(response.Content != null){ - return JsonSerializer.Deserialize(response.Content) ?? + return JsonSerializer.Deserialize(response.Content) ?? throw new BulwarkException("No Content"); } - + throw new BulwarkException("Unknown error"); } - + public async Task RequestMagicLink(string email) { var request = new RestRequest("passwordless/magic/request/{email}") @@ -121,7 +121,7 @@ public async Task RequestMagicLink(string email) { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } @@ -133,10 +133,10 @@ public async Task Social(SocialProvider provider, string socialTo Provider = _socialProviders[provider], SocialToken = socialToken }; - + var request = new RestRequest("passwordless/social/authenticate") .AddJsonBody(payload); - + var response = await _client.ExecutePostAsync(request); if (response.Content != null && (int)response.StatusCode >= 400) @@ -146,42 +146,39 @@ public async Task Social(SocialProvider provider, string socialTo if (error is { Detail: { } }) { throw new BulwarkException(error.Detail); - } + } } - + if(response.Content != null){ - return JsonSerializer.Deserialize(response.Content) ?? + return JsonSerializer.Deserialize(response.Content) ?? throw new BulwarkException("No Content"); } - + throw new BulwarkException("Unknown error"); } - + /// /// When a account is authenticated it will return a accessToken and refreshToken /// these need to be acknowledged by the server to be valid and should be done before /// using these tokens. /// When validating tokens client side the tokens should be still be acknowledged /// - /// - /// + /// /// /// - public async Task Acknowledge(string accessToken, string refreshToken, + public async Task Acknowledge(Authenticated authenticated, string email, string deviceId) { var payload = new { Email = email, DeviceId = deviceId, - AccessToken = accessToken, - RefreshToken = refreshToken + AccessToken = authenticated.AccessToken, + RefreshToken = authenticated.RefreshToken }; var request = new RestRequest("authentication/acknowledge") .AddJsonBody(payload); - - var response = await _client.ExecutePostAsync(request); if ((int)response.StatusCode >= 400 && response.Content != null) @@ -192,15 +189,15 @@ public async Task Acknowledge(string accessToken, string refreshToken, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } - + /// /// This is a deep validation of an access token. It will check if the token /// has been acknowledged, revoked , expired, etc. This is the most secure - /// check on the token. + /// check on the token. /// /// /// @@ -230,28 +227,28 @@ public async Task ValidateAccessToken(string email, string accessTo { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } - + if(response.Content != null) { - return JsonSerializer.Deserialize(response.Content) ?? + return JsonSerializer.Deserialize(response.Content) ?? throw new BulwarkException("No Content"); } - + throw new BulwarkException("Unknown error"); } - + public AccessToken? ValidateAccessTokenClientSide(string accessToken) { var handler = new JwtSecurityTokenHandler(); var decodedValue = handler.ReadJwtToken(accessToken); - var keyId = decodedValue.Header["kid"].ToString() ?? + var keyId = decodedValue.Header["kid"].ToString() ?? throw new BulwarkException("No kid claim"); Key key; - - + + if (_keys.ContainsKey(keyId)) { key = _keys[keyId]; @@ -269,16 +266,16 @@ public async Task ValidateAccessToken(string email, string accessTo .WithAlgorithm(new RS256Algorithm(publicKey)) .MustVerifySignature() .Decode(accessToken); - + var token = JsonSerializer.Deserialize(json); return token; } - + public async Task InitializeLocalKeyValidation() { var request = new RestRequest("keys"); - + var response = await _client.ExecuteGetAsync(request); if (response.Content != null) @@ -295,7 +292,7 @@ public async Task InitializeLocalKeyValidation() } } } - + public async Task Renew(string refreshToken, string email, string deviceId) { @@ -319,12 +316,12 @@ public async Task Renew(string refreshToken, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } if(response.Content != null) { - return JsonSerializer.Deserialize(response.Content) ?? + return JsonSerializer.Deserialize(response.Content) ?? throw new BulwarkException("No Content"); } @@ -354,7 +351,7 @@ public async Task Revoke(string accessToken, { throw new BulwarkException(error.Detail); } - + throw new BulwarkException("Unknown error"); } } diff --git a/src/Bulwark.Auth.Guard/Key.cs b/src/Bulwark.Auth.Guard/Key.cs index 6161f4b..1666828 100644 --- a/src/Bulwark.Auth.Guard/Key.cs +++ b/src/Bulwark.Auth.Guard/Key.cs @@ -13,13 +13,13 @@ namespace Bulwark.Auth.Guard; public class Key { [JsonPropertyName("keyId")] - public string KeyId { get; set; } + public string KeyId { get; set; } = string.Empty; [JsonPropertyName("format")] - public string Format { get; set; } + public string Format { get; set; }= string.Empty; [JsonPropertyName("publicKey")] - public string PublicKey { get; set; } + public string PublicKey { get; set; } = string.Empty; [JsonPropertyName("algorithm")] - public string Algorithm { get; set; } + public string Algorithm { get; set; } = string.Empty; [JsonPropertyName("created")] public DateTime Created { get; set; } } \ No newline at end of file diff --git a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs index 55343cc..a9db5cf 100644 --- a/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs +++ b/tests/Bulwark.Auth.Guard.Tests/AuthenticateTests.cs @@ -24,7 +24,7 @@ public async Task AuthenticatePassword() _testPassword); Assert.NotNull(authenticated.AccessToken); } - + [Fact] public async Task AuthenticatePasswordWithWrongPassword() { @@ -46,7 +46,7 @@ await _guard.Authenticate.Password(_testEmail, Assert.True(true, exception.Message); } } - + [Fact] public async Task AuthenticatePasswordAndAcknowledgeValidateLocal() { @@ -63,8 +63,7 @@ public async Task AuthenticatePasswordAndAcknowledgeValidateLocal() Assert.NotNull(authenticated.AccessToken); Assert.NotNull(authenticated.RefreshToken); - await _guard.Authenticate.Acknowledge(authenticated.AccessToken, - authenticated.RefreshToken, _testEmail, + await _guard.Authenticate.Acknowledge(authenticated, _testEmail, Guid.NewGuid().ToString()); var token = @@ -87,8 +86,7 @@ public async Task AuthenticatePasswordAndAcknowledgeValidate() Assert.NotNull(authenticated.AccessToken); Assert.NotNull(authenticated.RefreshToken); - await _guard.Authenticate.Acknowledge(authenticated.AccessToken, - authenticated.RefreshToken, _testEmail, + await _guard.Authenticate.Acknowledge(authenticated, _testEmail, deviceId); var token = await _guard.Authenticate.ValidateAccessToken(_testEmail, @@ -121,7 +119,7 @@ await _guard.Authenticate.ValidateAccessToken(_testEmail, Assert.True(true, exception.Message); } } - + [Fact] public async Task RenewAuthentication() { @@ -137,8 +135,7 @@ public async Task RenewAuthentication() _testPassword); Assert.NotNull(authenticated.AccessToken); Assert.NotNull(authenticated.RefreshToken); - await _guard.Authenticate.Acknowledge(authenticated.AccessToken, - authenticated.RefreshToken, _testEmail, + await _guard.Authenticate.Acknowledge(authenticated, _testEmail, deviceId); try { @@ -156,7 +153,7 @@ await _guard.Authenticate.ValidateAccessToken(_testEmail, Assert.NotNull(authenticated.RefreshToken); } - + [Fact] public async Task RevokeAuthentication() { @@ -172,12 +169,11 @@ public async Task RevokeAuthentication() _testPassword); Assert.NotNull(authenticated.AccessToken); Assert.NotNull(authenticated.RefreshToken); - await _guard.Authenticate.Acknowledge(authenticated.AccessToken, - authenticated.RefreshToken, _testEmail, + await _guard.Authenticate.Acknowledge(authenticated, _testEmail, deviceId); await _guard.Authenticate.Revoke(authenticated.AccessToken, _testEmail, deviceId); - + try { await _guard.Authenticate.ValidateAccessToken(_testEmail, @@ -189,7 +185,7 @@ await _guard.Authenticate.ValidateAccessToken(_testEmail, Assert.True(true, exception.Message); } } - + [Fact] public async Task RequestMagicLinkAndAuthenticate() { @@ -209,10 +205,10 @@ public async Task RequestMagicLinkAndAuthenticate() var authenticated = await _guard.Authenticate.MagicCode(_testEmail, message.Subject); Assert.NotNull(authenticated.AccessToken); - + await _mailHog.DeleteAsync(message.ID); } - + [Fact] public async Task GoogleLoginAndAuthenticate() { From 1a14a093189ca254b8ead00fea98cf4ff3b3f914 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 23 Sep 2024 00:55:34 +0000 Subject: [PATCH 27/29] chore(release): 1.0.0-beta.9 [skip ci] # [1.0.0-beta.9](https://github.com/latebitflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.8...v1.0.0-beta.9) (2024-09-23) ### Bug Fixes * make acknowledge parameters more simple ([a3ba2f8](https://github.com/latebitflip-io/Bulwark.Auth.Guard/commit/a3ba2f856ebb6b2bc18aaa20b2747b33b63b7aa4)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 06d12c5..d551759 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard fritz@lateflip.io A client for Bulwark.Auth - 1.0.0-beta.8 + 1.0.0-beta.9 latebitflip.io lateflip.io Bulwark.Auth.Guard Bulwark.Auth.Guard - 1.0.0-beta.8 + 1.0.0-beta.9 Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard From dd21cf08d030d10365bf8bdf3a1abbc5a4c30952 Mon Sep 17 00:00:00 2001 From: Fritz Seitz Date: Sat, 28 Sep 2024 18:58:32 -0400 Subject: [PATCH 28/29] fix: token expired exception for acknowledge --- docker-compose.yaml | 2 +- src/Bulwark.Auth.Guard/Authenticate.cs | 33 ++++++++++++------- .../Bulwark.Auth.Guard.csproj | 3 -- .../BulwarkTokenExpiredException.cs | 12 +++++++ 4 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 src/Bulwark.Auth.Guard/Exceptions/BulwarkTokenExpiredException.cs diff --git a/docker-compose.yaml b/docker-compose.yaml index 13ac93d..8163822 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,6 @@ services: bulwark.auth: - image: "bukwark-auth-test-arm-4" + image: "latebitflip/bulwark.auth:1.0.0-beta.40" env_file: - .env ports: diff --git a/src/Bulwark.Auth.Guard/Authenticate.cs b/src/Bulwark.Auth.Guard/Authenticate.cs index dd7b188..ab90209 100644 --- a/src/Bulwark.Auth.Guard/Authenticate.cs +++ b/src/Bulwark.Auth.Guard/Authenticate.cs @@ -5,6 +5,7 @@ using Bulwark.Auth.Guard.Exceptions; using JWT.Algorithms; using JWT.Builder; +using JWT.Exceptions; using RestSharp; namespace Bulwark.Auth.Guard; @@ -185,9 +186,10 @@ public async Task Acknowledge(Authenticated authenticated, { var error = JsonSerializer .Deserialize(response.Content); - if (error is { Detail: { } }) + if (error is not { Detail: not null }) throw new BulwarkException("Unknown error"); + if (error.Detail.Contains("token expired", System.StringComparison.CurrentCultureIgnoreCase)) { - throw new BulwarkException(error.Detail); + throw new BulwarkTokenExpiredException(error.Detail); } throw new BulwarkException("Unknown error"); @@ -262,14 +264,21 @@ public async Task ValidateAccessToken(string email, string accessTo publicKey.ImportFromPem(key.PublicKey.ToCharArray()); - var json = JwtBuilder.Create() - .WithAlgorithm(new RS256Algorithm(publicKey)) - .MustVerifySignature() - .Decode(accessToken); + try + { + var json = JwtBuilder.Create() + .WithAlgorithm(new RS256Algorithm(publicKey)) + .MustVerifySignature() + .Decode(accessToken); - var token = JsonSerializer.Deserialize(json); + var token = JsonSerializer.Deserialize(json); - return token; + return token; + } + catch (TokenExpiredException) + { + throw new BulwarkTokenExpiredException("Access Token Expired"); + } } public async Task InitializeLocalKeyValidation() @@ -312,12 +321,14 @@ public async Task Renew(string refreshToken, { var error = JsonSerializer .Deserialize(response.Content); - if (error is { Detail: { } }) + + if (error is not { Detail: not null }) throw new BulwarkException("Unknown error"); + if (error.Detail.Contains("token expired", System.StringComparison.CurrentCultureIgnoreCase)) { - throw new BulwarkException(error.Detail); + throw new BulwarkTokenExpiredException(error.Detail); } + throw new BulwarkException(error.Detail); - throw new BulwarkException("Unknown error"); } if(response.Content != null) { diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index d551759..50e3e67 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -34,7 +34,4 @@ - - - diff --git a/src/Bulwark.Auth.Guard/Exceptions/BulwarkTokenExpiredException.cs b/src/Bulwark.Auth.Guard/Exceptions/BulwarkTokenExpiredException.cs new file mode 100644 index 0000000..3fa7576 --- /dev/null +++ b/src/Bulwark.Auth.Guard/Exceptions/BulwarkTokenExpiredException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Bulwark.Auth.Guard.Exceptions; + +public class BulwarkTokenExpiredException : Exception +{ + public BulwarkTokenExpiredException(string message) : + base(message) { } + + public BulwarkTokenExpiredException(string message, Exception inner) : + base(message, inner) { } +} \ No newline at end of file From 8c3cfd42f1b5f575b8e38c45ffa73ce83a4c9cf3 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 28 Sep 2024 22:59:51 +0000 Subject: [PATCH 29/29] chore(release): 1.0.0-beta.10 [skip ci] # [1.0.0-beta.10](https://github.com/latebitflip-io/Bulwark.Auth.Guard/compare/v1.0.0-beta.9...v1.0.0-beta.10) (2024-09-28) ### Bug Fixes * token expired exception for acknowledge ([dd21cf0](https://github.com/latebitflip-io/Bulwark.Auth.Guard/commit/dd21cf08d030d10365bf8bdf3a1abbc5a4c30952)) --- src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj index 50e3e67..ae96e43 100644 --- a/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj +++ b/src/Bulwark.Auth.Guard/Bulwark.Auth.Guard.csproj @@ -6,12 +6,12 @@ Guard fritz@lateflip.io A client for Bulwark.Auth - 1.0.0-beta.9 + 1.0.0-beta.10 latebitflip.io lateflip.io Bulwark.Auth.Guard Bulwark.Auth.Guard - 1.0.0-beta.9 + 1.0.0-beta.10 Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard https://github.com/latebitflip-io/Bulwark.Auth.Guard