Skip to content

Commit

Permalink
feat: expose token scope on AuthenticateRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
Tr00d committed May 22, 2024
1 parent db8c97d commit 1b3c756
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
using FluentAssertions;
using Vonage.Common.Failures;
using Vonage.SimSwap.Authenticate;
using Vonage.Test.Common.Extensions;
using Xunit;

namespace Vonage.Test.SimSwap.Authenticate;

[Trait("Category", "Request")]
public class AuthenticateRequest
public class AuthenticateRequestTest
{
private const string ValidScope = "scope=test";

[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public void Parse_ShouldReturnFailure_GivenNumberIsNullOrWhitespace(string value) =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse(value).Should()
AuthenticateRequest.Parse(value, ValidScope).Should()
.BeFailure(ResultFailure.FromErrorMessage("Number cannot be null or whitespace."));

[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
public void Parse_ShouldReturnFailure_GivenScopeIsNullOrWhitespace(string value) =>
AuthenticateRequest.Parse("1234567", value).Should()
.BeParsingFailure("Scope cannot be null or whitespace.");

[Fact]
public void Parse_ShouldReturnFailure_GivenNumberContainsNonDigits() =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("1234567abc123").Should()
AuthenticateRequest.Parse("1234567abc123", ValidScope).Should()
.BeFailure(ResultFailure.FromErrorMessage("Number can only contain digits."));

[Fact]
public void Parse_ShouldReturnFailure_GivenNumberLengthIsHigherThan7() =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("123456").Should()
AuthenticateRequest.Parse("123456", ValidScope).Should()
.BeFailure(ResultFailure.FromErrorMessage("Number length cannot be lower than 7."));

[Fact]
public void Parse_ShouldReturnFailure_GivenNumberLengthIsLowerThan15() =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("1234567890123456").Should()
AuthenticateRequest.Parse("1234567890123456", ValidScope).Should()
.BeFailure(ResultFailure.FromErrorMessage("Number length cannot be higher than 15."));

[Theory]
Expand All @@ -37,14 +48,23 @@ public void Parse_ShouldReturnFailure_GivenNumberLengthIsLowerThan15() =>
[InlineData("+1234567890", "1234567890")]
[InlineData("+123456789012345", "123456789012345")]
[InlineData("+++1234567890", "1234567890")]
public void Parse_ShouldReturnSuccess_GivenNumberIsValid(string value, string expected) =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse(value).Map(number => number.PhoneNumber.Number).Should()
public void Parse_ShouldSetNumber(string value, string expected) =>
AuthenticateRequest.Parse(value, ValidScope)
.Map(request => request.PhoneNumber.Number)
.Should()
.BeSuccess(expected);

[Fact]
public void Parse_ShouldSetScope() =>
AuthenticateRequest.Parse("1234567", ValidScope)
.Map(request => request.Scope)
.Should()
.BeSuccess(ValidScope);

[Fact]
public void BuildAuthorizeRequest()
{
var request = Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("123456789").GetSuccessUnsafe();
var request = AuthenticateRequest.Parse("123456789", ValidScope).GetSuccessUnsafe();
request.BuildAuthorizeRequest().Number.Should().Be(request.PhoneNumber);
}
}
5 changes: 3 additions & 2 deletions Vonage.Test/SimSwap/Authenticate/AuthorizeRequestTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Vonage.Test.Common.Extensions;
using Vonage.SimSwap.Authenticate;
using Vonage.Test.Common.Extensions;
using Xunit;

namespace Vonage.Test.SimSwap.Authenticate;
Expand All @@ -8,7 +9,7 @@ public class AuthorizeRequestTest
{
[Fact]
public void GetEndpointPath_ShouldReturnApiEndpoint() =>
Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("123456789")
AuthenticateRequest.Parse("123456789", "scope")
.Map(request => request.BuildAuthorizeRequest())
.Map(r => r.GetEndpointPath())
.Should().BeSuccess("oauth2/bc-authorize");
Expand Down
3 changes: 2 additions & 1 deletion Vonage.Test/SimSwap/Authenticate/E2ETest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public async Task Authenticate()
.RespondWith(Response.Create().WithStatusCode(HttpStatusCode.OK)
.WithBody(this.Serialization.GetResponseJson(nameof(SerializationTest.ShouldDeserializeAccessToken))));
await this.Helper.VonageClient.SimSwapClient
.AuthenticateAsync(Vonage.SimSwap.Authenticate.AuthenticateRequest.Parse("447700900000"))
.AuthenticateAsync(AuthenticateRequest.Parse("447700900000",
"scope=openid dpv:FraudPreventionAndDetection#check-sim-swap"))
.Should()
.BeSuccessAsync(new AuthenticateResponse("ABCDEFG"));
}
Expand Down
21 changes: 17 additions & 4 deletions Vonage/SimSwap/Authenticate/AuthenticateRequest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Vonage.Common;
using Vonage.Common.Monads;
using Vonage.Common.Validation;

namespace Vonage.SimSwap.Authenticate;

Expand All @@ -12,17 +13,29 @@ public readonly struct AuthenticateRequest
/// Parses the input into an AuthenticateRequest.
/// </summary>
/// <param name="number">The phone number.</param>
/// <param name="tokenScope">The authorization scope for the token.</param>
/// <returns>Success if the input matches all requirements. Failure otherwise.</returns>
public static Result<AuthenticateRequest> Parse(string number) =>
public static Result<AuthenticateRequest> Parse(string number, string tokenScope) =>
PhoneNumber.Parse(number).Map(phoneNumber => new AuthenticateRequest
{
PhoneNumber = phoneNumber,
});
{
PhoneNumber = phoneNumber,
Scope = tokenScope,
})
.Map(InputEvaluation<AuthenticateRequest>.Evaluate)
.Bind(evaluation => evaluation.WithRules(VerifyScope));

/// <summary>
/// Subscriber number in E.164 format (starting with country code). Optionally prefixed with '+'.
/// </summary>
public PhoneNumber PhoneNumber { get; private init; }

/// <summary>
/// The authorization scope for the token.
/// </summary>
public string Scope { get; private init; }

private static Result<AuthenticateRequest> VerifyScope(AuthenticateRequest request) =>
InputValidation.VerifyNotEmpty(request, request.Scope, nameof(request.Scope));

internal AuthorizeRequest BuildAuthorizeRequest() => new AuthorizeRequest(this.PhoneNumber);
}
11 changes: 11 additions & 0 deletions Vonage/SimSwap/Check/CheckRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
using System.Text.Json.Serialization;
using Vonage.Common;
using Vonage.Common.Client;
using Vonage.Common.Monads;
using Vonage.Common.Serialization;
using Vonage.Serialization;
using Vonage.SimSwap.Authenticate;

namespace Vonage.SimSwap.Check;

Expand Down Expand Up @@ -42,6 +44,15 @@ private StringContent GetRequestContent() =>
[JsonPropertyName("maxAge")]
public int Period { get; internal init; }

/// <summary>
/// The authorization scope for the token.
/// </summary>
[JsonIgnore]
public string Scope => "scope=openid dpv:FraudPreventionAndDetection#check-sim-swap";

internal Result<AuthenticateRequest> BuildAuthenticationRequest() =>
AuthenticateRequest.Parse(this.PhoneNumber.NumberWithInternationalIndicator, this.Scope);

/// <summary>
/// Initializes a builder.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions Vonage/SimSwap/SimSwapClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ private VonageHttpClient BuildClientWithAuthenticationHeader(AuthenticationHeade
private static AuthenticationHeaderValue BuildAuthenticationHeader(AuthenticateResponse authentication) =>
authentication.BuildAuthenticationHeader();

private Task<Result<AuthenticateResponse>> AuthenticateCheckRequest(CheckRequest r) =>
this.AuthenticateAsync(AuthenticateRequest.Parse(r.PhoneNumber.NumberWithInternationalIndicator));
private Task<Result<AuthenticateResponse>> AuthenticateCheckRequest(CheckRequest request) =>
this.AuthenticateAsync(request.BuildAuthenticationRequest());

private static AuthenticateResponse BuildAuthenticateResponse(GetTokenResponse response) =>
new AuthenticateResponse(response.AccessToken);
Expand Down

0 comments on commit 1b3c756

Please sign in to comment.