Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of Hangfire authorization using token from navlink #270

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/Client/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
@inject Microsoft.Extensions.Localization.IStringLocalizer<NavMenu> _localizer
@using System.Security.Claims
@using BlazorHero.CleanArchitecture.Shared.Constants.Storage

<UserCard />
<MudNavMenu>
<MudNavLink Href="/" Match="NavLinkMatch.All" Icon="@Icons.Material.Outlined.Home">@_localizer["Home"]</MudNavLink>
@if (_canViewHangfire)
{
<MudNavLink Href="/jobs" Target="_blank" Icon="@Icons.Material.Outlined.Work">
<MudNavLink Href="@_jobsLink" Target="_blank" Icon="@Icons.Material.Outlined.Work">
@_localizer["Hangfire"]
</MudNavLink>
}
Expand Down Expand Up @@ -102,6 +103,10 @@
private bool _canViewProducts;
private bool _canViewBrands;

// example of authorization using token from navlink
private string _accessToken;
private string _jobsLink;

protected override async Task OnParametersSetAsync()
{
_authenticationStateProviderUser = await _stateProvider.GetAuthenticationStateProviderUserAsync();
Expand All @@ -115,5 +120,8 @@
_canViewChat = (await _authorizationService.AuthorizeAsync(_authenticationStateProviderUser, Permissions.Communication.Chat)).Succeeded;
_canViewProducts = (await _authorizationService.AuthorizeAsync(_authenticationStateProviderUser, Permissions.Products.View)).Succeeded;
_canViewBrands = (await _authorizationService.AuthorizeAsync(_authenticationStateProviderUser, Permissions.Brands.View)).Succeeded;

_accessToken = await _localStorage.GetItemAsync<string>(StorageConstants.Local.AuthToken);
_jobsLink = $"/jobs?token={_accessToken}";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it safe to pass a token in a query string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The token is exposed in the header of any call, so is more or less the same as exposing it in the query string.

}
}
50 changes: 48 additions & 2 deletions src/Server/Filters/HangfireAuthorizationFilter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
using Hangfire.Dashboard;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using BlazorHero.CleanArchitecture.Shared.Constants.Permission;
using Hangfire.Dashboard;
using Microsoft.AspNetCore.Http;

namespace BlazorHero.CleanArchitecture.Server.Filters
{
Expand All @@ -14,7 +19,48 @@ public bool Authorize(DashboardContext context)
//return httpContext.User.Identity.IsAuthenticated;
//return httpContext.User.IsInRole(Permissions.Hangfire.View);

return true;
// example of authorization using token from navlink
var httpContext = context.GetHttpContext();

string jwtToken;
bool readFromCookie = false;

bool readFromQuery = httpContext.Request.Query.TryGetValue("token", out var jwtTokenFromQuery);

if (readFromQuery)
{
jwtToken = jwtTokenFromQuery.ToString();
}
else
{
readFromCookie = httpContext.Request.Cookies.TryGetValue("token", out jwtToken);
}

if (!readFromCookie && !readFromQuery) return false;

var handler = new JwtSecurityTokenHandler();
var token = handler.ReadJwtToken(jwtToken);
if (token is null) return false;

var expirationTime = token.ValidTo;

if (DateTime.Now > expirationTime) return false;

if (readFromQuery)
{
CookieOptions options = new CookieOptions
{
Expires = expirationTime
};
httpContext.Response.Cookies.Append("token", jwtToken, options);
}

var hangfireViewPermission =
token.Claims.Any(w => w.Value.Equals(Permissions.Hangfire.View));

return hangfireViewPermission;

// return true;
}
}
}