Skip to content

Commit

Permalink
Fixed ISSOService interface to be clearer and to use correct user
Browse files Browse the repository at this point in the history
  • Loading branch information
jezzsantos committed Nov 25, 2024
1 parent 570b894 commit 76bdaea
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 87 deletions.
24 changes: 22 additions & 2 deletions src/Application.Services.Shared/ISSOService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,32 @@

namespace Application.Services.Shared;

/// <summary>
/// Defines a service to access and manage the SSO AuthTokens for a user
/// </summary>
public interface ISSOService
{
/// <summary>
/// Retrieves the list of tokens for the current user
/// </summary>
Task<Result<IReadOnlyList<ProviderAuthenticationTokens>, Error>> GetTokensAsync(ICallerContext caller,
string userId,
CancellationToken cancellationToken);

Task<Result<ProviderAuthenticationTokens, Error>> RefreshTokenAsync(ICallerContext caller, string userId,
/// <summary>
/// Retrieves the list of tokens for the specified user
/// </summary>
Task<Result<IReadOnlyList<ProviderAuthenticationTokens>, Error>> GetTokensOnBehalfOfUserAsync(ICallerContext caller,
string userId, CancellationToken cancellationToken);

/// <summary>
/// Refreshes the specified <see cref="refreshToken" /> for the current user
/// </summary>
Task<Result<ProviderAuthenticationTokens, Error>> RefreshTokenAsync(ICallerContext caller,
string providerName, string refreshToken, CancellationToken cancellationToken);

/// <summary>
/// Refreshes the specified <see cref="refreshToken" /> for the specified user
/// </summary>
Task<Result<ProviderAuthenticationTokens, Error>> RefreshTokenOnBehalfOfUserAsync(ICallerContext caller,
string userId, string providerName, string refreshToken, CancellationToken cancellationToken);
}
6 changes: 4 additions & 2 deletions src/IdentityApplication.UnitTests/SSOProvidersServiceSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,8 @@ public async Task WhenGetTokensAsyncAndNoTokens_ThenReturnsNone()
It.IsAny<CancellationToken>()))
.ReturnsAsync(ssoUser.ToOptional());

var result = await _service.GetTokensAsync(_caller.Object, "auserid".ToId(), CancellationToken.None);
var result =
await _service.GetTokensOnBehalfOfUserAsync(_caller.Object, "auserid".ToId(), CancellationToken.None);

result.Should().BeSuccess();
result.Value.Count.Should().Be(0);
Expand All @@ -367,7 +368,8 @@ public async Task WhenGetTokensAsync_ThenReturnsError()
It.IsAny<CancellationToken>()))
.ReturnsAsync(ssoUser.ToOptional());

var result = await _service.GetTokensAsync(_caller.Object, "auserid".ToId(), CancellationToken.None);
var result =
await _service.GetTokensOnBehalfOfUserAsync(_caller.Object, "auserid".ToId(), CancellationToken.None);

result.Should().BeSuccess();
result.Value.Count.Should().Be(1);
Expand Down
44 changes: 22 additions & 22 deletions src/IdentityApplication.UnitTests/SingleSignOnApplicationSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public SingleSignOnApplicationSpec()
.Setup(sps => sps.FindByProviderNameAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(_ssoProvider.Object.ToOptional());
_ssoProvidersService.Setup(sps =>
sps.FindByUserIdAsync(It.IsAny<ICallerContext>(), It.IsAny<Identifier>(), It.IsAny<string>(),
sps.FindByUserIdAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(_ssoProvider.Object.ToOptional());
_authTokensService = new Mock<IAuthTokensService>();
Expand All @@ -49,8 +49,7 @@ public async Task WhenAuthenticateAndNoProvider_ThenReturnsError()
.ReturnsAsync(Optional<ISSOAuthenticationProvider>.None);

var result = await _application.AuthenticateAsync(_caller.Object, "aninvitationtoken", "aprovidername",
"anauthcode", null,
CancellationToken.None);
"anauthcode", null, CancellationToken.None);

result.Should().BeError(ErrorCode.NotAuthenticated);
_endUsersService.Verify(
Expand Down Expand Up @@ -120,7 +119,7 @@ public async Task WhenAuthenticateAndPersonExistsButNotRegisteredYet_ThenIssuesT
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(),
It.IsAny<CancellationToken>()), Times.Never);
_ssoProvidersService.Verify(
sps => sps.SaveUserInfoAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<Identifier>(),
sps => sps.SaveUserInfoAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<SSOUserInfo>(),
It.IsAny<CancellationToken>()), Times.Never);
_endUsersService.Verify(eus =>
Expand Down Expand Up @@ -174,7 +173,7 @@ public async Task WhenAuthenticateAndPersonIsSuspended_ThenIssuesToken()
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>(),
It.IsAny<CancellationToken>()), Times.Never);
_ssoProvidersService.Verify(
sps => sps.SaveUserInfoAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<Identifier>(),
sps => sps.SaveUserInfoAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<SSOUserInfo>(),
It.IsAny<CancellationToken>()), Times.Never);
_endUsersService.Verify(eus =>
Expand Down Expand Up @@ -319,14 +318,14 @@ public async Task WhenAuthenticateAndPersonExists_ThenIssuesToken()
}

[Fact]
public async Task WhenRefreshTokenAsyncAndProviderUserNotExists_ThenReturnsError()
public async Task WhenRefreshTokenOnBehalfOfUserAsyncAndProviderUserNotExists_ThenReturnsError()
{
_ssoProvidersService.Setup(sp =>
sp.FindByUserIdAsync(It.IsAny<ICallerContext>(), It.IsAny<Identifier>(), It.IsAny<string>(),
sp.FindByUserIdAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(Optional<ISSOAuthenticationProvider>.None);

var result = await _application.RefreshTokenAsync(_caller.Object, "auserid", "aprovidername",
var result = await _application.RefreshTokenOnBehalfOfUserAsync(_caller.Object, "auserid", "aprovidername",
"arefreshtoken", CancellationToken.None);

result.Should().BeError(ErrorCode.NotAuthenticated);
Expand All @@ -336,19 +335,19 @@ public async Task WhenRefreshTokenAsyncAndProviderUserNotExists_ThenReturnsError
eus => eus.GetUserPrivateAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
It.IsAny<CancellationToken>()), Times.Never);
_ssoProvidersService.Verify(
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<Identifier>(),
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<ProviderAuthenticationTokens>(), It.IsAny<CancellationToken>()), Times.Never);
}

[Fact]
public async Task WhenRefreshTokenAsyncAndEndUserNotExists_ThenReturnsError()
public async Task WhenRefreshTokenOnBehalfOfUserAsyncAndEndUserNotExists_ThenReturnsError()
{
_endUsersService.Setup(eus =>
eus.GetUserPrivateAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(Error.EntityNotFound());

var result = await _application.RefreshTokenAsync(_caller.Object, "auserid", "aprovidername",
var result = await _application.RefreshTokenOnBehalfOfUserAsync(_caller.Object, "auserid", "aprovidername",
"arefreshtoken", CancellationToken.None);

result.Should().BeError(ErrorCode.NotAuthenticated);
Expand All @@ -361,12 +360,12 @@ public async Task WhenRefreshTokenAsyncAndEndUserNotExists_ThenReturnsError()
sop => sop.RefreshTokenAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
It.IsAny<CancellationToken>()), Times.Never);
_ssoProvidersService.Verify(
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<Identifier>(),
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<ProviderAuthenticationTokens>(), It.IsAny<CancellationToken>()), Times.Never);
}

[Fact]
public async Task WhenRefreshTokenAsyncAndPersonIsSuspended_ThenReturnsError()
public async Task WhenRefreshTokenOnBehalfOfUserAsyncAndPersonIsSuspended_ThenReturnsError()
{
_endUsersService.Setup(eus =>
eus.GetUserPrivateAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
Expand All @@ -382,7 +381,7 @@ public async Task WhenRefreshTokenAsyncAndPersonIsSuspended_ThenReturnsError()
It.IsAny<CancellationToken>()))
.ReturnsAsync(Error.Unexpected("amessage"));

var result = await _application.RefreshTokenAsync(_caller.Object, "auserid", "aprovidername",
var result = await _application.RefreshTokenOnBehalfOfUserAsync(_caller.Object, "auserid", "aprovidername",
"arefreshtoken", CancellationToken.None);

result.Should().BeError(ErrorCode.EntityExists, Resources.SingleSignOnApplication_AccountSuspended);
Expand All @@ -393,12 +392,12 @@ public async Task WhenRefreshTokenAsyncAndPersonIsSuspended_ThenReturnsError()
sop => sop.RefreshTokenAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
It.IsAny<CancellationToken>()), Times.Never);
_ssoProvidersService.Verify(
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<Identifier>(),
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<ProviderAuthenticationTokens>(), It.IsAny<CancellationToken>()), Times.Never);
}

[Fact]
public async Task WhenRefreshTokenAsyncAndRefreshErrors_ThenReturnsError()
public async Task WhenRefreshTokenOnBehalfOfUserAsyncAndRefreshErrors_ThenReturnsError()
{
_endUsersService.Setup(eus =>
eus.GetUserPrivateAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
Expand All @@ -414,7 +413,7 @@ public async Task WhenRefreshTokenAsyncAndRefreshErrors_ThenReturnsError()
It.IsAny<CancellationToken>()))
.ReturnsAsync(Error.Unexpected("amessage"));

var result = await _application.RefreshTokenAsync(_caller.Object, "auserid", "aprovidername",
var result = await _application.RefreshTokenOnBehalfOfUserAsync(_caller.Object, "auserid", "aprovidername",
"arefreshtoken", CancellationToken.None);

result.Should().BeError(ErrorCode.NotAuthenticated);
Expand All @@ -427,12 +426,12 @@ public async Task WhenRefreshTokenAsyncAndRefreshErrors_ThenReturnsError()
sop => sop.RefreshTokenAsync(_caller.Object, It.IsAny<string>(),
It.IsAny<CancellationToken>()));
_ssoProvidersService.Verify(
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<Identifier>(),
sps => sps.SaveUserTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<ProviderAuthenticationTokens>(), It.IsAny<CancellationToken>()), Times.Never);
}

[Fact]
public async Task WhenRefreshTokenAsync_ThenRefreshed()
public async Task WhenRefreshTokenOnBehalfOfUserAsync_ThenRefreshed()
{
_endUsersService.Setup(eus =>
eus.GetUserPrivateAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
Expand Down Expand Up @@ -472,7 +471,7 @@ public async Task WhenRefreshTokenAsync_ThenRefreshed()
]
});

var result = await _application.RefreshTokenAsync(_caller.Object, "auserid", "aprovidername",
var result = await _application.RefreshTokenOnBehalfOfUserAsync(_caller.Object, "auserid", "aprovidername",
"arefreshtoken", CancellationToken.None);

result.Should().BeSuccess();
Expand Down Expand Up @@ -506,7 +505,8 @@ public async Task WhenGetTokensAsync_ThenReturnsTokens()
{
var datum = DateTime.UtcNow;
_ssoProvidersService.Setup(sps =>
sps.GetTokensAsync(It.IsAny<ICallerContext>(), It.IsAny<Identifier>(), It.IsAny<CancellationToken>()))
sps.GetTokensOnBehalfOfUserAsync(It.IsAny<ICallerContext>(), It.IsAny<string>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<ProviderAuthenticationTokens>
{
new()
Expand Down Expand Up @@ -536,7 +536,7 @@ public async Task WhenGetTokensAsync_ThenReturnsTokens()
}
});

var result = await _application.GetTokensAsync(_caller.Object, "auserid", CancellationToken.None);
var result = await _application.GetTokensOnBehalfOfUserAsync(_caller.Object, "auserid", CancellationToken.None);

result.Should().BeSuccess();
result.Value.Count.Should().Be(1);
Expand Down
21 changes: 10 additions & 11 deletions src/IdentityApplication/ApplicationServices/ISSOProvidersService.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
using Application.Interfaces;
using Application.Resources.Shared;
using Common;
using Domain.Common.ValueObjects;

namespace IdentityApplication.ApplicationServices;

/// <summary>
/// Defines a service for accessing registered <see cref="ISSOAuthenticationProvider" />s
/// Defines a service for accessing the registered <see cref="ISSOAuthenticationProvider" />s
/// </summary>
public interface ISSOProvidersService
{
Task<Result<Optional<ISSOAuthenticationProvider>, Error>> FindByProviderNameAsync(string providerName,
CancellationToken cancellationToken);

Task<Result<Optional<ISSOAuthenticationProvider>, Error>> FindByUserIdAsync(ICallerContext caller,
Identifier userId, string providerName,
CancellationToken cancellationToken);
string userId, string providerName, CancellationToken cancellationToken);

Task<Result<IReadOnlyList<ProviderAuthenticationTokens>, Error>> GetTokensAsync(ICallerContext caller,
Identifier userId, CancellationToken cancellationToken);

Task<Result<Error>> SaveUserInfoAsync(ICallerContext caller, string providerName, Identifier userId,
SSOUserInfo userInfo,
CancellationToken cancellationToken);

Task<Result<Error>> SaveUserTokensAsync(ICallerContext caller, string providerName, Identifier userId,
ProviderAuthenticationTokens tokens,
CancellationToken cancellationToken);
Task<Result<IReadOnlyList<ProviderAuthenticationTokens>, Error>> GetTokensOnBehalfOfUserAsync(ICallerContext caller,
string userId, CancellationToken cancellationToken);

Task<Result<Error>> SaveUserInfoAsync(ICallerContext caller, string providerName, string userId,
SSOUserInfo userInfo, CancellationToken cancellationToken);

Task<Result<Error>> SaveUserTokensAsync(ICallerContext caller, string providerName, string userId,
ProviderAuthenticationTokens tokens, CancellationToken cancellationToken);
}
Loading

0 comments on commit 76bdaea

Please sign in to comment.