Skip to content

Commit a4a2a8c

Browse files
authored
Merge pull request #178 from TechnologyEnhancedLearning/RC
Merge RC to master
2 parents ebbe8a6 + fe62003 commit a4a2a8c

35 files changed

+942
-416
lines changed

Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
<ItemGroup>
12-
<PackageReference Include="elfhHub.Nhs.Models" Version="3.0.8" />
12+
<PackageReference Include="elfhHub.Nhs.Models" Version="3.0.10" />
1313
<PackageReference Include="LearningHub.Nhs.Models" Version="3.0.33" />
1414
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
1515
<PackageReference Include="Microsoft.TestPlatform.TestHost" Version="17.12.0" />

Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,22 @@ public static void AddServiceMappings(this IServiceCollection services, IConfigu
4040
ServerCertificateCustomValidationCallback =
4141
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
4242
});
43+
44+
services.AddHttpClient<IMoodleHttpClient, MoodleHttpClient>()
45+
.ConfigurePrimaryHttpMessageHandler(
46+
() => new HttpClientHandler
47+
{
48+
ServerCertificateCustomValidationCallback =
49+
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
50+
});
4351
}
4452
else
4553
{
4654
services.AddHttpClient<IUserApiHttpClient, UserApiHttpClient>();
55+
services.AddHttpClient<IMoodleHttpClient, MoodleHttpClient>();
4756
}
4857

58+
services.AddScoped<IMoodleApiService, MoodleApiService>();
4959
services.AddDistributedMemoryCache();
5060
services.AddScoped<IExternalSystemService, ExternalSystemService>();
5161
services.AddTransient<IRegistrationService, RegistrationService>();

Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,10 @@ public class WebSettings
6161
/// Gets or sets a value indicating whether IsPasswordUpdate.
6262
/// </summary>
6363
public bool IsPasswordUpdate { get; set; }
64-
}
64+
65+
/// <summary>
66+
/// Gets or sets a value indicating whether gets or sets a value to Enable Moodle.
67+
/// </summary>
68+
public bool EnableMoodle { get; set; }
69+
}
6570
}

Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Linq;
66
using System.Net;
77
using System.Threading.Tasks;
8+
using Azure.Core;
89
using elfhHub.Nhs.Models.Common;
910
using elfhHub.Nhs.Models.Enums;
1011
using IdentityModel;
@@ -22,9 +23,11 @@
2223
using LearningHub.Nhs.Models.Common;
2324
using Microsoft.AspNetCore.Authentication;
2425
using Microsoft.AspNetCore.Authorization;
26+
using Microsoft.AspNetCore.Http;
2527
using Microsoft.AspNetCore.Mvc;
2628
using Microsoft.Extensions.Logging;
2729
using Microsoft.Extensions.Options;
30+
using UAParser;
2831

2932
/// <summary>
3033
/// Account Controller operations.
@@ -163,34 +166,44 @@ await this.interaction.GrantConsentAsync(
163166

164167
if (loginResult.IsAuthenticated)
165168
{
166-
await this.SignInUser(userId, model.Username.Trim(), model.RememberLogin, context.Parameters["ext_referer"]);
167-
168-
if (context != null)
169+
var uaParser = Parser.GetDefault();
170+
var clientInfo = uaParser.Parse(this.Request.Headers["User-Agent"]);
171+
var result = await this.UserService.CheckUserHasAnActiveSessionAsync(userId);
172+
if (result.Items.Count == 0 || result.Items[0].BrowserName == clientInfo.UA.Family)
169173
{
170-
if (await this.ClientStore.IsPkceClientAsync(context.Client.ClientId))
174+
await this.SignInUser(userId, model.Username.Trim(), model.RememberLogin, context.Parameters["ext_referer"]);
175+
176+
if (context != null)
171177
{
172-
// if the client is PKCE then we assume it's native, so this change in how to
173-
// return the response is for better UX for the end user.
174-
return this.View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
178+
if (await this.ClientStore.IsPkceClientAsync(context.Client.ClientId))
179+
{
180+
// if the client is PKCE then we assume it's native, so this change in how to
181+
// return the response is for better UX for the end user.
182+
return this.View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
183+
}
184+
185+
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
186+
return this.Redirect(model.ReturnUrl);
175187
}
176188

177-
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
178-
return this.Redirect(model.ReturnUrl);
179-
}
180-
181-
// request for a local page
182-
if (this.Url.IsLocalUrl(model.ReturnUrl))
183-
{
184-
return this.Redirect(model.ReturnUrl);
185-
}
186-
else if (string.IsNullOrEmpty(model.ReturnUrl))
187-
{
188-
return this.Redirect("~/");
189+
// request for a local page
190+
if (this.Url.IsLocalUrl(model.ReturnUrl))
191+
{
192+
return this.Redirect(model.ReturnUrl);
193+
}
194+
else if (string.IsNullOrEmpty(model.ReturnUrl))
195+
{
196+
return this.Redirect("~/");
197+
}
198+
else
199+
{
200+
// user might have clicked on a malicious link - should be logged
201+
throw new Exception("invalid return URL");
202+
}
189203
}
190204
else
191205
{
192-
// user might have clicked on a malicious link - should be logged
193-
throw new Exception("invalid return URL");
206+
return this.View("AlreadyActiveSession");
194207
}
195208
}
196209
else if (userId > 0)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace LearningHub.Nhs.Auth.Interfaces
2+
{
3+
using System.Threading.Tasks;
4+
5+
/// <summary>
6+
/// IMoodleApiService.
7+
/// </summary>
8+
public interface IMoodleApiService
9+
{
10+
/// <summary>
11+
/// GetResourcesAsync.
12+
/// </summary>
13+
/// <param name="currentUserId">The current User Id.</param>
14+
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
15+
Task<int> GetMoodleUserIdByUsernameAsync(int currentUserId);
16+
}
17+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace LearningHub.Nhs.Auth.Interfaces
2+
{
3+
using System.Net.Http;
4+
using System.Threading.Tasks;
5+
6+
/// <summary>
7+
/// The Moodle Http Client interface.
8+
/// </summary>
9+
public interface IMoodleHttpClient
10+
{
11+
/// <summary>
12+
/// The get cient async.
13+
/// </summary>
14+
/// <returns>The <see cref="Task"/>.</returns>
15+
Task<HttpClient> GetClient();
16+
17+
/// <summary>
18+
/// GetDefaultParameters.
19+
/// </summary>
20+
/// <returns>defaultParameters.</returns>
21+
string GetDefaultParameters();
22+
}
23+
}

Auth/LearningHub.Nhs.Auth/Interfaces/IUserService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ public interface IUserService
114114
/// </returns>
115115
Task StoreUserHistoryAsync(UserHistoryViewModel userHistory);
116116

117+
/// <summary>
118+
/// check user has an laredy active session.
119+
/// </summary>
120+
/// <param name="userId">The userId.</param>
121+
/// <returns>The <see cref="Task"/>.</returns>
122+
Task<PagedResultSet<UserHistoryViewModel>> CheckUserHasAnActiveSessionAsync(int userId);
123+
117124
/// <summary>
118125
/// The store user history async.
119126
/// </summary>

Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Blobs" Version="1.4.0" />
102102
<PackageReference Include="Azure.Extensions.AspNetCore.DataProtection.Keys" Version="1.3.0" />
103103
<PackageReference Include="Azure.Identity" Version="1.13.2" />
104-
<PackageReference Include="elfhHub.Nhs.Models" Version="3.0.8" />
104+
<PackageReference Include="elfhHub.Nhs.Models" Version="3.0.10" />
105105
<PackageReference Include="FluentValidation" Version="11.11.0" />
106106
<PackageReference Include="IdentityServer4" Version="4.1.2" />
107107
<PackageReference Include="IdentityServer4.Contrib.RedisStore" Version="4.0.0" />
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
namespace LearningHub.Nhs.Auth.Models
2+
{
3+
using System.Collections.Generic;
4+
5+
/// <summary>
6+
/// MoodleUserResponseViewModel.
7+
/// </summary>
8+
public class MoodleUserResponseViewModel
9+
{
10+
/// <summary>
11+
/// Gets or sets the list of users.
12+
/// </summary>
13+
public List<MoodleUser> Users { get; set; }
14+
15+
/// <summary>
16+
/// Gets or sets the warnings.
17+
/// </summary>
18+
public List<object> Warnings { get; set; }
19+
20+
/// <summary>
21+
/// MoodleUser.
22+
/// </summary>
23+
public class MoodleUser
24+
{
25+
/// <summary>
26+
/// Gets or sets the user ID.
27+
/// </summary>
28+
public int Id { get; set; }
29+
30+
/// <summary>
31+
/// Gets or sets the username.
32+
/// </summary>
33+
public string Username { get; set; }
34+
35+
/// <summary>
36+
/// Gets or sets the first name.
37+
/// </summary>
38+
public string FirstName { get; set; }
39+
40+
/// <summary>
41+
/// Gets or sets the last name.
42+
/// </summary>
43+
public string LastName { get; set; }
44+
45+
/// <summary>
46+
/// Gets or sets the full name.
47+
/// </summary>
48+
public string FullName { get; set; }
49+
50+
/// <summary>
51+
/// Gets or sets the email.
52+
/// </summary>
53+
public string Email { get; set; }
54+
55+
/// <summary>
56+
/// Gets or sets the department.
57+
/// </summary>
58+
public string Department { get; set; }
59+
60+
/// <summary>
61+
/// Gets or sets the first access timestamp.
62+
/// </summary>
63+
public long FirstAccess { get; set; }
64+
65+
/// <summary>
66+
/// Gets or sets the last access timestamp.
67+
/// </summary>
68+
public long LastAccess { get; set; }
69+
70+
/// <summary>
71+
/// Gets or sets the authentication method.
72+
/// </summary>
73+
public string Auth { get; set; }
74+
75+
/// <summary>
76+
/// Gets or sets a value indicating whether the user is suspended.
77+
/// </summary>
78+
public bool Suspended { get; set; }
79+
80+
/// <summary>
81+
/// Gets or sets a value indicating whether the user is confirmed.
82+
/// </summary>
83+
public bool Confirmed { get; set; }
84+
85+
/// <summary>
86+
/// Gets or sets the language.
87+
/// </summary>
88+
public string Lang { get; set; }
89+
90+
/// <summary>
91+
/// Gets or sets the theme.
92+
/// </summary>
93+
public string Theme { get; set; }
94+
95+
/// <summary>
96+
/// Gets or sets the timezone.
97+
/// </summary>
98+
public string Timezone { get; set; }
99+
100+
/// <summary>
101+
/// Gets or sets the mail format.
102+
/// </summary>
103+
public int MailFormat { get; set; }
104+
105+
/// <summary>
106+
/// Gets or sets the forum tracking preference.
107+
/// </summary>
108+
public int TrackForums { get; set; }
109+
110+
/// <summary>
111+
/// Gets or sets the small profile image URL.
112+
/// </summary>
113+
public string ProfileImageUrlSmall { get; set; }
114+
115+
/// <summary>
116+
/// Gets or sets the profile image URL.
117+
/// </summary>
118+
public string ProfileImageUrl { get; set; }
119+
}
120+
}
121+
}

Auth/LearningHub.Nhs.Auth/NLog.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
</targets>
4040

4141
<rules>
42+
43+
<!-- Block all IdentityServer4 logs from being processed by later rules (like DB) -->
44+
<logger name="IdentityServer4.*" final="true" />
45+
4246
<!--<logger name="*" minlevel="Trace" writeTo="logfile" />-->
4347
<logger name="*" minlevel="Error" writeTo="database" />
4448
</rules>

0 commit comments

Comments
 (0)