Skip to content

Commit fff2249

Browse files
committed
🔒 SSO is now working
1 parent 1b00b0a commit fff2249

File tree

7 files changed

+57
-52
lines changed

7 files changed

+57
-52
lines changed

‎src/WebUI/Common/Identity/ICurrentUserService.cs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
namespace WebUI.Common.Identity;
1+
using Microsoft.Graph.Models;
2+
using System.Security.Claims;
3+
4+
namespace WebUI.Common.Identity;
25

36
public interface ICurrentUserService
47
{
58
string UserId { get; }
69

710
string AccessToken { get; }
8-
string FirstName { get; }
9-
string LastName { get; }
11+
string UserName { get; }
1012

1113
void UpdateAccessToken(string token);
1214
void UpdateName(string firstName, string lastName);
@@ -18,9 +20,7 @@ public class CurrentUserService : ICurrentUserService
1820

1921
public string AccessToken { get; private set; } = string.Empty;
2022

21-
public string FirstName { get; private set; } = string.Empty;
22-
23-
public string LastName { get; private set; } = string.Empty;
23+
public string UserName { get; private set; } = string.Empty;
2424

2525
public void UpdateAccessToken(string token)
2626
{
@@ -34,7 +34,24 @@ public void UpdateName(string firstName, string lastName)
3434
ArgumentException.ThrowIfNullOrWhiteSpace(firstName);
3535
ArgumentException.ThrowIfNullOrWhiteSpace(lastName);
3636

37-
FirstName = firstName;
38-
LastName = lastName;
37+
UserName = $"{firstName} {lastName}";
38+
}
39+
}
40+
41+
public class OAuthCurrentUserService : ICurrentUserService
42+
{
43+
public string UserId { get; }
44+
public string AccessToken { get; } = string.Empty;
45+
public string UserName { get; }
46+
47+
public void UpdateAccessToken(string token) => throw new NotImplementedException();
48+
49+
public void UpdateName(string firstName, string lastName) => throw new NotImplementedException();
50+
51+
public OAuthCurrentUserService(IHttpContextAccessor httpContextAccessor)
52+
{
53+
UserId = httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier) ?? string.Empty;
54+
UserName = httpContextAccessor.HttpContext?.User?.FindFirstValue("Name") ?? string.Empty;
55+
UserName = UserName.TrimEnd(" [SSW]");
3956
}
4057
}

‎src/WebUI/Features/DailyScrum/Infrastructure/GraphService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public GraphService(
2121
GraphServiceClientFactory factory)
2222
{
2323
_logger = logger;
24-
_graphServiceClient = factory.CreateWithAccessToken();
24+
_graphServiceClient = factory.CreateDefault();
2525
}
2626

2727
// public async Task<List<TodoTaskList>?> GetTodoLists()

‎src/WebUI/Features/DailyScrum/Infrastructure/GraphServiceClientFactory.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@ public class GraphServiceClientFactory
88
{
99
private readonly ICurrentUserService _currentUserService;
1010
private readonly IServiceProvider _serviceProvider;
11+
12+
// TODO: Read from config
1113
private readonly string _clientId = "2407f45c-4141-4484-8fc5-ce61327519d9";
1214
private readonly string _tenantId = "ac2f7c34-b935-48e9-abdc-11e5d4fcb2b0";
1315
private readonly string _redirectUri = "http://localhost:5001"; // Must match redirect URI in app registration
16+
private readonly string[] _scopes = new[] { "User.Read" };
1417

1518
public GraphServiceClientFactory(ICurrentUserService currentUserService, IServiceProvider serviceProvider)
1619
{
1720
_currentUserService = currentUserService;
1821
_serviceProvider = serviceProvider;
1922
}
2023

21-
public GraphServiceClient Create()
24+
public GraphServiceClient CreateDefault()
2225
{
2326
return _serviceProvider.GetRequiredService<GraphServiceClient>();
2427
}
@@ -33,8 +36,6 @@ public GraphServiceClient CreateWithAccessToken()
3336

3437
public GraphServiceClient CreateWithDeviceCodeFlow()
3538
{
36-
var scopes = new[] { "User.Read" };
37-
3839
var options = new DeviceCodeCredentialOptions
3940
{
4041
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
@@ -53,7 +54,7 @@ public GraphServiceClient CreateWithDeviceCodeFlow()
5354
// https://learn.microsoft.com/dotnet/api/azure.identity.devicecodecredential
5455
var deviceCodeCredential = new DeviceCodeCredential(options);
5556

56-
var graphClient = new GraphServiceClient(deviceCodeCredential, scopes);
57+
var graphClient = new GraphServiceClient(deviceCodeCredential, _scopes);
5758

5859
return graphClient;
5960
}

‎src/WebUI/Features/DailyScrum/Queries/GetDailyScrumQuery.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,11 @@ private async Task<List<ProjectViewModel>> GetProjects(DateOnly date)
8686

8787
private EmailViewModel GetEmail()
8888
{
89-
var firstName = _currentUserService.FirstName;
90-
var lastName = _currentUserService.LastName;
89+
var userName = _currentUserService.UserName;
9190

9291
return new EmailViewModel
9392
{
94-
Subject = $"{firstName} {lastName} - Daily Scrum",
93+
Subject = $"{userName} - Daily Scrum",
9594
To = new EmailParticipantViewModel
9695
{
9796
Name = "SSWBenchMasters",

‎src/WebUI/Program.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
2-
using Microsoft.AspNetCore.HttpOverrides;
32
using Microsoft.Identity.Web;
43
using Microsoft.Identity.Web.UI;
54
using System.Reflection;
@@ -12,18 +11,18 @@
1211

1312
var initialScopes = builder.Configuration.GetSection("DownstreamApi:Scopes").Get<string[]>();
1413

15-
// builder.Services
16-
// .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
17-
// .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
18-
// .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
19-
// .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
20-
// .AddInMemoryTokenCaches();
21-
//
22-
// builder.Services.AddAuthorization(options =>
23-
// {
24-
// // By default, all incoming requests will be authorized according to the default policy.
25-
// options.FallbackPolicy = options.DefaultPolicy;
26-
// });
14+
builder.Services
15+
.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
16+
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
17+
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
18+
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
19+
.AddInMemoryTokenCaches();
20+
21+
builder.Services.AddAuthorization(options =>
22+
{
23+
// By default, all incoming requests will be authorized according to the default policy.
24+
options.FallbackPolicy = options.DefaultPolicy;
25+
});
2726

2827
builder.Services
2928
.AddRazorPages()
@@ -32,7 +31,8 @@
3231
// App Services
3332
builder.Services.ConfigureFeatures(builder.Configuration, appAssembly);
3433
builder.Services.AddMediatR();
35-
builder.Services.AddSingleton<ICurrentUserService, CurrentUserService>();
34+
// builder.Services.AddSingleton<ICurrentUserService, CurrentUserService>();
35+
builder.Services.AddScoped<ICurrentUserService, OAuthCurrentUserService>();
3636
builder.Services.AddScoped<GraphServiceClientFactory>();
3737

3838
var app = builder.Build();
@@ -47,7 +47,8 @@
4747

4848
app.UseRouting();
4949

50-
// app.UseAuthorization();
50+
app.UseAuthentication();
51+
app.UseAuthorization();
5152

5253
app.MapStaticAssets();
5354
app.MapRazorPages()

‎src/WebUI/appsettings.json

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
{
2-
/*
3-
The following identity settings need to be configured
4-
before the project can be successfully executed.
5-
For more info see https://aka.ms/dotnet-template-ms-identity-platform
6-
*/
72
"AzureAd": {
83
"Instance": "https://login.microsoftonline.com/",
94
"Domain": "qualified.domain.name",
@@ -15,21 +10,14 @@
1510
"CallbackPath": "/signin-oidc"
1611
},
1712
"DownstreamApi": {
18-
/*
19-
'Scopes' contains scopes of the Web API you want to call. This can be:
20-
- a scope for a V2 application (for instance api:b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/access_as_user)
21-
- a scope corresponding to a V1 application (for instance <App ID URI>/.default, where <App ID URI> is the
22-
App ID URI of a legacy v1 Web application
23-
Applications are registered in the https:portal.azure.com portal.
24-
*/
2513
"BaseUrl": "https://graph.microsoft.com/v1.0",
2614
"Scopes": [
27-
"user.read",
28-
// "tasks.read",
29-
// "mailboxitem.read",
30-
// "mailboxfolder.read",
31-
// "mail.readbasic",
32-
"mail.readbasic"
15+
"mail.read",
16+
"mail.readbasic",
17+
"mailboxfolder.read",
18+
"mailboxitem.read",
19+
"tasks.read",
20+
"user.read"
3321
]
3422
},
3523
"Logging": {

‎tests/UnitTests/UpdateAccessTokenCommandTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public void Handle_GivenValidAccessToken_ShouldSetFirstNameAndLastName()
1515

1616
sut.Handle(new UpdateAccessTokenCommand(token), CancellationToken.None);
1717

18-
currentUserService.FirstName.Should().Be("Daniel");
19-
currentUserService.LastName.Should().Be("Mackay");
18+
currentUserService.UserName.Should().Be("Daniel Mackay");
2019
}
21-
}
20+
}

0 commit comments

Comments
 (0)