From d50cd1569ae2ae79b8f119553d0079adc25b2672 Mon Sep 17 00:00:00 2001 From: Szymon Gaertig Date: Fri, 2 Sep 2016 14:42:09 +0200 Subject: [PATCH] claims on refresh token event #3153 --- .../RefreshTokenRefreshDetails.cs | 10 ++++ .../Extensions/IEventServiceExtensions.cs | 43 +++++++------- source/Tests/UnitTests/Core.Tests.csproj | 1 + .../Events/RefreshTokenRefreshDetailsTests.cs | 58 +++++++++++++++++++ 4 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 source/Tests/UnitTests/Events/RefreshTokenRefreshDetailsTests.cs diff --git a/source/Core/Events/TokenService/RefreshTokenRefreshDetails.cs b/source/Core/Events/TokenService/RefreshTokenRefreshDetails.cs index b48c719ed..bc62e4ec8 100644 --- a/source/Core/Events/TokenService/RefreshTokenRefreshDetails.cs +++ b/source/Core/Events/TokenService/RefreshTokenRefreshDetails.cs @@ -14,6 +14,8 @@ * limitations under the License. */ +using System.Collections.Generic; + namespace IdentityServer3.Core.Events { /// @@ -52,5 +54,13 @@ public class RefreshTokenRefreshDetails /// The lifetime. /// public int Lifetime { get; set; } + + /// + /// Gets or sets current user claims + /// + /// + /// The claims + /// + public Dictionary Claims { get; set; } } } diff --git a/source/Core/Extensions/IEventServiceExtensions.cs b/source/Core/Extensions/IEventServiceExtensions.cs index e4f6144f6..3ea601443 100644 --- a/source/Core/Extensions/IEventServiceExtensions.cs +++ b/source/Core/Extensions/IEventServiceExtensions.cs @@ -26,16 +26,17 @@ namespace IdentityServer3.Core.Extensions { internal static class IEventServiceExtensions { - public static async Task RaisePreLoginSuccessEventAsync(this IEventService events, + public static async Task RaisePreLoginSuccessEventAsync(this IEventService events, string signInMessageId, SignInMessage signInMessage, AuthenticateResult authResult) { var evt = new Event( EventConstants.Categories.Authentication, Resources.Events.PreLoginSuccess, - EventTypes.Success, + EventTypes.Success, EventConstants.Ids.PreLoginSuccess, - new LoginDetails { - SubjectId = authResult.HasSubject ? authResult.User.GetSubjectId() : null, + new LoginDetails + { + SubjectId = authResult.HasSubject ? authResult.User.GetSubjectId() : null, Name = authResult.User.Identity.Name, SignInId = signInMessageId, SignInMessage = signInMessage, @@ -45,7 +46,7 @@ public static async Task RaisePreLoginSuccessEventAsync(this IEventService event await events.RaiseEventAsync(evt); } - public static async Task RaisePreLoginFailureEventAsync(this IEventService events, + public static async Task RaisePreLoginFailureEventAsync(this IEventService events, string signInMessageId, SignInMessage signInMessage, string error) { var evt = new Event( @@ -57,13 +58,13 @@ public static async Task RaisePreLoginFailureEventAsync(this IEventService event { SignInId = signInMessageId, SignInMessage = signInMessage, - }, + }, error); await events.RaiseEventAsync(evt); } - public static async Task RaiseLocalLoginSuccessEventAsync(this IEventService events, + public static async Task RaiseLocalLoginSuccessEventAsync(this IEventService events, string username, string signInMessageId, SignInMessage signInMessage, AuthenticateResult authResult) { var evt = new Event( @@ -84,7 +85,7 @@ public static async Task RaiseLocalLoginSuccessEventAsync(this IEventService eve await events.RaiseEventAsync(evt); } - public static async Task RaiseLocalLoginFailureEventAsync(this IEventService events, + public static async Task RaiseLocalLoginFailureEventAsync(this IEventService events, string username, string signInMessageId, SignInMessage signInMessage, string error) { var evt = new Event( @@ -97,13 +98,13 @@ public static async Task RaiseLocalLoginFailureEventAsync(this IEventService eve SignInId = signInMessageId, SignInMessage = signInMessage, LoginUserName = username - }, + }, error); await events.RaiseEventAsync(evt); } - public static async Task RaiseExternalLoginSuccessEventAsync(this IEventService events, + public static async Task RaiseExternalLoginSuccessEventAsync(this IEventService events, ExternalIdentity externalIdentity, string signInMessageId, SignInMessage signInMessage, AuthenticateResult authResult) { var evt = new Event( @@ -125,7 +126,7 @@ public static async Task RaiseExternalLoginSuccessEventAsync(this IEventService await events.RaiseEventAsync(evt); } - public static async Task RaiseExternalLoginFailureEventAsync(this IEventService events, + public static async Task RaiseExternalLoginFailureEventAsync(this IEventService events, ExternalIdentity externalIdentity, string signInMessageId, SignInMessage signInMessage, string error) { var evt = new Event( @@ -139,7 +140,7 @@ public static async Task RaiseExternalLoginFailureEventAsync(this IEventService SignInMessage = signInMessage, Provider = externalIdentity.Provider, ProviderId = externalIdentity.ProviderId, - }, + }, error); await events.RaiseEventAsync(evt); @@ -157,7 +158,7 @@ public static async Task RaiseExternalLoginErrorEventAsync(this IEventService ev await events.RaiseEventAsync(evt); } - public static async Task RaiseSuccessfulResourceOwnerFlowAuthenticationEventAsync(this IEventService events, + public static async Task RaiseSuccessfulResourceOwnerFlowAuthenticationEventAsync(this IEventService events, string userName, string subjectId, SignInMessage message) { var evt = new Event( @@ -175,7 +176,7 @@ public static async Task RaiseSuccessfulResourceOwnerFlowAuthenticationEventAsyn await events.RaiseEventAsync(evt); } - public static async Task RaiseFailedResourceOwnerFlowAuthenticationEventAsync(this IEventService events, + public static async Task RaiseFailedResourceOwnerFlowAuthenticationEventAsync(this IEventService events, string userName, SignInMessage message, string error) { var evt = new Event( @@ -193,7 +194,7 @@ public static async Task RaiseFailedResourceOwnerFlowAuthenticationEventAsync(th await events.RaiseEventAsync(evt); } - public static async Task RaisePartialLoginCompleteEventAsync(this IEventService events, + public static async Task RaisePartialLoginCompleteEventAsync(this IEventService events, ClaimsIdentity subject, string signInMessageId, SignInMessage signInMessage) { var evt = new Event( @@ -212,7 +213,7 @@ public static async Task RaisePartialLoginCompleteEventAsync(this IEventService await events.RaiseEventAsync(evt); } - public static async Task RaiseLogoutEventAsync(this IEventService events, + public static async Task RaiseLogoutEventAsync(this IEventService events, ClaimsPrincipal subject, string signOutId, SignOutMessage signOutMessage) { var evt = new Event( @@ -239,7 +240,8 @@ public static async Task RaiseCspReportEventAsync(this IEventService events, str EventTypes.Information, EventConstants.Ids.CspReport); - evt.DetailsFunc = () => { + evt.DetailsFunc = () => + { string subject = null; string name = null; if (user != null && user.Identity.IsAuthenticated) @@ -253,7 +255,7 @@ public static async Task RaiseCspReportEventAsync(this IEventService events, str { reportData = Newtonsoft.Json.JsonConvert.DeserializeObject(report); } - catch(Newtonsoft.Json.JsonReaderException) + catch (Newtonsoft.Json.JsonReaderException) { reportData = "Error reading CSP report JSON"; evt.Message = "Raw Report Data: " + report; @@ -400,7 +402,8 @@ public static async Task RaiseSuccessfulRefreshTokenRefreshEventAsync(this IEven OldHandle = oldHandle, NewHandle = newHandle, ClientId = token.ClientId, - Lifetime = token.LifeTime + Lifetime = token.LifeTime, + Claims = token.Subject.Claims.ToClaimsDictionary() }; await events.RaiseEventAsync(evt); @@ -412,7 +415,7 @@ public static async Task RaiseUnhandledExceptionEventAsync(this IEventService ev EventConstants.Categories.InternalError, "Unhandled exception", EventTypes.Error, - EventConstants.Ids.UnhandledExceptionError, + EventConstants.Ids.UnhandledExceptionError, exception.ToString()); await events.RaiseEventAsync(evt); diff --git a/source/Tests/UnitTests/Core.Tests.csproj b/source/Tests/UnitTests/Core.Tests.csproj index 7f71a0387..cc772e165 100644 --- a/source/Tests/UnitTests/Core.Tests.csproj +++ b/source/Tests/UnitTests/Core.Tests.csproj @@ -194,6 +194,7 @@ + diff --git a/source/Tests/UnitTests/Events/RefreshTokenRefreshDetailsTests.cs b/source/Tests/UnitTests/Events/RefreshTokenRefreshDetailsTests.cs new file mode 100644 index 000000000..14a6b1624 --- /dev/null +++ b/source/Tests/UnitTests/Events/RefreshTokenRefreshDetailsTests.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using IdentityServer3.Core.Events; +using IdentityServer3.Core.Extensions; +using IdentityServer3.Core.Models; +using IdentityServer3.Core.Services; +using Moq; +using Xunit; + +namespace IdentityServer3.Tests.Events +{ + public class RefreshTokenRefreshDetailsTests + { + [Fact] + public async Task When_claims_are_provided_then_create_event_with_given_claims() + { + // Given + var oldHandle = "old_handle"; + var newHandle = "new_handle"; + + var claimsPrincipalMock = new Mock(); + claimsPrincipalMock.Setup(x => x.Claims) + .Returns(new List() + { + new Claim("claim_type_1", "claims_1_value"), + new Claim("claim_type_2", "claims_2_value") + }); + + var refreshToken = new RefreshToken() + { + AccessToken = new Token() + { + Client = new Client() + { + ClientId = "client_id", + AccessTokenLifetime = 10 + }, + }, + Subject = claimsPrincipalMock.Object + }; + var eventServiceMock = new Mock(); + + // When + await eventServiceMock.Object.RaiseSuccessfulRefreshTokenRefreshEventAsync(oldHandle, + newHandle, + refreshToken); + + // Then + eventServiceMock.Verify( + x => x.RaiseAsync( + It.Is>(rt + => rt.Details.Claims.ContainsKey("claim_type_1") + && rt.Details.Claims.ContainsKey("claim_type_2") + && rt.Details.Claims.Count == 2))); + } + } +} \ No newline at end of file