Last active
December 5, 2021 00:20
-
-
Save vertonghenb/65fe177b04f13037c83e745fefa123a9 to your computer and use it in GitHub Desktop.
Blazor Authorization with Auth0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@page "/add-weather" | |
@using WeatherStation.Shared | |
@inject HttpClient Http | |
@inject NavigationManager NavigationManager | |
@attribute [Authorize(Roles ="Administrator")] | |
<PageTitle>Add Weather Data</PageTitle> | |
<h3>Add Weather Data</h3> | |
<EditForm Model="forecast" OnValidSubmit="Add"> | |
<div class="form-group"> | |
<label>Date</label> | |
<InputDate class="form-control" @bind-Value="forecast.Date" /> | |
</div> | |
<div class="form-group"> | |
<label>Temperature (C)</label> | |
<InputNumber class="form-control" @bind-Value="forecast.TemperatureC" /> | |
</div> | |
<div class="form-group"> | |
<label>Summary</label> | |
<InputSelect class="form-control" @bind-Value="forecast.Summary"> | |
<option value="">Select</option> | |
<option value="Freezing">Freezing</option> | |
<option value="Bracing">Bracing</option> | |
<option value="Chilly">Chilly</option> | |
<option value="Cool">Cool</option> | |
<option value="Mild">Mild</option> | |
<option value="Warm">Warm</option> | |
<option value="Balmy">Balmy</option> | |
<option value="Hot">Hot</option> | |
<option value="Sweltering">Sweltering</option> | |
<option value="Scorching">Scorching</option> | |
</InputSelect> | |
</div> | |
<button class="btn btn-primary mt-2" type="submit">Add Weather</button> | |
</EditForm> | |
@code { | |
private WeatherForecast forecast = new(); | |
protected override void OnInitialized() | |
{ | |
base.OnInitialized(); | |
forecast.Date = DateTime.Now; | |
} | |
private async Task Add() | |
{ | |
var response = await Http.PostAsJsonAsync<WeatherForecast>("WeatherForecast",forecast); | |
response.EnsureSuccessStatusCode(); | |
NavigationManager.NavigateTo("fetchdata"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; | |
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal; | |
using System.Security.Claims; | |
using System.Text.Json; | |
namespace WeatherStation.Client.Shared; | |
public class ArrayClaimsPrincipalFactory<TAccount> : AccountClaimsPrincipalFactory<TAccount> where TAccount : RemoteUserAccount | |
{ | |
public ArrayClaimsPrincipalFactory(IAccessTokenProviderAccessor accessor) | |
: base(accessor) | |
{ } | |
// when a user belongs to multiple roles, Auth0 returns a single claim with a serialised array of values | |
// this class improves the original factory by deserializing the claims in the correct way | |
public async override ValueTask<ClaimsPrincipal> CreateUserAsync(TAccount account, RemoteAuthenticationUserOptions options) | |
{ | |
var user = await base.CreateUserAsync(account, options); | |
var claimsIdentity = (ClaimsIdentity)user.Identity; | |
if (account != null) | |
{ | |
foreach (var kvp in account.AdditionalProperties) | |
{ | |
var name = kvp.Key; | |
var value = kvp.Value; | |
if (value != null && | |
value is JsonElement element && element.ValueKind == JsonValueKind.Array) | |
{ | |
claimsIdentity.RemoveClaim(claimsIdentity.FindFirst(kvp.Key)); | |
var claims = element.EnumerateArray() | |
.Select(x => new Claim(kvp.Key, x.ToString())); | |
claimsIdentity.AddClaims(claims); | |
} | |
} | |
} | |
return user; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@page "/" | |
<PageTitle>Index</PageTitle> | |
<AuthorizeView> | |
<Authorized> | |
@foreach (var claim in context.User.Claims) | |
{ | |
<p>@claim.Type - @claim.Value</p> | |
} | |
</Authorized> | |
<NotAuthorized> | |
Please login to see all the claims, <a href="authentication/login">Log in</a> | |
</NotAuthorized> | |
</AuthorizeView> | |
<AuthorizeView Roles="Administrator"> | |
Only Administrators can see this. | |
</AuthorizeView> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @param {Event} event - Details about the user and the context in which they are logging in. | |
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login. | |
*/ | |
exports.onExecutePostLogin = async (event, api) => { | |
const claimName = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role' | |
if (event.authorization) { | |
api.idToken.setCustomClaim(claimName, event.authorization.roles); | |
api.accessToken.setCustomClaim(claimName, event.authorization.roles); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Components.Web; | |
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; | |
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; | |
using WeatherStation.Client; | |
using WeatherStation.Client.Shared; | |
var builder = WebAssemblyHostBuilder.CreateDefault(args); | |
builder.RootComponents.Add<App>("#app"); | |
builder.RootComponents.Add<HeadOutlet>("head::after"); | |
builder.Services.AddHttpClient("WeatherAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)) | |
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>(); | |
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>() | |
.CreateClient("WeatherAPI")); | |
builder.Services.AddOidcAuthentication(options => | |
{ | |
builder.Configuration.Bind("Auth0", options.ProviderOptions); | |
options.ProviderOptions.ResponseType = "code"; | |
options.ProviderOptions.AdditionalProviderParameters.Add("audience", builder.Configuration["Auth0:Audience"]); | |
}).AddAccountClaimsPrincipalFactory<ArrayClaimsPrincipalFactory<RemoteUserAccount>>(); // 👈 | |
await builder.Build().RunAsync(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Authorization; | |
using Microsoft.AspNetCore.Mvc; | |
using WeatherStation.Shared; | |
namespace WeatherStation.Server.Controllers; | |
[ApiController] | |
[Route("[controller]")] | |
[Authorize] | |
public class WeatherForecastController : ControllerBase | |
{ | |
private static readonly string[] Summaries = new[] | |
{ | |
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" | |
}; | |
private static readonly List<WeatherForecast> forecasts = new(); | |
static WeatherForecastController() | |
{ | |
forecasts.AddRange(Enumerable.Range(1, 5).Select(index => new WeatherForecast | |
{ | |
Date = DateTime.Now.AddDays(index), | |
TemperatureC = Random.Shared.Next(-20, 55), | |
Summary = Summaries[Random.Shared.Next(Summaries.Length)] | |
})); | |
} | |
[HttpGet] | |
public IEnumerable<WeatherForecast> GetForecasts() | |
{ | |
return forecasts; | |
} | |
[HttpPost] | |
[Authorize(Roles = "Administrator")] // 👈 | |
public WeatherForecast CreateForecast(WeatherForecast forecast) | |
{ | |
forecasts.Add(forecast); | |
return forecast; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment