Просмотр исходного кода

Enabled server side authorization with Auth0 token

Lukas Angerer 3 лет назад
Родитель
Сommit
a6ca9d8026

+ 1 - 0
src/RunnersMeet.Client/src/app/app.component.html

@@ -1,5 +1,6 @@
 <h1>{{title}}</h1>
 <ul>
+	<li><a [routerLink]="['/']">Home</a></li>
 	<li><a [routerLink]="['/tracks']">Tracks</a></li>
 	<li><a [routerLink]="['/tracks/create']">Create Track</a></li>
 </ul>

+ 7 - 2
src/RunnersMeet.Client/src/app/app.module.ts

@@ -1,6 +1,6 @@
 import { NgModule } from '@angular/core';
 import { BrowserModule } from '@angular/platform-browser';
-import { AuthModule } from '@auth0/auth0-angular';
+import { AuthHttpInterceptor, AuthModule } from '@auth0/auth0-angular';
 
 import { AppRoutingModule } from './app-routing.module';
 import { AppComponent } from './app.component';
@@ -8,7 +8,7 @@ import { environment } from '../env/environment';
 import { HomePageComponent } from './pages/home-page/home-page.component';
 import { TracksPageComponent } from './pages/tracks-page/tracks-page.component';
 import { TracksApiService } from './tracks-api.service';
-import { HttpClientModule } from '@angular/common/http';
+import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
 import { CreateTrackPageComponent } from './pages/create-track-page/create-track-page.component';
 import { FormsModule } from '@angular/forms';
 
@@ -32,6 +32,11 @@ import { FormsModule } from '@angular/forms';
 		FormsModule
 	],
 	providers: [
+		{
+			provide: HTTP_INTERCEPTORS,
+			useClass: AuthHttpInterceptor,
+			multi: true,
+		},
 		TracksApiService
 	],
 	bootstrap: [AppComponent]

+ 23 - 0
src/RunnersMeet.Server/AppServer.cs

@@ -1,3 +1,5 @@
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.IdentityModel.Tokens;
 using RunnersMeet.Server.Persistence;
 
 namespace RunnersMeet.Server;
@@ -26,6 +28,27 @@ public class AppServer
 			});
 		});
 
+		var authOptions = new AuthOptions();
+		builder.Configuration.GetSection("Auth").Bind(authOptions);
+		builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+			.AddJwtBearer(options =>
+			{
+				options.Authority = authOptions.Authority;
+				options.TokenValidationParameters = new TokenValidationParameters
+				{
+					ValidIssuer = authOptions.Authority,
+					ValidAudience = authOptions.Audience
+				};
+			});
+
+		builder.Services.AddAuthorization(authorizationOptions =>
+		{
+			foreach (var policyPair in authOptions.PolicyClaims)
+			{
+				authorizationOptions.AddPolicy(policyPair.Key, policyBuilder => policyBuilder.RequireClaim("permissions", policyPair.Value));
+			}
+		});
+
 		var app = builder.Build();
 
 		// Configure the HTTP request pipeline.

+ 9 - 0
src/RunnersMeet.Server/AuthOptions.cs

@@ -0,0 +1,9 @@
+// ReSharper disable CollectionNeverUpdated.Global
+namespace RunnersMeet.Server;
+
+public class AuthOptions
+{
+	public string Authority { get; set; } = String.Empty;
+	public string Audience { get; set; } = String.Empty;
+	public IDictionary<string, string[]> PolicyClaims { get; set; } = new Dictionary<string, string[]>();
+}

+ 2 - 0
src/RunnersMeet.Server/Controllers/TracksController.cs

@@ -1,4 +1,5 @@
 using System.Security.Claims;
+using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Mvc;
 using RunnersMeet.Server.Domain;
 using RunnersMeet.Server.Persistence;
@@ -7,6 +8,7 @@ namespace RunnersMeet.Server.Controllers;
 
 [Route("api/[controller]")]
 [ApiController]
+[Authorize("Tracks")]
 public class TracksController : ControllerBase
 {
 	private readonly IFileStorage _fileStorage;

+ 1 - 0
src/RunnersMeet.Server/RunnersMeet.Server.csproj

@@ -9,6 +9,7 @@
 
     <ItemGroup>
         <PackageReference Include="LiteDB" Version="5.0.15" />
+        <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.1" />
         <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.1" />
         <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
     </ItemGroup>

+ 7 - 0
src/RunnersMeet.Server/appsettings.json

@@ -6,6 +6,13 @@
 		}
 	},
 	"AllowedHosts": "*",
+	"Auth":{
+		"Authority": "https://dev-2ls6voifhbt37usw.eu.auth0.com/",
+		"Audience": "https://runners.larcanum.net",
+		"PolicyClaims": {
+			"Tracks": ["manage:tracks"]
+		}
+	},
 	"Persistence": {
 		"DataFilePath": "./data/tracks.db",
 		"FileStorageRootPath": "./data/files"